Platinum Partner
java,tips and tricks

A Strange case of Java Generic and Inheritage Parameter Passing

I came a cross some strange Java code and I would like to share it here. Take a look few of classes I have here:

// file: AFoo.java
package atest.deng;
public abstract class AFoo<T> {
}

// file: Foo.java
package atest.deng;
public class Foo extends AFoo<String> {
}

// file: FooProcessor.java
package atest.deng;
public class FooProcessor<T> {
    public void process(Class<AFoo<?>> cls) {
        System.out.println(cls);
    }
}

// file: FooMain.java
package atest.deng;
public class FooMain {
    public static void main(String[] args) {
        new FooProcessor().process(Foo.class);
    }
}


bash> mvn compile
bash> [INFO] BUILD SUCCESS

I tried this with JDK6 + Maven and it compiles without problem. But try to remove the <T> part from FooProcessor and it will fail to compile!

// file: FooProcessor.java
package atest.deng;
public class FooProcessor {
    public void process(Class<AFoo<?>> cls) {
        System.out.println(cls);
    }
}

bash> mvn clean compile
bash> [ERROR] java-demo\src\main\javatest\deng\FooMain.java:[4,26] process(java.lang.Class<atest.deng.AFoo<?>>) in atest.deng.FooProcessor cannot be applied to (java.lang.Class<atest.deng.Foo>)

With the <T> the code won't compile, and yet we are not even using it in this case. How and why <T> affects the method parameters invocation?

Now, we can improve the FooProcessor in this way so that the presence of <T> doesn't have any affect.

package atest.deng;
public class FooProcessor {
    public void process(Class<? extends AFoo<?>> cls) {
        System.out.println(cls);
    }
}

That's a more proper way to write the generic parameter anyway. But despite a better solution, the puzzle is that the original code compiled under the compiler, but only with the <T> presented, and yet it's not used. Wouldn't you consider this as a Java compiler bug?

Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}