2009-03-29 32 views
7

ich auf eine Funktion gestolpert wie folgt aussehen:<?> vs <T>

public void function(Class<?> clazz) {...} 

Was sind die Vor/Nachteile der Methode zu ändern, was sind die Kompilierung/Laufzeit diff.

Antwort

7

todd.run ist völlig richtig, aber das ist nur die halbe Antwort. Es gibt auch Anwendungsfälle für die Auswahl von <T> über <?> (oder umgekehrt), die gelten, wenn Sie der Klasse, die die Methode einschließt, keinen Typparameter hinzufügen. Betrachten wir zum Beispiel den Unterschied zwischen

public <E extends JLabel> boolean add(List<E> j) { 
    boolean t = true; 
    for (JLabel b : j) { 
     if (b instanceof JLabel) { 
      t = t && labels.add(b); 
     } 
    } 
    return t; 
} 

und

public boolean add(List<? extends JLabel> j) { 
    boolean t = true; 
    for (JLabel b : j) { 
     if (b instanceof JLabel) { 
      t = t && labels.add(b); 
     } 
    } 
    return t; 
} 

Die erste Methode wird kompilieren eigentlich nicht, wenn Sie einen geeigneten Typ Parameter an die umgebenden Klasse hinzufügen, während die zweite Methode unabhängig von kompilieren, ob Die einschließende Klasse hat einen Typparameter. Wenn Sie nicht <?> verwenden, dann sind Sie örtlich dafür verantwortlich, dem Compiler mitzuteilen, wie er den Typ erhält, der durch den an seiner Stelle verwendeten Buchstaben ausgefüllt wird. Sie stoßen häufig auf dieses Problem - müssen Sie verwenden? eher als T - beim Versuch, generische Methoden zu schreiben, die "extends" und "super" verwenden oder benötigen. Eine bessere, aber ausführlichere Behandlung dieses Problems finden Sie auf Seite 18 von Gilad Bracha's Generics Tutorial (PDF). Siehe auch this stack overflow question, deren Antwort diese Probleme beleuchtet.

Überprüfen Sie diesen Stack-Überlauf-Link für Informationen über Ihre zweite Frage: Java generics - type erasure - when and what happens. Während ich die Antwort auf Ihre Frage über den Kompilierzeitunterschied zwischen <?> und <T> nicht kenne, bin ich mir ziemlich sicher, dass die Antwort bei this FAQ gefunden werden kann, die erickson in diesem Beitrag erwähnte.

+0

Sie können den Platzhalter in diesem Fall erfassen: boolean add (List list) {return addImpl (list); } boolean addImpl (Liste Liste) {... –

+0

(Der Beispielcode ist ein bisschen seltsam. Sie könnten zurückgeben, nachdem labels.add false zurückgibt. –

+0

Diese Antwort ergibt keinen Sinn und ist nicht korrekt. Ich lege die erste Methode in eine Klasse ohne Typparameter ('public class test {Liste labels = new ArrayList (); // addiere Methode hier}') und es kompiliert fein. – user102008

2

Grundsätzlich sind sie gleichwertig. Sie können die erste Syntax verwenden, in der Sie nichts vom Typ T deklarieren müssen.

UPDATE: oh, und T kann verwendet werden, um Typen zusammen zu binden: wenn Class<T> in verschiedenen Teilen der Funktion verwendet wird, wird es sich beziehen zu derselben Klasse, aber nicht Class<?>.

+0

Das ist jedoch nicht richtig in Situationen, in denen es mehrere Vorkommen von / in einer Methodensignatur. – dmeister

+0

Nein.In diesem Fall ist ein methodenspezifischer Typparameter und bezieht sich daher nicht auf denselben Typ wie auf Klassenebene, auch wenn er T genannt wird. –

+0

@Saua: niemand spricht über die Klassenstufe –

10

Verwendung von "?" ist das gleiche wie "any", während "T" "ein bestimmter Typ" bedeutet. Also, vergleichen diese Schnittstellen:

public interface StrictClass<T> { 
public T doFunction(Class<T> class); 
} 

public interface EasyClass<T> { 
public > doFunction(Class<?> class); 
} 

Jetzt können wir Klassen erstellen:

public class MyStrictClass implements StrictClass<String> { 
    public String doFunction(Class<String> stringClass) { 
    //do something here that returns String 
    } 
} 

public class MyEasyClass implements EasyClass<String> { 
    public String doFunction(Class<?> anyClass) { 
    //do something here that returns String 
    } 
} 

Hoffnung, das hilft!

+0

"öffentliche DOFunction" ist falsch und sollte nicht einmal kompilieren. Ich nehme an, Sie meinten, es sei "öffentliche T-Funktion". –

+0

"Klasse" kann auch nicht als Variablenname verwendet werden, da es sich um ein reserviertes Wort handelt. –