Problem overriding ArrayList add method

2020-05-03 11:28发布

问题:

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?

回答1:

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



回答2:

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.



回答3:

Absolutely - use the @Override annotation, and ideally use the strongly typed signature:

@Override
public void add(Token token) {
    ...
}


回答4:

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.



回答5:

You need to do:

 public boolean add(Token o) {
   }

Because ArrayList is a generic.



回答6:

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:

  1. make sure Token implements Serializable
  2. cast Token to serializable

i.e:

add((Serializable)new Token())


回答7:

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());
    }


标签: java jdk1.6