39 votes

Création d'un tableau pour stocker des types génériques en Java

Supposons que j'ai créer un tableau qui stocke liste de tableaux de nombres Entiers et de la taille de la matrice est de 10.

Le code ci-dessous va le faire:

ArrayList<Integer>[] pl2 = new ArrayList[10]; 

Question 1:

À mon avis le plus approprié code serait

ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];    

Pourquoi n'est-ce pas le travail?

Question 2:

Les deux ci-dessous compiler

  1. ArrayList<Integer>[] pl2 = new ArrayList[10];
  2. ArrayList[] pl3 = new ArrayList[10];

Quelle est la différence dans la mesure où la référence de la déclaration d' pl2 et pl3 est concerné?

16voto

ltebean Points 713

Le générique d'info uniquement les questions au moment de la compilation, il indique au compilateur le type pourrait être mis dans un tableau, dans l'exécution, toutes les informations génériques seront effacées, donc ce qui compte c'est comment vous déclarez le type générique.

Cité de Penser en Java:

ce n'est pas précisément correct de dire que vous ne pouvez pas créer des tableaux de les types génériques. Vrai, le compilateur ne vous laisseront pas de les instancier un tableau d'un type générique. Cependant, il vous permettra de créer une référence à un tel tableau. Par exemple:

List<String>[] ls; 

Cela passe par le compilateur sans plainte. Et bien que vous impossible de créer un véritable objet array qui contient les médicaments génériques, vous pouvez créer un tableau de la non-generified type et de la lancer:

//: arrays/ArrayOfGenerics.java 
// It is possible to create arrays of generics. 
import java.util.*; 

public class ArrayOfGenerics { 
    @SuppressWarnings("unchecked") 
    public static void main(String[] args) { 
        List<String>[] ls; 
        List[] la = new List[10]; 
        ls = (List<String>[])la; // "Unchecked" warning 
        ls[0] = new ArrayList<String>(); 
        // Compile-time checking produces an error: 
        //! ls[1] = new ArrayList<Integer>(); 

        // The problem: List<String> is a subtype of Object 
        Object[] objects = ls; // So assignment is OK 
        // Compiles and runs without complaint: 
        objects[1] = new ArrayList<Integer>(); 

        // However, if your needs are straightforward it is 
        // possible to create an array of generics, albeit 
        // with an "unchecked" warning: 
        List<BerylliumSphere>[] spheres = 
           (List<BerylliumSphere>[])new List[10]; 
        for(int i = 0; i < spheres.length; i++) 
           spheres[i] = new ArrayList<BerylliumSphere>(); 
    } 
}

Une fois que vous avez une référence à une Liste[], vous pouvez voir que vous obtenir certains moment de la compilation de la vérification. Le problème est que les tableaux sont covariants, donc une Liste[] est aussi un Objet[], et vous pouvez les utiliser cette attribuer une ArrayList dans votre tableau, avec un sans faute soit le moment de la compilation ou de l'exécution.

Si vous savez que vous n'allez pas sortie et vos besoins sont relativement simple, cependant, il est possible pour créer un tableau de génériques, qui fournira de base au moment de la compilation la vérification de type. Cependant, un conteneur générique sera pratiquement toujours une meilleur choix qu'un tableau de génériques.

13voto

Vladimir Points 4310

Question 1:

Fondamentalement, ce qui est interdit par le langage Java. Ce qui est couvert dans Java Langage de Spécification pour les génériques.

Lorsque vous utilisez

ArrayList<Integer>[] pl2 = new ArrayList[10];    // warning

vous obtenez le message d'avertissement du compilateur, parce que l'exemple suivant permet de compiler (génération d'avertissement pour chaque ligne de code):

ArrayList wrongRawArrayList = new ArrayList();      // warning
wrongRawArrayList.add("string1");                   // warning 
wrongRawArrayList.add("string2");                   // warning  

pl2[0] = wrongRawArrayList;                         // warning 

mais maintenant, vous tableau, qui doit comporter ArrayList de Integer, contient totalement tort, ArrayList de String objets.

Question 2:

Comme il a été déjà répondu, la déclaration de l' p12 vous offre moment de la compilation, de vérification et vous libère de l'aide de casting lors de l'obtention des éléments de votre ArrayList.

Légèrement modifiée de l'exemple précédent:

ArrayList<Integer>[] pl2 = new ArrayList[10];                // warning 

ArrayList<String> wrongArrayList = new ArrayList<String>();  // OK!
wrongArrayList.add("string1");                               // OK! 
wrongArrayList.add("string2");                               // OK!

pl2[0] = wrongArrayList;                                     // ERROR

Maintenant, puisque vous êtes l'utilisation de génériques, ce ne sera pas compilé. Mais si vous l'utilisez

ArrayList[] pl2 = new ArrayList[10]; 

vous obtiendrez le même résultat que dans le premier exemple.

4voto

Abimaran Kugathasan Points 12318

Les tableaux sont covariants. Cela signifie qu'ils conservent le type de leurs éléments au moment de l'exécution. Java les génériques ne sont pas. Ils utilisent le type d'effacement en gros de masque de la conversion implicite qui se passe. Il est important de comprendre que.

Vous devez utiliser Array.newInstance()

En outre, les tableaux portent runtime type d'informations à propos de leur le type de composant, qui est, sur le type des éléments contenus. Le runtime type d'informations concernant le type de composant est utilisé lors de la les éléments sont stockés dans un tableau afin de s'assurer qu'aucun "étranger" les éléments peuvent être insérés.

Pour plus de détails, regardez ici

2voto

Rohit Points 164

Commençons avec la question 2 en premier et ensuite revenir à la question 1:

Question 2:

> ArrayList[] pl2 = new ArrayList[10]; ArrayList[] pl3 = new ArrayList[10];

Quelle est la différence dans la mesure où la référence de la déclaration de p12 et p13 est concerné?

Dans pl2 assure une meilleure sécurité de type de p13.

Si je vous écris pour pl2:

pl2[0]=new ArrayList<String>();

il va me donner un compilateur message d'erreur indiquant "impossible de convertir de ArrayList<String> de ArrayList<Integer>"

Ainsi, il s'assure de la compilation de la sécurité.

Cependant, si j'écris pour p13

pl3[0]=new ArrayList<String>();
pl3[1]=new ArrayList<Integer>();

il ne sera pas jeter toute erreur et il incombe au développeur de code et de vérifier correctement lors de l'extraction de données à partir de p13, afin d'éviter tout dangereux de conversion de type en cours d'exécution.

Question 1:

C'est juste sans doute la façon dont les génériques de travail. Pendant l'initialisation de tableau, ArrayList<Integer>[] pl2 = new ArrayList[10], la gauche, ArrayList<Integer>[] pl2, permettra d'assurer la sécurité de type uniquement lors de l'initialisation de l'objet ArrayList dans la position de l'index:

pl2[0]=new ArrayList<Integer>();

Le côté droit de la principale déclaration de tableau = new ArrayList[10] s'assure juste que la position de l'index tiendra les éléments de type ArrayList. Voir également le type d'effacement des concepts de Type Effacement pour plus d'informations.

2voto

alain.janinm Points 7597

Cela ne fonctionne pas parce que les classes génériques n'appartient pas à Reifiable Types.

Le SÉMINAIRE sur la création de la Matrice d'expression des états :

C'est une erreur de compilation si le [type de classe] ne désigne pas un reifiable type (§4.7). Sinon, le [type de classe] peut-nom d'un nom de type de référence, même une classe abstraite de type (§8.1.1.1) ou un type d'interface (§9).

Les règles ci-dessus impliquent que le type d'élément dans un tableau création d'expression ne peut pas être paramétrée type, autre qu'une surabondance de génériques.

La définition de Reifiable Types est :

Parce que certains type d'information est effacée lors de la compilation, pas tous les types sont disponibles au moment de l'exécution. Les Types qui sont complètement disponibles au moment de l'exécution sont connus comme reifiable types.

Un type est reifiable si et seulement si une des conditions suivantes est satisfaite:

It refers to a non-generic class or interface type declaration.

It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).

It is a raw type (§4.8).

It is a primitive type (§4.2).

It is an array type (§10.1) whose element type is reifiable.

It is a nested type where, for each type T separated by a ".", T itself is reifiable.

For example, if a generic class X<T> has a generic member class Y<U>, then the type X<?>.Y<?> is reifiable because X<?> is reifiable and Y<?> is reifiable. The type X<?>.Y<Object> is not reifiable because Y<Object> is not reifiable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X