2010-11-26 21 views
2

Si j'appelle un (générique) VarArgs méthode avec des objets de différentes classes, je reçois un avertissement intéressant:Avertissement: Un tableau générique d'objets et Serializable & Comparable <?> est créé pour un paramètre varargs

List<?> result = Arrays.asList("1", 1); 

Un tableau générique de l'objet & Serializable & comparable est créé pour un paramètre varargs

Je peux me débarrasser de l'avertissement par coulée à une interface commune ou classe,

List<Serializable> result = asList((Serializable) "1", (Serializable) 1); 

mais que signifie Object&Serializable&Comparable<?>? Peut-il aussi être utilisé dans des annotations de type générique sur les signatures de méthodes (comme extends ou super)?

Répondre

3

La classe Object et les interfaces Comparable et Serializable sont les supertypes que les classes Integer et String ont en commun.

En raison de l'effacement de type dans les génériques et de la covariance des rangées, les génériques et les matrices ne se mélangent pas très bien entre eux. La méthode Arrays#asList prend un varargs en entrée, et en Java, les varargs sont implémentés en interne avec des tableaux. D'où l'avertissement. (Vous pouvez en lire plus à ce sujet dans Effective Java de Josh Bloch.)

Pour en venir à votre deuxième question, <Object & Comparable<Whatever> & Serializable> peut être utilisé dans les signatures de méthodes pour spécifier les contraintes sur les paramètres de type. (Voir this answer.) Cependant, Java n'autorise pas de tels types dans les annotations de type générique.

En d'autres termes, ce qui suit est valide:

public static void <A extends Comparable<A> & Serializable> meth(A a); 

mais ce qui suit est pas:

List<Serializable & SomeOtherInterface> list = ...; 
+0

EXTRA INFO: Scala permet de telles annotations de type. http://ideone.com/gCTEd – missingfaktor

1

Je pense que parce que tous les types d'objets sont Serializable et Comparable (String et Integer) alors le compilateur dit que tous les éléments dans le tableau auront Object type AND implémente les interfaces Serializable et Comparable.

Je doute que Serializable & Comparable pourrait être utilisé normalement dans le code java, vous pouvez toujours les mettre en œuvre normalement et recevoir le même avertissement :-)

public class ComparableAndSerializableClass implements Comparable<ComparableAndSerializableClass>, Serializable{ 

    public static void main(String[] args) { 
     List<?> result = Arrays.asList("1", 1, new ComparableAndSerializableClass()); 
     for (Object comp : result) { 
      System.out.println(comp.getClass()); 
     } 
    } 

    @Override 
    public int compareTo(ComparableAndSerializableClass o) { 
     return 0; 
    } 
} 
0

Si vous avez un type générique comme Foo<...>, vous pouvez utiliser une méthode d'aide pour appelez Arrays.asList() pour vous:

public static List<Foo<?>> asList(Foo<?> ... foos) { 
    return Arrays.asList(foos); 
} 

Le compilateur Java créera un tableau générique pour le paramètre varargs que vous pouvez ensuite utiliser en toute sécurité dans l'appel à Arrays.asList(). Si vous voulez que tous les Foo aient le même type interne:

public static <T> List<Foo<T>> asList(Foo<T> ... foos) { 
    return Arrays.asList(foos); 
}