2009-10-13 5 views
0

Le titre dit tout: si j'ai une méthode java qui est générique dans T, puis-je trouver quelque chose à propos de T? En particulier, puis-je vérifier si T implémente une certaine interface ou étend une certaine classe?Dans la méthode générique <T> doSth (Liste <T> l), vérifiez si T implémente Comparable?

Je voudrais faire quelque chose comme

public <T> List<T> doSth(List<T> l) { 

    if(T extends Comparable) { 
    // do one thing 
    } else { 
    // do another 
    } 

    return l; 
} 

Tous les conseils?

Merci beaucoup,

Johannes

Répondre

4

Non - en raison de type erasure. Au moment de l'exécution, vous ne connaissez pas le type de T du tout.

Une option serait de spécifier le type comme un autre paramètre:

public <T> List<T> doSth(List<T> l, Class<T> clazz) { 
    if (Comparable.class.isAssignableFrom(clazz)) { 
     ... 
    } 
} 
+0

Ergh. Pourquoi apporter 'Class' dans ce ?? –

+0

@Tom: Parce qu'il répond à la question? Je sais avoir à fournir la classe est icky, mais il fait le travail ... –

1

oui, vous pouvez:

public <T> List<T> doSth(List<T> l) { 
    //You could also check every element, if there is a chance only some will be comparable 
    if (l.size() >0 && l.get(0) instanceof Comparable) { 
    // do one thing 
    } else { 
    // do another 
    } 

    return l; 
} 

Notez que vous vérifiez quel type les éléments dans "l" sont, PAS T - c'est la clé. Edit: Changement du code pour gérer le fait qu'il s'agissait d'une liste - j'avais manqué cela dans ma lecture originale.

+1

C'est faux pour deux raisons. 'l' est Liste donc ça ne va pas être comparable et ce n'est pas ce que l'OP veut. – ChssPly76

+0

-1: Vous avez manqué l beeing de type Liste et pas de type tangens

+0

@tangens - vous avez raison, j'ai corrigé ma solution pour le problème de liste. Toutes mes excuses pour avoir manqué cela - apparemment mon cerveau est en vacances aujourd'hui – aperkins

10

Il n'est pas clair si vous souhaitez effectuer la vérification à la compilation ou à l'exécution. Si vous voulez simplement vous assurer que le paramètre list transmis à la méthode contient certains types d'objets, redéfinissez T de manière appropriée.

Par exemple, pour faire en sorte que le compilateur permettra seulement List<Comparable> à passer à cette méthode, redéfinissez T comme:

public <T extends Comparable<? super T>> List<T> doSth(List<T> l) { 
    // Method body omitted 
} 

Vous pouvez alors utiliser la méthode-surcharge (au lieu d'une instruction if-else), pour s'assurer que le code correct est appelé pour toute valeur de T. Autrement dit, remplacer:

public <T> List<T> doSth(List<T> l) { 

    if(T extends Comparable) { 
     // do one thing 
    } else { 
     // do another 
    } 

    return null 
} 

avec ces:

public <T extends Comparable<? super T>> List<T> doSth(List<T> l) { 
    // do one thing 
    return null; 
} 

public <T> List<T> doSth(List<T> l, Class<T> clazz) { 
    // do another 
    return null; 
} 

Cependant, vous devez vous rappeler choisir la méthode surchargée pour appeler et vérification de type générique est la compilation que! Par exemple, le code suivant:

List<? extends Serializable> alist = new ArrayList<Integer>(); 
doSth(alist); 

se fait appeler la deuxième méthode doSth, car le paramètre de type de compilation (? extends Serializable) ne met pas en œuvre Comparable, même si le paramètre de type d'exécution (Integer) fait.

0

Vous pouvez faire un

public <T extends Comparable<T>> List<T> doSth(List<T> l) 

qui vous permettra d'utiliser l'interface Comparable sur les articles dans 'l'

0

bien pour vérifier le temps de compilation Don a déjà donné une réponse. Pour l'exécution, il n'est possible que si vous passez également un objet explicite représentant T, par exemple:
static <T> List<T> doSth(List<T> l, Class<T> tClass) ayant un objet tClass représentant la vraie classe de T, vous pouvez vérifier s'il a implémenté une réflexion via la comparaison. Mais la vérification à la compilation est beaucoup, beaucoup mieux de mon point de vue.

+0

Oups manqué que Jon déjà mentionné cette option aussi –

1

Vous devriez déjà savoir à (même avant! :) la compilation si T s'étend Comparable ou non, alors pourquoi ne pas faire deux méthodes?

public <T extends Comparable<T>> List<T> doSthComp(List<T> l) { 
    // do one thing 
    return l; 
} 

public <T> List<T> doSth(List<T> l) { 
    // do another 
    return l; 
} 
+0

Vous pouvez probablement être plus généreux avec les limites là. –

+0

Bien sûr, vous ne pouvez pas le savoir au moment de la compilation si vous l'appelez à partir d'un autre type générique ... à ce stade, vous aurez toujours besoin de l'objet 'Class' approprié pour que ma solution fonctionne aussi. Je déteste le type effacement ... –

Questions connexes