2010-07-11 4 views
5

En Java est-il de toute façon d'avoir un constructeur qui acceptera un tableau ou une collection? J'ai joué avec cela pendant un moment mais je ne pense pas que ce soit possible.Java: Un constructeur ou une méthode qui va accepter array ou set ou list ou ...?

Je voudrais pouvoir initialiser MyClass, comme ceci:

MyClass c = new MyClass({"rat", "Dog", "Cat"}); 

Et comme ceci:

LinkedList <String> l = new <String> LinkedList(); 
l.add("dog"); 
l.add("cat"); 
l.add("rat"); 
MyClass c = new MyClass(l); 

C'est ce que MyClass ressemble. Que puis-je faire XXX pour que cela fonctionne? Je sais que je pourrais surcharger le constructeur, mais si je peux minimiser le code, ce serait génial non?

public class MyClass{ 

    private LinkedHashSet <String> myList; 

    public MyClass(XXX <String> input){ 
     myList = new LinkedHashSet <String>(); 
     for(String s : input){ 
      myList.put(s); 
     } 

    } 

} 

Répondre

19

Vous pouvez déclarer deux constructeurs et appeler deuxième de la première:

class MyClass { 
    public MyClass(String... x) { 
     // for arrays 
     // this constructor delegate call to the second one 
     this(Arrays.asList(x)); 
    } 
    public MyClass(List<String> x) { 
     // for lists 
     // all logic here 
    } 
} 

appels ressembleraient

new MyClass(new ArrayList<String>()); 
new MyClass("dog", "cat", "rat"); 
new MyClass(new String[] {"rat", "Dog", "Cat"}); 

Comme il n'y a qu'une seule ligne de code dans le premier constructeur, il est assez minimaliste.

+0

Nice one. Je ferais peut-être l'inverse, car obtenir un 'String []' sur une 'Liste ' est moins coûteux que de construire une 'Liste ' basée sur 'String []'. – BalusC

+2

BalusC - vous vous trompez. Arrays.asList (..) renvoie une vue du même tableau qu'une liste non modifiable. Presque aucun coût. D'un autre côté, aller à String [] nécessite de copier toutes les références vers un nouveau tableau alloué – user44242

+1

@usersmarvin: Merci pour les heads up! Soit dit en passant, pour avertir les utilisateurs des commentaires dans les questions/réponses qui ne sont pas les leurs, mettez un '@' devant le surnom, par ex. '@ BalusC'. Un minimum de 3 premiers caractères est requis pour trouver un match. – BalusC

1

MyClass1 public class {

public MyClass1(final String... animals) { 
     for (final String animal : animals) { 
      System.out.println("eat " + animal); 
     } 
    } 

    public static void main(final String[] args) { 
     new MyClass1(); 
     new MyClass1("dog", "cat", "rat"); 
     new MyClass1(new String[] { "dog", "cat", "rat" }); 
    } 
} 

ou

public class MyClass2 { 

    public MyClass2(final Iterable<String> animals) { 
     for (final String animal : animals) { 
      System.out.println("eat " + animal); 
     } 
    } 

    public static void main(final String[] args) { 
     new MyClass2(Arrays.asList("cat", "rat", "dog", "horse")); 
     final LinkedList<String> animals = new LinkedList<String>(); 
     animals.add("dog"); 
     animals.add("house"); 
     animals.addAll(Arrays.asList("cat", "rat")); 
     new MyClass2(animals); 
    } 
} 
0

Si vous voulez vraiment un seul constructeur, vous pouvez utiliser Arrays.asList et ont le constructeur prend une collection qui couvre Liste et Set.

Personnellement, j'aurais deux constructeurs.

1

Il semble que les tableaux ne soient pas itérables, donc il n'y a aucun moyen de le faire. Il est impossible d'avoir un constructeur qui accepte les tableaux et autres itérables. Ceci est particulièrement gênant puisque nous pouvons le faire:

Foo[] foos = ... 
for (Foo foo : foos) 

Voir cet article pour plus de détails: Why is an array not assignable to Iterable?

1

En théorie, vous pouvez déclarer le constructeur quelque chose comme ceci:

MyClass(Object args) { 
    if (args instanceof List) { 
     ... 
    } else if (args instanceof Set) { 
     ... 
    } else if (args.getClass().isArray()) { 
     ... 
    } else { 
     thrown new IllegalArgumentException("arg's type is wrong"); 
    } 
} 

mais l'OMI , ce serait une mauvaise conception de l'API, car elle redirige tout type de vérification vers l'exécution. (Il n'y a pas d'autre moyen de le faire avec un seul constructeur.Le seul supertype commun des types de tableau et l'interface Collection est Object.)

Il est de loin préférable d'utiliser la surchargement du constructeur comme décrit dans les autres réponses.

Soit dit en passant, les éléments suivants (de votre exemple) est une erreur de syntaxe Java, quel que soit déclaré types d'arguments de constructeur:

MyClass c = new MyClass({"rat", "Dog", "Cat"}); 

Cette forme de initialiseur de tableau ne peut être utilisé dans une déclaration variable; par exemple.

String[] foo = {"rat", "Dog", "Cat"}; 

ou dans le cadre de une expression de création de matrice; par exemple.

String[] foo = new String[]{"rat", "Dog", "Cat"}; 
String[][] bar = new String[][]{{"rat", "Dog", "Cat"}, /* ... */}; 
Questions connexes