views:

1487

answers:

3

Hi, I have the following code:

class SuperClass {
    public static String getName() { return "super"; }
}

class SubClass extends SuperClass {
    public static String getName() { return "sub"; }
}

public class Dummy<T extends SuperClass> {
    public void print() {
        System.out.println("SuperClass: " + SuperClass.getName());
        System.out.println("SubClass: " + SubClass.getName());
        System.out.println("T: " + T.getName());
    }
    public static void main(String[] args) {
        new Dummy<SubClass>().print();
    }
}

This code outputs the following:

SuperClass: super
SubClass: sub
T: super

My question is: Why doesn't T.getName() return the value of SubClass.getName()? After all, I specified that T == SubClass. Or are static function calls invalid for generic references?

Thanks a lot in advance!

+10  A: 

This isn't just an issue about generics.

If you say:

SuperClass obj = new SubClass();
System.out.println(obj.getName());

you will also get "super". There are no "polymorphic" static methods.

In your case, all the compiler knows about T is that it extends SuperClass, so it will call SuperClass.getName().

Simon Nickerson
Ok, that's clear so far. But how can I then invoke the static method SubClass.getName() from Dummy using T? I would like to have many further subclasses with Dummy being able to invoke getName() transparently.
JeffreyHammansson
A: 

When you instanciated the class with "new Dummy()" you called the default constructor which doesn't actually set anything. When print method got called, the VM saw that the type of T, as declared in the class declaration, is SuperClass; It then calls the static method on this class.

Kurley
+1  A: 

Unlike C++ templates, Java generics work by type erasure, so it only generates one class for all values of T, and translates all references to type T in this class to the super type of T, in this case SuperClass, then uses virtual dispatch to provide the variance for calls to object methods, and static dispatch to calls to static methods.

So when you do Dummy<SubClass>.print(), the compiler does not make a global replace of T with SubClass in Dummy. All the compiler does is check that uses of T as an argument or return type in the methods of Dummy are SubClass. There's no change to any code inside Dummy, so the same SuperClass static method gets called whatever T is.

If you want different behaviour in a generic class depending on the parameterised type, you have pass an object of that type in and use a virtual method, or pass in the class for the type and use reflection.

Pete Kirkham