2009-03-24 9 views
5

Ich habe den folgenden Code machen:kann nicht statisch Verweis auf allgemeine Unterklasse (Java)

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(); 
    } 
} 

Dieser Code gibt die folgende:

SuperClass: super 
SubClass: sub 
T: super 

Meine Frage ist: Warum nicht T .getName() gibt den Wert von SubClass.getName() zurück? Immerhin habe ich T == SubClass angegeben. Oder sind statische Funktionsaufrufe für generische Referenzen ungültig?

Vielen Dank im Voraus!

Antwort

13

Dies ist nicht nur ein Problem mit Generika.

Wenn Sie sagen:

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

Sie werden auch "super" erhalten. Es gibt keine "polymorphen" statischen Methoden.

In Ihrem Fall weiß der Compiler über T ist, dass es SuperClass erweitert, so dass es SuperClass.getName() aufrufen wird.

+0

Ok, das ist soweit klar. Aber wie kann ich dann die statische Methode SubClass.getName() von Dummy mit T aufrufen? Ich möchte viele weitere Unterklassen haben, bei denen Dummy getName() transparent aufrufen kann. – JeffreyHammansson

0

Wenn Sie die Klasse mit "new Dummy()" instanziiert haben, haben Sie den Standardkonstruktor aufgerufen, der eigentlich nichts setzt. Wenn die Druckmethode aufgerufen wurde, erkannte die VM, dass der Typ von T, wie in der Klassendeklaration deklariert, SuperClass ist. Es ruft dann die statische Methode für diese Klasse auf.

1

Im Gegensatz zu C++ Vorlagen, Java Generics Arbeit von Typ Löschung, so dass es nur eine Klasse für alle Werte von T erzeugt, und alle Verweise übersetzen T in dieser Klasse zum Supertyp T, in diesem Fall SuperClass zu geben, dann verwendet den virtuellen Versand, um die Varianz für Aufrufe von Objektmethoden bereitzustellen, und den statischen Versand an Aufrufe von statischen Methoden.

Also, wenn Sie Dummy<SubClass>.print() tun, wird der Compiler nicht ein globaler von T mit SubClass in Dummy ersetzen machen. Der Compiler prüft nur, ob die Verwendung von T als Argument oder Rückgabetyp in den Methoden DummySubClass ist. Es gibt keine Änderung an irgendeinem Code innerhalb Dummy, also wird die gleiche SuperClass statische Methode gerufen, was auch immer T ist.

Wenn Sie in einer generischen Klasse abhängig vom parametrisierten Typ ein unterschiedliches Verhalten wünschen, müssen Sie ein Objekt dieses Typs übergeben und eine virtuelle Methode verwenden oder die Klasse für den Typ übergeben und Reflektion verwenden.

Verwandte Themen