2009-03-25 5 views
1

une instance lors de l'initialisation d'une classe générique en Java est-il avantage à préciser le type des deux côtés de la déclaration?Quelle est la bonne façon de créer une instance de classe Generic en Java?

Ou pour le dire d'une autre manière, quelle est la différence entre ces deux déclarations valides:

ArrayList<String> test = new ArrayList<String>(); 

et:

ArrayList<String> test = new ArrayList(); 

(Il semble deuxième déclaration ne correspond pas à:

ArrayList<String> test = new ArrayList<Object>(); 

comme la troisième déclaration invalide et provoque une erreur de compilation incompatible types .)

Répondre

14

La deuxième déclaration serpente plus ou moins équivalente à la première, mais seulement parce que les médicaments génériques sont effacés lors de l'exécution. Vous obtiendrez un avertissement "conversion non contrôlée", c'est pourquoi je ne l'aime pas.

Une meilleure façon est d'avoir une méthode générique statique comme ceci:

public static <T> List<T> newList() { 
    return new ArrayList<T>(); 
} 

puis faire

List<String> test = newList(); 

C'est ce que Google Collections fait.

(Et vous devriez presque toujours déclarerait vos listes comme List, pas ArrayList rend facile de changer la mise en œuvre plus tard..)

Edit: dribeas demandé dans les commentaires ce que la différence exacte entre les deux déclarations, et pourquoi j'ai dit qu'elles sont "plus ou moins équivalentes". En raison de type erasure, la seule différence entre eux est l'avertissement. Voici un petit morceau de code les comparer:

import java.util.*; 

class GenericDeclarationTest { 
    public static void main(String[] args) { 
     List<String> list1 = new ArrayList<String>(); 
     list1.add(""); 
     String s1 = list1.get(0); 
     List<String> list2 = new ArrayList(); 
     list2.add(""); 
     String s2 = list2.get(0); 
    } 
} 

Et voici le bytecode généré (comme imprimé par javap -c GenericDeclarationTest):

Compiled from "GenericDeclarationTest.java" 
class GenericDeclarationTest extends java.lang.Object{ 
GenericDeclarationTest(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: new  #2; //class java/util/ArrayList 
    3: dup 
    4: invokespecial #3; //Method java/util/ArrayList."<init>":()V 
    7: astore_1 
    8: aload_1 
    9: ldc  #4; //String 
    11: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
    16: pop 
    17: aload_1 
    18: iconst_0 
    19: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
    24: checkcast  #7; //class java/lang/String 
    27: astore_2 
    28: new  #2; //class java/util/ArrayList 
    31: dup 
    32: invokespecial #3; //Method java/util/ArrayList."<init>":()V 
    35: astore_3 
    36: aload_3 
    37: ldc  #4; //String 
    39: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
    44: pop 
    45: aload_3 
    46: iconst_0 
    47: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
    52: checkcast  #7; //class java/lang/String 
    55: astore 4 
    57: return 

} 

Comme vous pouvez le voir (si vous avez la patience), les deux sont identique. Par ailleurs, cela peut devenir plus facile dans Java 7. Il existe un proposal dans Project Coin pour "Inférence de type améliorée pour la création d'instance générique". Si elle fait la coupe finale, la syntaxe sera:

List<String> test = new ArrayList<>(); 
// or 
Map<String, Object> test2 = new HashMap<>(); 

Pas trop difficile à saisir, est-il?

+0

était le après dans votre code « statique » intentionnel? Quel est son but ? – euphoria83

+0

@ euphoria83: Le permet au compilateur de savoir qu'il s'agit d'une méthode générique. Voir page 7 et suivantes de http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf. –

+0

Quelle est la différence entre: Liste x = new ArrayList(); et votre fonction intermédiaire? Et quand vous dites que le premier et le deuxième exemple sont plus ou moins équivalents, quelles sont les différences? –

3

Cette redondance est ennuyeux. Vous voudrez peut-être regarder Google Collections qui ont des méthodes d'usine qui créent List s comme ceci:

List<Double> doubleList = Lists.newLinkedList(); 

Notez également que Java Generics are not covariant.

+0

Google Collections est très pratique, merci. –

Questions connexes