2017-02-12 3 views
1

Der folgende Code kompiliert jedoch nicht, wenn ich f (Objekt) zu f (String) oder f (Integer) es kompiliert. Ich habe die anderen Beiträge über das Thema gelesen, aber ich verstehe es immer noch nicht, wie kommt der Compiler nicht, welche Methode zu verwenden ist (im Falle einer neuen Instanz A a = neue B();)Warum können überschreibende Methoden keinen Typparameter angeben, wenn die Methode "overriden" nicht funktioniert?

public class SampleTester { 
    public static class A { 
     public void f(int x) { System.out.print("1"); } 
     public void f(Object x) { System.out.print("2"); } 
    } 
    public static class B extends A { 
      public <T> void f(T x) { System.out.print("3"); } //compiler error 
    } 
    public static void main(String[] args) { 
     A a = new A(); 
     B b= new B(); 
     a.f(3); 
     a.f("foo"); 
     b.f(3); 
     b.f("foo"); 
    } 
} 

Wenn ich T x-Object t ändern es immer noch nicht kompilieren, so was ist der Unterschied? und außerdem, warum überschreibt es nicht nur die Funktion von A? . (Beide die gleiche Signatur nach Typ Löschung

+0

Ich bin nicht sicher, warum diese Frage abgelehnt wurde. Es scheint eine ziemlich gute Frage zu sein, IMO. – CKing

+0

Während ich nicht downvote, wäre eine offensichtliche Frage "Also, was ist die Fehlermeldung?" * Jede * Frage, die besagt, dass etwas nicht kompiliert wird (oder kompiliert, sondern eine Ausnahme auslöst), sollte die Fehlerdetails enthalten. –

Antwort

3

Die Klasse B erstreckt A und damit alle Methoden erbt, die in A vorliegen Dies bedeutet, dass B 3 Methoden erhalten wird:

public void f(int x) 
public void f(Object x) 
public <T> void f(T x) 

Das Problem ist, dass f(T x) wird durch Typen Löschung während der Kompilierung gehen und T mit Object ersetzt werden, so dass in einem doppelten Verfahren führt, da Sie bereits eine Methode, die ein Object Argument.

Um dies zu beheben, entfernen Sie entweder die Methode Object oder geben Sie eine obere Grenze für T an. (Beispiel T extends Number so dass T mit Number während Typ-Lösch ersetzt) ​​


Ihren Kommentar zu adressieren (was ich jetzt zu Ihrer Frage hinzugefügt haben):

public <T> void f(Object x) nicht kompilieren, weil es nicht ist eine gültige Überschreibung für public void f(Object x) von A.

Verfahren public <T> void f(Object x) zu der Unterklasse gehört und kann mit einer superlcass Referenz als a.<Integer>f(null); oder a.<String>f(null); genannt werden. Da überschriebene Methoden zur Laufzeit aufgelöst werden ABER Generics durchlaufen Typ-Löschvorgang zur Kompilierzeit selbst, gibt es keine Möglichkeit für den Compiler zu T mit Integer oder String zur Kompilierzeit zu ersetzen.

Es ist noch legal die Methoden zu umkehren, so dass Sie die Methode public <T> void f(Object x) in A und die Methode public void f(Object x) in B haben, da der Compiler alle notwendigen Informationen, um zu entscheiden hat, was <T> ersetzt werden sollte.

+0

Aber wenn ich T x zu Objekt t ändere, kompiliert es, also was ist der Unterschied? und warum wird die Funktion von A nicht einfach überschrieben? (beide haben die gleiche Signatur nach dem Typ löschen – DsCpp

+0

Es kompiliert hier nicht. Es sei denn, Sie entfernen auch aus der Methodensignatur. In diesem Fall überschreiben Sie einfach die Basismethode. –

+0

@DsCpp Meine vorherige Erklärung war unvollständig, da es einige angenommen tieferes Verständnis auf Ihrer Ebene. Bitte beachten Sie die Bearbeitung für eine klarere Erklärung. – CKing

Verwandte Themen