I have a class that is extending Java's ArrayList. I'm currently using Java build 1.6.0_22-b04. Looks like this:
public class TokenSequence extends ArrayList<Token>{
public TokenSequence (Collection<Token> tokens) {
super(tokens);
}
public void add(Object o) {
if (o instanceof Token){
add( (Token)o );
}
else if (o instanceof TokenSequence)
add( (TokenSequence)o );
else
add( new Token( o.toString() ) );
}
}
My problem in the above code is the add(Object o) method. Java won't let me compile the code because it says
"Name clash: The method add(Object) of type TokenSequence has the same erasure as add(E) of type ArrayList<E> but does not override it"
This same code works with no problems in another computer under Java build 1.6.0_17-b04.
Anyone has any idea on a quick fix?
Try adding the #Override annotation to your add() method and make sure to have the same signature (boolean return type)
public class TokenSequence extends ArrayList<Object> {
#Override
public boolean add(Object e) {
return super.add(e);
}
}
Or if you want it to be void, take another method param.
cheers
Change it to public boolean add(Token o). (Note return and parameter type)
In order to override a method, your override must have the exact same signature, including the return type.
Since your method has a different return type, it doesn't actually override the base add method.
The reason that it won't even compile is that because it doesn't override the base method, you end up with two different add methods, both of which are callable by your derived class.
However, due to type erasure, they both actually take an Object parameter, which is illegal.
Absolutely - use the #Override annotation, and ideally use the strongly typed signature:
#Override
public void add(Token token) {
...
}
The error message already provided a large hint here.
I haven't tried it, but I believe the correct implementation would be:
public void add(Token o) {
}
because Token is the E in your extends statement.
You need to do:
public boolean add(Token o) {
}
Because ArrayList is a generic.
First of all, in the current implementation it will go to infinite recursion when you will try to call add function with instance of TokenSequence. Did you mean to call "addAll" in that case?
Second, forget about
void add(Object)
in you case you need to add 2 methods (make them return boolean, if you want to be consistent):
public void add(String o) {
add(new Token(o.toString()));
}
public void add(TokenSequence t){
addAll(t);
}
and the add(Token) is already implemented by ArrayList
on the other hand, if you want a single method, you can declare, for example:
public void add(Serializable t)
this method will be called for both TokenSequence and String.
unfortunately to make the same method executed for Token (as oppose to the one provided by ArrayList), you will need:
make sure Token implements Serializable
cast Token to serializable
i.e:
add((Serializable)new Token())
create a custom ArrayList class and override the add the method as follows
public class CustomArrayList<E> extends ArrayList<E>{
#Override
public boolean add(E e) {
String temp = (String)e;
if(temp==null || temp.isEmpty()){
return false;
}
return super.add(e);
}
}
with this class, following example will add only 1 element and print size as 1
public static void main(String args[]) {
ArrayList<String> lst = new CustomArrayList<String>();
lst.add("aaaa");
lst.add(null);
lst.add("");
System.out.println(lst.size());
}
Related
I'm looking to implement a generic search function to basically look if a mouse click is within one of several list of rectangles (of varying types, all children of G3_gRect). When nothing is found, it should return a new object of type T with a property defining it as being invalid (as opposed to other things that it could be).
This all works fine until I try to make it return the generic type T.
What can I do differently to make this work?
This breaks in the last line when trying to initialize a new object of type T. I assume because it doesn't know that it could always initialize that type.
private <T extends G3_gRect> T whatRect(MouseEvent e, List<List<T>> maps) {
while (!maps.isEmpty()) {
List<T> map = maps.remove(0);
for (T entry : map) {
if(entry.R.contains(e.getPoint())) return entry;
}
}
return new T(G2_gObj.ObjType.NONE); //return with empty object rather than null.
}
A few of the relevant parts of related classes:
public abstract class G2_gObj {
public enum ObjType {
FUNCTION, RIBBON, D_LINE, D_START, D_END, D_IN_AREA, C_IN_AREA, M_IN_AREA, D_OUT_AREA, M_OUT_AREA, NONE, C_OUT_AREA
}
public ObjType t;
public G2_gObj(ObjType t) {
this.t = t;
}
}
public class G3_gRect extends G2_gObj{
public G3_gRect(ObjType t) {
super(t);
}
}
public class G4_gFunct extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
public class G4_gDPoint extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
Right now my workaround is to pass in an object of type T into this method to return if nothing is found. It works, its fine, but I imagine there is a better way to actually make this work.
Thanks!
There's no way to construct an object without knowing its exact class. Barring the use of reflection, your only option would be to have the caller pass a default value, or to return null (which would avoid unnecessary object creation).
If you do want to use reflection (a questionable decision), you can have a parameter Class<T> clazz, and return
clazz.getConstructor(ObjType.class).newInstance(G2_gObj.ObjType.NONE)
I am sorry about putting the error directly as the title, but I couldn't find any better title.
I have an interface defined as following to be used as a blueprint for all my validator classes:
public interface Validator<T> {
public boolean validate(T item);
}
And then I have some classes that would implement it, lets say one of them is this:
public class EmptyStringValidator implements Validator<String> {
private final String _errorMessage;
public EmptyStringValidator() {
this("String cannot be empty.");
}
public EmptyStringValidator(String message) {
this._errorMessage = message;
}
#Override
public String getMessage() {
return this._errorMessage;
}
#Override
public boolean validate(String item) {
return gsi.application.core.Validation.isEmptyString(item);
}
}
I would like to put it all in an array and call it all in one loop. So this is the code I am using:
public List<Validator<? extends Object>> validators;
public FormItem<T> addValidator(Validator<? extends Object> validator) {
this.validators.add(validator);
return this;
}
public boolean validate() {
for (Validator<? extends Object> validator : this.validators)
if (!validator.validate(this.getInputValue())) {
this._errorMessage = validator.getMessage();
return false;
}
return true;
}
However, that code is giving an error at the validate() function, specifically at this part:
validator.validate(this.getInputValue())
It gives me the error that I have mentioned
The method validate(capture#2-of ? extends Object) in the type Validator<capture#2-of ? extends Object> is not applicable for the arguments (String)
which to my understanding doesn't makes sense. To my understanding <? extends Object> should accept anything that derives from the Object class, right?
Could anyone point out what am I doing wrong or point me at the right direction?
Thanks.
As an aside, ? extends Object is no different from saying ?. That isn't the root of your problem, however.
The issue is that validators is a List<Validator<? extends Object>>. In other words, each element can be any kind of Validator<T>, not necessarily a Validator<String>. So you can put a Validator<String> into it, but when you pull an element out you don't know what kind of Validator it is, and so you don't know if it is compatible with the type returned by this.getInputValue().
The simplest fix would be to specify a concrete type (eg: String) for the type parameter. A more complicated fix would be to use a type variable in place of ? extends Object, and have getInputValue()'s type signature use that same type variable. You need to constrain the types such that getInputValue()'s return type is assignable to the parameter of validate().
An even better type for collected validators generally is Validator<? super T>, where T is the input type, in this case String.
This way addValidator(Validator<? super String> validator) accepts Validator<String> but also Validator<CharSequence> and Validator<Object>.
For example:
class LongerThan10 implements Validator<CharSequence> {
#Override
public boolean validate(CharSequence item) {
return item.length() > 10;
}
}
formItem.addValidator(str -> !str.isBlank())
formItem.addValidator(new LongerThan10());
In this specific case it makes not much sense, but it is a good idea to accept validators that work with super types generally.
Objective: What I need is to create a function or functions to handle different types of List parameter, and I will be iterating through the list in the function.
Attempts:
1- Multiple functions with different type of List
public static int update(List<MyClass> myClasses){};
public static int update(List<Project> rojects){};
public static int update(List<Time> times){};
But that deemed to be in-compilable as due to multiple functions with same parameter type List.
2- Generic type of list, and using (instanceof) However, I failed to completely do this as I am not sure how, and as much as I read, this seems to be an unfavorable way of such action.
My question: what is the Java way of implementing such requirement? I need a clean code, I don't care if it is complicated, I care mostly about accuracy and proper coding.
PS: if the instanceof the correct way, then would you please provide me with a small example on how to iterate the list with the different types.
Thanks in advance :)
EDIT: The different objects have no relation with each other, as in, they do not extend each other nor do they extend a super class. The blocks of each function are generating an SQLite statements which would be different for each type.
Respond to 'harsh's answer:
So I ended up using a combination of your suggestions, and that is to implement a base class with a function of getClassType() which returns a string of the class name, then I would check the returned value in the update(List<T> list) function.
public static <T extends Item> int update(List<T> list){
...
// Loop through the list and call the update function
for (T item: list){
if (item.getClassType() == MyClass.CLASS_TYPE)
update((MyClass) item);
}
...
}
public interface Item {
/**
* #return Return the class type, which is the name of the class
*/
public String getClassType();
}
public class ClassProject implements Item{
public static final String CLASS_TYPE = "ClassProject";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class ClassTime implements Item{
public static final String CLASS_TYPE = "ClassTime";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class MyClass implements Item{
public static final String CLASS_TYPE = "MyClass";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
Reason for doing this whole interface is because I don't like istanceof and not sure about it's performance and cost, so I attempted to make one of my own. Now is this a terrible way of doing this?
Can you do something like this:
public class Update<T>
{
public static int update(List<T> objects){};
}
OR
public static <T> int update(List<T> objects){};
whichever is more appropriate in your case.
So if you go by second approach and due to type erasure at runtime, you are left with instanceof checking:
public static <T> int update(List<T> objects){
for(T object : objects)
{
if(object.getClass().isInstance(Pair.class))
{
//do something
}else if(object.getClass().isInstance(Time.class))
{
}
}
return 0;
}
But that's doesn't look a good design, you can improve above by using a factory method:
static Handler getHandler(Class<?> handlerClass)
{
if(handlerClass.isInstance(Project.class))
{
//return ProjectHandler
}else if(handlerClass.isInstance(Time.class))
{
//return TimeHandler
}
//return errorHandler
}
interface Handler {
int handle();
}
public static <T> int update(List<T> objects){
for(T object : objects)
{
getHandler(object.getClass()).handle();
}
return 0;
}
Now a nicer approach IMO would be to designate your classes under update via marker interface and then cleanly handle update in each of the classes:
interface Updateable {
int update();
}
public static <T extends Updateable> int update2(List<T> objects){
for(T object : objects)
{
object.update();
}
return 0;
}
Based on your answer to my comment you are left with two approaches. The first would be to try to come up with an interface that all the possible types that would be passed to this method implement. If your interface was called Foo you could define the method as something like:
public int update(List<Foo> list)
Then your code inside would be based on the methods available in Foo.
If you can't do this then you will need separate methods per possible type. You can't do instanceof at runtime due to Type Erasure. The underlying type if the list is erased in the compiled code and therefor will not be available for instanceof logic.
EDIT:
To clear up a little confusion on my above answer. You can do instanceof on a per element basis when iterating the list, something like this:
for(Object item:list){
if (item instanceof A){
//do A based logic
}
else if (item instanceof B){
//do B based logic
}
}
You can't however check the list type at runtime like so:
if (list instanceof List<A>)
Your best bet really would be to try and generalize the types supported via an interface as suggested in my first solution. Doing the instanceof approach will lead to code that will constantly need to be modified as you add more supported types.
Expanding harsh's answer, can't you do:
public class Update
{
public static <T> int update(List<T> objects, Class<T> clazz){};
}
And then, in your implementation, vary behavior according to the passed Class instance?
I need to implement a bag data structure using the interface java.util.Collection.
I'm not asking for help on the actual implementation of the data structure. I just can't get my program to compile. I just want to get a blank implementation of the interface (with non functional signatures of the methods) to compile before I start actually implementing methods.
class Bag<T> implements java.util.Collection<T>
{
public void Collection () {
}
public boolean add(E e) {
}
public boolean addAll (Collection<? extends E> c) {
}
public void clear() {
}
public boolean contains(Object o) {
}
public boolean containsAll(Collection<?> c) {
}
public boolean equals(Object o) {
}
public int hashCode() {
}
public boolean isEmpty() {
}
public Interator<E> interator() {
}
public boolean remove(Object o) {
}
public boolean removeAll(Collection<?> c) {
}
public int size() {
}
public Object[] toArray() {
}
public <T> T[] toArray(T[] a) {
}
}
Compiler can't find class E in the parameters of methods like add. Am I supposed to define a class for E, or is there something I'm not understanding about what E actually is? Compiler says it can't find class Collection (in the parameters of methods like addAll) Do I import java.util.Collection or is there something else I should know? Compiler also has no idea about class Iterator and neither do I.
I know this is all probably elementary, but I could not find anything via Google, etc yesterday and my professor's lectures don't follow the projects at all. I'm lost on this one. Thanks for any help!
Edit: Also, I haven't searched as much on this but if someone could tell me anything useful about the "?"s such as public boolean addAll (Collection<? extends E> c) {}, that would be greatly appreciated.
Either use T or E as the type parameter, and then use it consistently throughout your class definition.
The Java documentation uses E, so you could for example change the first line to:
class Bag<E> implements java.util.Collection<E>
You will also need to either return values or throw an exception for those methods that don't return void.
public int size() {
throw UnsupportedOperationException();
}
E should be T, which is the generic type you are going to store. Your constructor should be for your class not the interface. Also you will need to add at least stubbed returns in your methods that have a return value, e.g. "return false" if the return is a boolean.
Hope this helps.
Try changing the import statement to import java.util.*;
Because you don't have E declared , use T instead and also you need to return wherever it is declared to return.
You are gonna have to do a lot of basic learning before you can implement an interface in JAVA. May be read "thinking in java" or something
In you program there are multiple problems
import of the Collection class is missing
no return statements are there in any of the methods
replace the E with T
Your generic parameter is called T and you're using E in your methods' implementations. If you go with T as the element type, update the method signatures.
It probably still won't compile without at least dummy implementations such as return null; or return false; in non-void methods.
The java.util.Iterator is an interface that describes a set of methods which allow you to iterate over the elements in your collection. You would return an instance of a class that implements that interface and its methods. YourListIterator will probably keep a reference or index to where in the list you are, return the corresponding element and move forward through the list.
Generics (including the use of ?) are discussed in this tutorial.
Today I stumbled upon something interesting.
Assume the following Java 6 class:
public class Ereasure {
public Object get(Object o) {
return null; // dummy
}
public static class Derived<T> extends Ereasure{
// (1)
#Override
public Object get(T o) {
return super.get(o);
}
// (2)
/*
#Override
public Object get(Object o) {
return super.get(o);
}*/
}
}
If you try to compile the above example, the compiler says
Ereasure.java:9: method does not override or implement a method from a supertype
#Override
If you remove the #Override annotation(which should not be necessary!), it says
Ereasure.java:8: name clash: get(T) in Ereasure.Derived and get(java.lang.Object) in Ereasure have the same erasure, yet neither overrides the other
This is a bit contradictional, since T should erease to Object and therefor override the parent classes get method.
If you leave (1) unannotated and uncomment (2) so (1) overloads (2) it would not work either.
Compiler output:
Ereasure.java:15: get(T) is already defined in Ereasure.Derived
public Object get(Object o) {
As a conclusion, T is being ereased to Object, but cannot override the parent get Method.
My question is now, why dooesn't at least one of the examples compile?
You can see in the example below why it is impossible to do what you want:
public class Erasure {
public void set(Object o) {
return;
}
// method overloading: (which is valid)
public void set(String s) {
return;
}
public static class Derived<S> extends Erasure {
// Oops... which one am I supposed to override?
// (It would actually be overloading if S was a concrete type
// that is neither Object nor String.)
#Override
public void set(S o) { // does not compile
super.set(o);
}
}
}
The solution to your problem is that Erasure should be a parameterized class.
At a simple guess the compiler does not use the generic view when calculating overloads which of course would not make sense, because sometimes T might be Object other times its another type. The overridding would then become dependent on a moving target T which is downright wrong, especially if there were multiple methods all called "get" but with different single parameter types. In such a case it just wouldnt make sense and at a guess they chose to just keep things simple.
Consider a case where you have both a getter and a setter overridden as generics.
Derived<String> d = new Derived<String();
Erasure e = d;
e.set(new Object());
String s = d.get(); //Class cast exception
The fundamental principal of generics is that a class cast exception can only happen if there is either (a) an explicit cast or (b) a warning. If you were allowed to do what you wanted, the above would throw an exception without either.