2012-05-13 32 views
5

Preámbulo: Soy consciente de la utilización de una lista o de otras colecciones a devolver un resultado, pero luego tengo que ir a través de la lista arrancando los resultados a cabo: véase el segundo ejemplodevolver varios valores en Java

Preámbulo-2: estoy buscando una respuesta más allá de 'esto no es compatible con Java ...'


Busco una forma conveniente para devolver varios objetos de una llamada a un método Java.

Algo así como en PHP:

list ($obj1, $obj2, ...) foobar(); 

realmente estoy cansando de los objetos que pasan titular en los argumentos por ejemplo:

class Holder { 
    int value; 
} 

Holder h1=new Holder(); 
Holder h2=new Holder(); 

y luego:

o.foobar(h1,h2); 

... estaría muy interesado si alguien ha encontrado una forma elegante de evitar esto.


Usando una lista

List<String> = foobar(); 

Hay dos desventajas de este:

tengo que empacar en primer lugar la lista de la parte llamada de la casa:

// this is on the callee side of the house 
ArrayList<String> result = new ArrayList<String> 
result.add("foo"); 
result.add("bar"); 

Luego, en el lado de la persona que llama, tengo que sacar los resultados:

// This is on the caller side 
List<String> result = foobar(); 
String result1 = result.get(0); 
String result2 = result.get(1); // this is not as elegant as the PHP equivalent 

Además, decir que quería devolver objetos de diferentes tipos decir cadena, entero tendría que devolver una lista de objetos y luego emitir cada objeto ... no es bonito

Gracias.

+3

Simplemente devolvería una lista – keyser

+0

¿Cuál es el problema con la devolución de la lista? –

+2

Editado. Una "mano vieja" en Java no haría esta pregunta, y el original pareció un poco sarcástico. –

Respuesta

8

Usar una clase de tupla genérica es lo más parecido que puedo imaginar. Para dar una idea, esa clase de propósito general para tres valores de retorno podría ser algo como esto:

public class T3<A, B, C> { 
    A _1; 
    B _2; 
    C _3; 
    T3(A _1, B _2, C _3) { 
     this._1 = _1; 
     this._2 = _2; 
     this._3 = _3; 
    } 
} 

Esto permite que un constructor de una declaración sobre el lado del abonado llamado, por ejemplo:

public T3<String, Integer, Character> getValues() { 
    return new T3<String, Integer, Character>("string", 0, 'c'); 
} 

pero ningún titular la construcción de la instancia por parte del llamado debe hacerse.

Cada número de valores devueltos necesita una clase tuple propia. Puede haber algo como eso proporcionado en el Functional Java library. Como referencia, aquí hay un N-Tuple implementation.

Para el caso de dos valores java.util.AbstractMap.SimpleEntry haría:

return new SimpleEntry<String, Integer>("string", 0); 

De todos modos, veo dos puntos importantes a tener en cuenta para múltiples valores de retorno:

  1. valores de retorno con tipo
  2. Señalando el significado de cada valor de retorno

todo lo aburrido que es decir, recomendaría crear una clase separada para contener todos los valores de respuesta y declararlo como el tipo de retorno del método. De esta forma, se puede resaltar el significado de cada valor.

4

¿Puedes devolver un List, Set o Map?

+1

No puedo, pero esto es más bien solución engorrosa: consulte el ejemplo 2 en mi pregunta – user1172468

5

Usted puede tener un método como con una firma como esta:

List<Holder> foobar(); 
1

Puede utilizar cualquiera de la clase Collection para este propósito. Este Lesson puede ayudarlo a decidir cuál es el más adecuado para usted.

+0

Hola, gracias por la respuesta, soy consciente de esto, he aclarado que estoy buscando alguno de los remedios típicos para esto. – user1172468

2

Volviendo un titular de una prolongada parece mejor que el retorno de una lista:

class Holder { 
    int value1; 
    String value2; 
    Holder(int value1, String value2) {} 
} 

Holder foobar() { 
    return new Holder(1, "bar"); 
} 
+0

Ya, posiblemente verboso verbose verbose :-(, gracias por la respuesta – user1172468

+0

@ user1172468 Verbosity es la propiedad inherente de Java. A veces anhelo la magia de sobrecarga de tipo C++ y de operador, pero hacen un lío, así que me alegro de que Java sea verboso. –

2

Si necesita devolver múltiples valores del mismo tipo, a continuación, una lista o grupo es apropiado. Es perfectamente válido devolver, por ejemplo, una lista de nombres de usuario de longitud variable como una lista. Si sabe que siempre va a devolver un número fijo de valores, usaría una matriz.Por ejemplo, en un método que devuelve un algún tipo de identificador de usuario como tres números enteros distintos, usaría:

public int[] getUserId(){ 
    int[] returnArray = new int[3]; 
    returnArray[0] = getFirstPart(); 
    returnArray[1] = getSecondPart(); 
    returnArray[2] = getThirdPart(); 

    return returnArray; 
} 

En el código de la persona que llama, la obtención de los valores es tan simple como array[0], array[1] y array[2]. Esto es mucho más fácil que una Colección, y no romperá nada, ya que los ID de usuario se definen como tres enteros.

Si realmente necesita devolver múltiples valores distintos, entonces la clase de titular es la mejor opción, no hay otra forma de evitarlo. Los valores de retorno múltiples no son compatibles con Java. Pero preferiría ver la solución desde el punto de vista del diseño. Si una clase necesita devolver múltiples valores distintos, entonces probablemente haga muchas cosas, algunas de ellas sin relación con otras. Una sola pieza de código (una clase, un método) siempre debe tener un único propósito claro y responsabilidades claramente definidas. En lugar de devolver múltiples valores distintos, consideraría dividir el método en múltiples métodos más cortos o definir una interfaz para externalizar toda la funcionalidad. Si esos valores de retorno están relacionados de alguna manera y no tendrían sentido si se los desarma, entonces creo que merecen una clase por sí mismos.

Cuestiones relacionadas