2016-08-16 3 views
0

Ich stimme zu, dass ohne die Klasse B die Ausgabe ist "1233", aber warum, wenn die Klasse B mit A den Code kompilieren nicht?Vererbung in Java und Generika

public class SomeClass { 

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

    public static void main(String[] args){ 
     A a=new A(); 
     B b=new B(); 
     a.f(3); 
     a.f("hello"); 
     b.f(3); 
     b.f("hello"); 
    } 
} 
+2

Was sagt Ihnen die Fehlermeldung? –

Antwort

1

Sie können die oben genannten Klassen wegen des Typenlöschungsproblems nicht kompilieren.

Die Methode, die Sie in Ihrer Basisklasse haben, ist generisch und entspricht f(Object x) in Ihrer Elternklasse. Dies geschieht zur Kompilierzeit.

public void f(Object x){} 
public <T> void f(T x){} 

Siehe this Oracle documentation über Typ Erasures.


Sie können jedoch int Verfahren halten und es wird kompilieren fein:

class A { 
     public void f(int x){ 
     System.out.print("1"); 
     } 
} 

public class B extends A 
{ 
     public <T> void f(T x){ 
     System.out.print("3"); 
     } 
} 
+1

Das ist nicht wahr. Entferne die Methode 'f (int x)' und es wird immer noch nicht kompiliert. – Codebender

0

Verfahren kann nur in abgeleiteten Klasse überschrieben werden, wenn die Argumentliste genau die gleichen sind wie die der überschriebenen Methode und Der Rückgabetyp sollte derselbe oder ein Untertyp des Rückgabetyps der überschriebenen Methode (in der übergeordneten Klasse) sein.

Sie können folgende Methode überschreiben

public <T> void f(T x) { 
      System.out.print("3"); 
     } 

Sie weitere Informationen finden Sie auf Overriding and Hiding Methods

0

Das Problem wegen der Methode f (String) ist nicht eindeutig für den Typ B in Someclass, können Sie es beheben wie dieses

public class SomeClass { 
    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 void f(Object x) { 
      System.out.print("3"); 
     } 
    } 

    public static void main(String[] args) { 
     A a = new A(); 
     B b = new B(); 
     a.f(3); 
     a.f("hello"); 
     b.f(3); 
     b.f("hello"); 
    } 
} 

Und wird arbeiten, hoffe, dass Hilfe.

3

Die Methodensignaturen führen zu einem Namenskonflikt, da zwei Methodensignaturen das Problem des Namenskonflikts haben, da die generische Methode den vorherigen nicht überschreibt. Nach type erasure haben beide die gleiche Signatur.

public <T> void f(T x){...} 
public void f(Object x){...} 

Methode, die in B deklariert wird, wird nicht das Überschreiben der Methode der A als Methode gesagt wird, wenn außer Kraft gesetzt werden,

JLS 8.4.8.1. Overriding (by Instance Methods)

eine Instanzmethode m C erklärt in oder geerbt von Klasse C, überschreibt von C eine andere Methode m A in Klasse A deklariert, wenn alle folgenden erfüllt sind:

  • A eine Superklasse von C. ist
  • C erben m A nicht.
  • Die Signatur von m C ist eine Untersignatur (§8.4.2) der Signatur von m A.
    ....

Hier finden Sie gültig und kompiliert fein,

public static class A { 

    public <T> void f(T x) { 
     System.out.print("3"); 
    } 
} 

public static class B extends A { 

    @Override 
    public void f(Object x) { 
     System.out.print("2"); 
    } 

} 
+0

Ist es richtig zu sagen, dass: Methode kann nicht durch generische Methode überschrieben werden (in anderen Worten Eltern können generische sein, aber nicht es ist der Nachkomme)? – tami

+0

@tami Nicht genau. Die gleiche Signatur wie die Basismethode ist ebenfalls gültig, und einige andere Signaturen sind auch im Falle einer generischen Methode gültig. –

+1

"Die gleiche Signatur wie die Basismethode ist auch gültig", bedeutet es, dass das Schreiben von "public void f (T x)" in beiden Klassen (A und B) korrekt ist? Ist es auch ein Override, wenn ich "public void f (int x)" (nicht nur "public void f (Objekt x)") setze? – tami

1

Java Generics Typ Löschung verwendet. javac wird Zusammenstoß, während

Lösung
public <T> void f(T x); 
public void f(Object x); 

Beide sind gleiche bezüglich javac Compiler.

andere example Hinzufügen:

class Test{ 
    void add(Set<Integer> ii){} 
    void add(Set<String> ss){} 
} 

This limitation is part of the language syntax, not the Java runtime itself. Essentially, this rule is intended to avoid conflicts in legacy code that still uses raw types.

Bitte auf die obige Antwort verweisen.