javagenericsbounded-wildcard

Confusion over Wildcard Arguments in Java


public class A {
    void meth1()
    {

    }
}
public class B extends A{
    void meth2()
    {

    }
}

public class generic_class<T extends A> {
    T var1;

    public void meth4(generic_class<? extends B> gc)
    {
        gc.var1.meth2();
    }
}

Here in the generic_class's meth4 I have declared a wildcard <? extends B>. As far as I know, generics don't exist at runtime, all the 'T's would get replaced by the upper bound that is 'A'. So var1 is of type 'A', then how come it is able to access the meth2() declared in B. As a super class it shouldnt have any idea about the attributes and methods of its derived class.


Solution

  • Looking into the bytecode can shed light on what's going on. (I had renamed class A to Base, B to Sub, generic_class to Test). This is what I see in the bytecode (using javap -c Test):

    Compiled from "Test.java"
    public class Test<T extends Base> {
      T var1;
    
      public Test();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public void meth4(Test<? extends Sub>);
        Code:
           0: aload_1
           1: getfield      #2                  // Field var1:LBase;
           4: checkcast     #3                  // class Sub
           7: invokevirtual #4                  // Method Sub.meth2:()V
          10: return
    }
    

    Occurrences of T are treated as Base. Then it is cast into Sub since that was the generic constraint of the method param and then the required method is invoked, thereby achieving the required functionality despite type erasure.