2016-04-07 10 views
0
class A<E>{ 

} 
class B<E> extends A{ 

} 

public class WildInDeclare<E>{ 
    public static void main(String[] args){ 
     A<Integer> obj = new B<Integer>(); 
    } 
} 

Wenn ich das obige Programm kompiliere, habe ich diesen Fehler erhalten.Vererbung mit Generics in Java

Note: WildInDeclare.java uses unchecked or unsafe operations. 
Note: Recompile with -Xlint:unchecked for details. 

Danach habe ich einfach ersetzen class B<E> extends A{-class B<E> extends A<E>{es funktioniert gut können Sie erklären, warum es erforderlich, wieder A<E> mit Codebeispiel Während Vererbung schreiben Bitte.

Das zweite Problem mit der Vererbung Ich konfrontiert. Ich aktualisiere den obigen Code mit dem folgenden Code.

class A<E>{ 
    public A(E o){ 

    } 
} 
class B<E> extends A{ 
    public B(){ 
     super(E); 
    } 
} 

public class WildInDeclare<E>{ 
    public static void main(String[] args){ 
     A<Integer> obj = new B<Integer>(); 
    } 
} 

Aber es ist nicht kompilieren warum? Ich habe den folgenden Fehler erhalten.

WildInDeclare.java:8: error: cannot find symbol 
       super(E); 
        ^
    symbol: variable E 
    location: class B<E> 
    where E is a type-variable: 
    E extends Object declared in class B 
Note: WildInDeclare.java uses unchecked or unsafe operations. 
Note: Recompile with -Xlint:unchecked for details. 
1 error 

Wie kann ich Parameter zur Elternklasse übergeben?

+0

Welche Compiler-Fehlermeldung erhalten Sie? –

+3

, weil Sie von 'A' erben, das ein Generikum in seiner Klassensignatur hat. Wenn Sie es auslassen, wird 'A' als Rawtype geerbt (wie sollte der Compiler automatisch für Sie entscheiden, dass das generische' E' für die Klasse 'B' auch als generisch für' A' verwendet werden soll)? – SomeJavaGuy

+0

@ OleV.V. Frage aktualisiert –

Antwort

1

können Sie erklären, warum es erforderlich, wieder auf eine

schreiben Da A eine generische Klasse, die einen Typ Parameter annimmt. Idealerweise könnten Sie nicht auf den Rohtyp A verweisen, Sie könnten nur auf A<String> oder A<Integer> oder A<Map<K, List<O>> usw. verweisen. Java ermöglicht die Verwendung des Rohtyps für die Abwärtskompatibilität, aber im Prinzip sollte es obligatorisch sein um den Parameter bereitzustellen.

Wenn Sie sagen, dass Klasse B erweitert A erweitert, müssen Sie noch sagen, welche Art von A es erweitert; d.h. was der generische Parameter ist. (Dies gilt nicht brauchen die gleichen wie B ‚s allgemeine Parameter zu sein - man könnte zum Beispiel definiert B<E> extends A<String> und das wäre konsistent.)

der folgende Code kompiliert ... nicht. Warum?

Dieser Code ist nur syntaktisch ungültig. Sie haben A 's Konstruktor definiert, um ein Objekt seines generischen Parametertyps zu übernehmen. Wenn Sie also super() vom Konstruktor B aufrufen, müssen Sie ein solches Objekt übergeben. E ist kein Objekt - es ist nur der Name für den generischen Parameter von B. So der Compiler ist richtig zu sagen "kann kein Symbol finden", gibt es nichts E im Bereich genannt.

Wenn Sie B wollte einen Eingabeparameter nehmen, die es geht nur um die Oberklassenkonstruktors, würde es in etwa so aussehen:

class B<E> extends A<E> { 
    public B(E e) { // this parameter could be called anything, doesn't have to be e 
     super(e); 
    } 
} 
+0

Wie wird der Konstruktor des Elternelements ohne den Parameter des Kindkonstruktors übergeben? 'super (3);' funktioniert auch nicht. –

+0

'super (3)' würde funktionieren ** wenn und nur wenn ** '3' eine Instanz des generischen Parameters' E' ist. Aber da dieser Parameter keine Grenzen hat, könnte er irgendein Typ sein, und so sagt der Compiler richtig, dass dies nicht konsistent ist. (Wenn Sie versuchen, eine 'B ' zu konstruieren, die somit eine Unterklasse von 'A ' ist, würden Sie versuchen, ein 'int' in einen Konstruktor zu übergeben, der eine' String' übernimmt. Im Allgemeinen mit unbeschränkten Parametern muss der Aufrufer aus diesem Grund den Konstruktorparameter angeben. –