2010-07-11 15 views
5

En Java, ¿hay alguna forma de tener un constructor que acepte una matriz o una colección? He estado jugando con esto por un tiempo, pero no creo que sea posible.Java: ¿Un constructor o método que aceptará una matriz o conjunto o lista o ...?

Me gustaría ser capaz de inicializar MyClass, así:

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

Y como esto:

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

Esto es lo que MyClass se parece. ¿Qué puedo hacer XXX para que esto funcione? Sé que podría sobrecargar el constructor, pero si puedo minimizar el código, sería increíble ¿no?

public class MyClass{ 

    private LinkedHashSet <String> myList; 

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

    } 

} 

Respuesta

19

Se puede declarar dos constructores y llame segundo de la primera:

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 
    } 
} 

Las llamadas se vería como

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

Dado que sólo hay una línea de código en el primer constructor, es bastante minimalista.

+0

Nice one. Tal vez lo haga al revés, ya que obtener un 'String []' de una 'List ' es menos costoso que construir 'List ' basado en 'String []'. – BalusC

+2

BalusC - estás equivocado. Arrays.asList (..) devuelve una vista de la misma matriz como una lista inmutable. Casi sin costo Por otro lado, ir a String [] requiere copiar todas las referencias a una nueva matriz asignada – user44242

+1

@usersmarvin: ¡Gracias por el aviso! Por cierto, para notificar a los usuarios sobre comentarios en preguntas/respuestas que no son las suyas, pon una '@' delante del alias, p. '@ BalusC'. Se requiere un mínimo de 3 primeros caracteres en el nombre para encontrar una coincidencia. – BalusC

1

public class {MyClass1

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" }); 
    } 
} 

o

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 realmente quiere un único constructor que podría utilizar Arrays.asList y luego hacer que el constructor toma una colección que cubre lista y establece.

Yo personalmente tendría dos constructores.

1

Parece que las matrices no son iterables, por lo que no hay forma de hacerlo. Es imposible tener un constructor que acepte matrices Y otros iterables. Esto es especialmente molesto, ya que podemos hacer esto:

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

Ver este post para más detalles: Why is an array not assignable to Iterable?

1

En teoría, se podría declarar el constructor o menos así:

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"); 
    } 
} 

pero OMI , ese sería un mal diseño de la API, ya que activa todo tipo de comprobación para el tiempo de ejecución. (No hay otra manera de hacer esto con un único constructor. El único supertipo común de tipos de matriz y la interfaz Collection es Object).

Es mucho mejor usar sobrecarga de constructor como se describe en las otras respuestas.

Por cierto, la siguiente (de su ejemplo) es un error de sintaxis de Java, con independencia del constructor del declararon tipos de argumentos:

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

Esa forma de matriz de inicialización sólo se puede utilizar en una declaración de variables; p.ej.

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

o como parte de una expresión creación de la matriz; p.ej.

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