Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unbounded wildcards with extends and super as parameters

Tags:

java

generics

Help me please to undestand why i can't call the testSuper() method? There is compile error:

The method testSuper(Group<? super BClass<?>>) in the type Group <BClass<String>> is not applicable for the arguments (Group<AClass<String>>)

But the testExtends() method OK. However, it looks the same.

class AClass<T> {}

class BClass<T> extends AClass<T> {}

class Group<T> {
    T name;
    public void testExtends(Group<? extends AClass<?>> value){} 
    public void testSuper(Group<? super BClass<?>> value){}
    public T getName(){return name;}
}

public class GenericTest {

    public static void GenericTestMethod(){

        Group<AClass<String>> instGrA = new Group<AClass<String>>();
        Group<BClass<String>> instGrB = new Group<BClass<String>>();

        //OK
        instGrA.testExtends(instGrB);

        //The method testSuper(Group<? super BClass<?>>) in the type Group <BClass<String>>
        //is not applicable for the arguments (Group<AClass<String>>)
        instGrB.testSuper(instGrA);

    }
}
like image 526
Vasily Karpenko Avatar asked Oct 19 '22 16:10

Vasily Karpenko


1 Answers

There is a difference between the calls.

In the call that compiles,

instGrA.testExtends(instGrB);

you pass a Group<BClass<String>> to a method that is expecting a Group<? extends AClass<?>>. That matches, because BClass<String> is a subtype of AClass<?>> -- BClass is a subclass of AClass, and String is a subtype of ?.

However, in the call that doesn't compile,

instGrB.testSuper(instGrA);

you pass a Group<AClass<String>> to a method that is expecting a Group<? super BClass<?>>. That doesn't match, because although AClass is the superclass of BClass, AClass<String> isn't a supertype of BClass<?>.

The wildcards inside the parameters for testExtends and testSuper are to blame here. Because you're assigning AClass and BClass to T in your instances, you can use them. I can get this to compile if we change the declarations of these methods in Group to use T:

public void testExtends(Group<? extends T> value){}
public void testSuper(Group<? super T> value){}
like image 77
rgettman Avatar answered Nov 04 '22 19:11

rgettman