2010-04-19 5 views
4

Quelle est la meilleure pratique dans cette situation? Je voudrais un tableau non initialisé du même type et de la même longueur que l'original.Comment créer un nouveau tableau AnyType []?

public static <AnyType extends Comparable<? super AnyType>> void someFunction(AnyType[] someArray) { 

    AnyType[] anotherArray = (AnyType[]) new Comparable[someArray.length]; 
    ...or... 
    AnyType[] anotherArray = (AnyType[]) new Object[someArray.length]; 

    ...some other code... 
} 

Merci, CB

+0

Pourquoi est-ce marqué «débutant»? –

Répondre

7
AnyType[] anotherArray = (AnyType[])java.lang.reflect.Array.newInstance(
     someArray.getClass().getComponentType(), someArray.length); 
+3

Il est à noter que ceci crée un tableau dont le type de base est le même que le type de base du tableau d'entrée. Ce n'est pas nécessairement le même que le paramètre de type générique qui sera déduit par le compilateur. –

+0

Notez également que ceci est également vrai pour l'entrée "someArray". Le "anotherArray" créé peut stocker des instances de "AnyType" exactement aussi sûrement que "someArray". Donc ce code n'ajoute aucune restriction qui n'y était pas déjà. –

5

Les tableaux et les génériques ne se mélangent pas vraiment bien. C'est parce que les tableaux sont covariant et les génériques ne le sont pas. Permettez-moi de vous donner un exemple:

public static void main(String args[]) { 
    foo(new Float[1]); 
} 

public static void foo(Number[] n) { 
    n[0] = 3; 
} 

Ce code est compilé, mais se traduira par une ArrayStoreException.

Le problème que vous aurez à recréer ce tableau est qu'il ne s'agit peut-être pas d'un tableau de AnyType, mais qu'il s'agit peut-être d'une sous-classe de AnyType. Vous pouvez bien sûr utiliser someArray.getClass() et créer le tableau avec la réflexion.

Le thème général est cependant que vous devriez privilégier List s sur les baies car List s n'ont pas les mêmes problèmes. Modifiez le code à:

public static void main(String args[]) { 
    foo(new ArrayList<Float>()); 
} 

public static void foo(List<Number> list) { 
    list.add(3); 
} 

Et le code ne compilera pas, ce qui est un résultat bien meilleur.

5

Une bonne référence est de voir comment <T> T[] Collection.toArray(T[]) est mis en œuvre par AbstractCollection:

public <T> T[] toArray(T[] a) { 
    // Estimate size of array; be prepared to see more or fewer elements 
    int size = size(); 
    T[] r = a.length >= size ? a : 
       (T[])java.lang.reflect.Array 
       .newInstance(a.getClass().getComponentType(), size); 
    //... 

Ainsi, la technique utilise:

Si vous devez absolument créer un tableau « générique », cette technique de passer un instanceof T[] et utilisant la réflexion pour instancier une autre est la façon illustrée par Java Framework Collections.

Toutefois, vous devez également vous demander si vous avez réellement besoin d'une telle fonctionnalité pour .

De Effective Java 2e édition: Article 25: Préférez les listes de tableaux:

En résumé, les tableaux et les génériques ont des règles de type très différentes. Les tableaux sont covariants et réifiés, les génériques sont invariants et effacés. En conséquence, les tableaux fournissent la sécurité du type à l'exécution mais pas la sécurité du type à la compilation et vice versa pour les génériques. D'une manière générale, les tableaux et les génériques ne se mélangent pas bien. Si vous vous trouvez en train de les mélanger et d'obtenir des erreurs et des avertissements au moment de la compilation, votre première impulsion devrait être de remplacer les tableaux par des listes.

Vous devriez lire tout l'article pour un traitement plus complet du sujet.