1

I'm doing an experience, trying to override a Method of a Generic Class, in this way:

public class MyGenFun<T extends CharSequence> extends Do<String>{
    public void doX(T s){
        System.out.println("in CHILD");
    }

    public static void main (String ...a){
        MyGenFun<String> x = new MyGenFun<>();
        x.doX("Test");  /// LINE 1
    }
}

class Do<A>{

    public void doX(A a){
        System.out.println("in Super");
    }
}

Why I can't? The compile error is

yGenFun.java:15: error: reference to doX is ambiguous, both method doX(A) in Do and method doX(T) in MyGenFun match x.doX("Test"); ^ where A,T are type-variables: A extends Object declared in class Do T extends CharSequence declared in class MyGenFun 1 error

If I comment the "Line 1", I can compile the code. So I think I am overriding correctly.

Danielson
  • 2,459
  • 2
  • 25
  • 48
G Bisconcini
  • 704
  • 2
  • 6
  • 24

3 Answers3

4

This is because you are not actually overriding the method but just overloading it. To override, all argument types must match. So a correct override method would be

public void doX(String s) {       
}

T is something that extends CharSequence, which may be String but does not need to be String, it could for example be CharBuffer as well.

You instantiate the following:

MyGenFun<String> x = new MyGenFun<>();

So because you are not overriding this method but overloading it, there are now two methods with the same signature in the current context, one comes from the child class, one from the super class:

public void doX(String a) {
...
}
beosign
  • 423
  • 5
  • 10
  • The Type-erasure don't erase the doX(T) to doX(Object) in both super and child and become Override? – G Bisconcini Aug 02 '15 at 08:00
  • The compiler still checks the use of generics before generating the bytecode and erasing types: See [link] (http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens) – beosign Aug 02 '15 at 08:05
3

Having this class hierarchy, you have two overloaded methods with signatures:

public void doX(String s){

}

public void doX(CharSequence s){

}

When you pass a String to doX, the compiler cannot infer which of the two methods to invoke, because String is compatible with String and CharSequence at the same time.

So, you should rather override like this:

public class MyGenFun<T extends CharSequence> extends Do<T>{

    @Override
    public void doX(T s){
        System.out.println("in CHILD");
    }
}
Konstantin Yovkov
  • 59,030
  • 8
  • 92
  • 140
  • Thanks for the answer. But I can't figure out why this method was overloaded. The Type-Erasure don't erase the generic extends CharSequence> and on methods to only Object? And than, I get the method Override when both are do(Object) ? – G Bisconcini Aug 02 '15 at 07:56
  • The compiler still checks the use of generics before generating the bytecode and erasing types: See http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – beosign Aug 02 '15 at 08:04
  • @kocko: It is fine to have two methods, one with `CharSequence` and one with `String`. The most specific method gets called, so when calling `doX("string")`, the method with the `String` parameter will be called. – beosign Aug 02 '15 at 08:12
0

your method signature says that you need a parameter to pass , public void doX(T s);

so call like : x.doX("abc");
swapyonubuntu
  • 1,356
  • 2
  • 21
  • 31