2009-03-29 6 views
7

je suis tombé sur une fonction qui ressemble à ceci:<?> vs <T>

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

Quels sont les avantages/inconvénients de changer la méthode:

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

modifier: quels sont les temps de compilation/exécution diff.

Répondre

7

todd.run est totalement à droite, mais ce n'est que la moitié de la réponse. Il existe également des cas d'utilisation pour choisir <T> sur <?> (ou vice versa) qui s'appliquent lorsque vous n'ajoutez pas de paramètre de type à la classe qui contient la méthode. Par exemple, considérez la différence entre

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

et

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

La première méthode fait pas compiler SAUF si vous ajoutez un paramètre de type approprié à la classe englobante, tandis que la seconde méthode compilerons indépendamment du fait que la classe englobante a un paramètre de type. Si vous n'utilisez pas <?>, alors vous êtes localement responsable de dire au compilateur comment acquérir le type qui sera rempli par la lettre utilisée à sa place. Vous rencontrez fréquemment ce problème - besoin d'utiliser? plutôt que T - lorsque vous essayez d'écrire des méthodes génériques qui utilisent ou nécessitent "étend" et "super". Un traitement meilleur mais plus élaboré de ce problème est à la page 18 de Gilad Bracha's Generics Tutorial (PDF). Voir aussi this stack overflow question dont la réponse éclaire ces problèmes.

Consultez ce lien de débordement de pile pour plus d'informations sur votre deuxième question: Java generics - type erasure - when and what happens. Bien que je ne connais pas la réponse à votre question sur la différence de temps de compilation entre <?> et <T>, je suis assez sûr que la réponse peut être trouvée à this FAQ que erickson mentionné dans ce post.

+0

Vous pouvez capturer le type générique dans ce cas: boolean add (liste list) {return addImpl (list); } boolean addImpl (Liste list) {... –

+0

(L'exemple de code est un peu étrange Vous pourriez revenir après que labels.add retourne false –

+0

Cette réponse n'a pas de sens et n'est pas correcte. Je mets la première méthode dans une classe sans paramètre de type ('public class test {Liste labels = new ArrayList (); // ajoute la méthode ici}') et compile bien. – user102008

2

Fondamentalement, ils sont équivalents. Vous pouvez utiliser la première syntaxe où vous n'avez pas besoin de déclarer quoi que ce soit de type T.

MISE À JOUR: oh, et T peut être utilisé pour lier les types ensemble: si Class<T> est utilisé dans différentes parties de la fonction, il se référera à la même classe, mais pas Class<?>.

+0

Cependant, ce n'est pas correct dans des situations où il y a plusieurs occurences de / dans une signature de la méthode. – dmeister

+0

Non.Dans ce cas, est un paramètre de type spécifique à une méthode, donc il ne se référera pas au même type que celui utilisé au niveau de la classe, même s'il s'appelle T. –

+0

@saua: personne ne parle du niveau de la classe –

10

L'utilisation de "?" est identique à "any", alors que "T" signifie "un type spécifique". Donc, comparer ces interfaces:

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

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

Maintenant, nous pouvons créer des classes:

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 
    } 
} 

Hope that helps!

+0

"public doFunction" est incorrect et ne devrait même pas être compilé. Je suppose que vous vouliez dire que c'était "public T doFunction". –

+0

De plus, "class" ne peut pas être utilisé comme nom de variable, car il s'agit d'un mot réservé. –

Questions connexes