2014-08-30 8 views
9

Ich las Effective Java Kapitel 5 über Generika, insbesondere die Elemente auf bevorzugte generische Methoden. Mir ist aufgefallen, dass manchmal der Typ-Parameter (zwischen spitzen Klammern) in der Methodendeklaration vor dem Rückgabetyp manchmal weggelassen wird. Es gibt viele Fälle so, aber zum Beispiel auf Seite 135 der zweiten Auflage:Warum sind die spitzen Klammern vor dem Rückgabetyp manchmal aus der Definition einer generischen Methode

public void popAll(Collection<E> dst) { 
while (!isEmpty()) 
dst.add(pop()); 
} 

Auf der anderen Seite habe ich ähnliche generische Methoden mit der Erklärung

Ist die erste gesehen ein Tippfehler? Wenn nicht, wann kann ich die Klammern aus der Deklaration weglassen?

Dank

+0

Ich bin mir nicht sicher, warum dies als ein Duplikat gekennzeichnet wurde. Der angebliche Betrogene ist eine ganz andere Frage. –

+5

Da ich keine legitime Antwort posten kann, werde ich mit einem Kommentar antworten: Ich glaube der Unterschied ist, dass im ersten Fall die ganze Klasse als generisch deklariert wird, während im zweiten Fall nur die Methode generisch ist. –

+0

Gewählt, um wieder zu öffnen. Ich konnte es aus der anderen Frage nicht herausfinden. Die scheinen verwandt zu sein, aber nicht doppelt. –

Antwort

5

E ist eine Variable vom Typ - es steht für eine andere Art in, wie String oder Integer. So wie Sie dst.add(pop()) nicht verstehen können, ohne zu wissen, wo und wie dst definiert wurde, können Sie eine Methodendeklaration wie popAll(Collection<E> dst) nicht verstehen, ohne zu wissen, wo und wie die Typvariable E definiert ist. Bei popAll ist die Typvariable E auf der Klassenebene definiert: Stack<E>: Es ist der Typ der Elemente im Stapel. Sie werden oft sogar sehen es javadoc'd:

/**A Stack of elements 
    * 
    *@param E The type of elements in the stack */ 
public class Stack<E>{ 
    public void popAll(Collection<E> dst){ ... } 
} 

Auf der anderen Seite, wenn Sie eine Methode Erklärung wie public <E> void ... sehen, die Art Variable E wird erklärt (nicht von einem umschließenden Umfang verwiesen wie die umschließende Klasse). In den meisten Fällen, wenn Sie eine Methode mit einer eigenen Typvariablen sehen, handelt es sich um eine statische Methode. Daher gibt es keine umschließende Instanz der Klasse, um den Wert E festzulegen.

In beiden Fällen, was macht die E Variable? Es sagt uns, wie zwei verschiedene Typen miteinander in Beziehung stehen müssen. In popAll teilt es uns mit, dass der Elementtyp der Sammlung, in die die popped-Elemente eingefügt werden sollen, dem Elementtyp des Stapels entsprechen muss, aus dem Sie die Popup-Elemente auswählen.

In ähnlicher Weise nehmen Sie das Beispiel von Seite 136:

public class ListUtils{ 
    public static <E> E reduce(List<E> list, Function<E> f, E initVal); 
} 

Hier ist die E Variable vom Typ sagt uns, dass der Elementtyp von list hat das Argument Art von f und die Art der initVal anzupassen. Die umgebende Klasse definiert E für uns nicht, sie ist nur im Rahmen der Methodenklaration reduce sinnvoll.

5

Der Unterschied besteht darin, dass die ganze Klasse im ersten Fall generic deklariert wird im zweiten Fall während nur die Methode generisch ist.

1

Die Antwort ist ... es ist nicht. Eine „generische Methode“ ist definiert sein, die Variablen eingeben, bevor der Rückgabetyp deklariert:

Verfahren sind generic wenn es eine oder mehr Variablen vom Typ deklariert.(JLS 8.4.4)

ist daher keine "generische Methode".

Da die Methode den Typparameter E nicht deklariert, muss sie in einem umschließenden Bereich definiert werden; fast sicher durch die Klasse (eine "generische Klasse"), die die Methode enthält.

Verwandte Themen