Frage

lief ich in eine Situation heute, wo Java nicht die Methode wurde Aufrufen ich erwartet hatte - Hier ist die minimale Testfall: (tut mir leid, das ersonnen scheint - das Szenario ‚realen Welt‘ ist wesentlich komplexer und Marken viel mehr Sinn von einem "warum zum Teufel würde Sie , die ?" Standpunkt.)

Ich bin speziell interessiert, warum dies geschieht, ich kümmere mich nicht um Redesign Vorschläge. Ich habe das Gefühl, das in Java Puzzlers ist, aber ich habe nicht meine Kopie praktisch.

Sehen Sie die spezifische Frage in beglückwünscht im Test .getValue () unter:

public class Ol2 {  

    public static void main(String[] args) {  
        Test<Integer> t = new Test<Integer>() {  
            protected Integer value() { return 5; }  
        };  

        System.out.println(t.getValue());  
    }  
}  


abstract class Test<T> {  
    protected abstract T value();  

    public String getValue() {  
        // Why does this always invoke makeString(Object)?  
        // The type of value() is available at compile-time.
        return Util.makeString(value());  
    }  
}  

class Util {  
    public static String makeString(Integer i){  
        return "int: "+i;  
    }  
    public static String makeString(Object o){  
        return "obj: "+o;  
    }  
} 

Die Ausgabe von diesem Code ist:

obj: 5
War es hilfreich?

Lösung

Nein, ist die Art des Wertes zum Zeitpunkt der Kompilierung nicht zur Verfügung. Beachten Sie, dass javac nur eine Kopie des Codes kompiliert wird für alle möglichen T-Shirts verwendet werden. Da die einzig mögliche Art für den Compiler in Ihrem getValue () verwenden Methode ist Gegenstand.

C ++ anders, weil es mehrere kompilierte Versionen des Codes schließlich schaffen wird je nach Bedarf.

Andere Tipps

Da die Entscheidung über das, was makeString() wird zur Compile-Zeit gemacht zu verwenden und auf der Grundlage der Tatsache, dass T könnte alles sein, muss die Object Version sein. Denk darüber nach. Wenn Sie Test<String> täte, würde es haben die Object Version nennen. Als solche werden alle Instanzen von Test<T> wird makeString(Object) verwenden.

Nun, wenn Sie tut so etwas wie:

public abstract class Test<T extends Integer> {
  ...
}

Dinge vielleicht anders.

Josh Blochs Effective Java hat eine ausgezeichnete Diskussion um die Verwirrung zu klären, die entsteht, weil der Versand vs außer Kraft gesetzt funktioniert anders überlastet (in einer Unterklasse) Methoden. Auswahl unter überlastet Methoden --- der Gegenstand dieser Frage --- bei der Kompilierung bestimmt wird; Auswahl unter außer Kraft gesetzt Methoden zur Laufzeit durchgeführt wird (und erhält daher die Kenntnis der spezifischen Art des Objekts.)

Das Buch ist viel klarer als mein Kommentar: Siehe "Artikel 41: Verwenden Sie eine Überlastung umsichtig"

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top