2012-02-16 13 views
5

La siguiente Python cortó hace exactamente lo que quiero decir:¿Cómo puedo expandir argumentos en Java?

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

def function(a, b, c): 
    print("%i :: %s :: %f" % (a,b,c)) 

a = 1 
b = "abc" 
c = 1.0 

function(a, b, c) 

list = [a, b, c] 

# This is what I am searching for in Java 
function(*(list)) 

Así que tienen una estructura de lista del producto y que no sé cuántos argumentos que tiene, pero sé que tiene el número correcto de argumentos con el tipo y formato correctos. Y quiero pasarlos a un método. Entonces, tengo que "expandir" esos argumentos. ¿Alguien sabe cómo hacerlo en Java?

+0

¿Estás buscando [por ejemplo] (http://stackoverflow.com/questions/766559/when-do-you-use-varargs-in-java) [varargs] (http://docs.oracle.com /javase/1.5.0/docs/guide/language/varargs.html)? –

+0

¿Definir "expandir"? No está claro en tu ejemplo lo que esto significa. – Tudor

+0

Si solo quiere usar algo como el operador '%', puede usar la clase 'Formatter' como en mi respuesta a continuación. –

Respuesta

5

Java no tiene esta función, ya que como lenguaje estáticamente fuertemente tipado, es poco común que un método tome una colección de valores de tipo uniforme que podrían almacenarse en algún objeto compuesto (matriz, lista, etc. .). Python no tiene este problema porque todo está tipeado dinámicamente. Puede hacer esto en Java definiendo un método auxiliar que toma un solo objeto para mantener todos los parámetros, y luego los expande en una llamada al método real.

Espero que esto ayude!

1

No puede. En Java, los parámetros del método se verifican en tiempo de compilación, y dado que el contenido de la matriz solo se define en tiempo de ejecución, esta verificación sería imposible.

La solución más cercana es tener un método que tome una matriz como parámetro y, finalmente, amplíe los argumentos para realizar una llamada al método de destino.

2

Se podría declarar parámetros opcionales con Object... de tal manera que se puede pasar un número arbitrario de argumentos y luego echado cada uno de ellos con el tipo requerido:

public void method1(String p1, Integer p2) { 
} 

public void method2(Object... params) { 
    method1((String)params[0], (Integer)params[1]; 
} 

Puede llamar method2 como:

method2("abc", 1); 

Por supuesto, este ejemplo es un poco redundante, porque puede llamar directamente al method1, pero eso no es lo que quería ilustrar. :)

0

usted puede hacer esto:

import java.util.Formatter; 

// ... 

StringBuilder target = new StringBuilder(); 
Formatter formatter = new Formatter(target); 

List<Integer> integers = new ArrayList<Integer>(); 
integers.add(1); 
integers.add(2); 
integers.add(3); 

formatter.format("%d %d %d", integers.toArray()); 
System.out.println(target.toString()); 

Editar:Javadoc for java.util.Formatter

0

creo que esto hace lo mismo que el código inicial con una sintaxis similar ...

public class MultiArgs { 

    public static void main(String[] args) { 
     int a = 1; 
     String b = "abc"; 
     double c = 1.0; 
     List<?> list = Arrays.asList(a, b, c); 

     System.out.println(function(a, b, c)); // 1 :: abc :: 1.000000 
     System.out.println(function(list.toArray())); // 1 :: abc :: 1.000000 
    } 

    private static <T extends Object> String function(T... objects) { 
     return String.format("%d :: %s :: %f", objects); 
    } 
} 
0

No se recomienda (como las notas de respuesta de templatetypedef, este es un patrón muy poco común para un lenguaje fuertemente tipado), pero usted puede Haz lo que quieras usando la reflexión.

SomeType foo = //obtained from elsewhere 
List<?> args = //obtained from somewhere else 

//this bit obtains the method handle 
Method theMethod = null; 
for (Method m : foo.getClass().getMethods()) { 
    if (m.getName().equals("theMethodIWant") { 
     theMethod = m; 
     break; 
    } 
} 

theMethod.invoke(foo, args.toArray()); //this is the line that does the magic 

Algunas advertencias bastante graves:

  • reflexión puede tener un impacto significativo rendimiento en comparación con una llamada directa - mucho más que en un lenguaje dinámico como Python. Esto puede o no importar. En caso de duda, mida.

  • El bloque que obtiene un identificador método dará lugar a un puntero nulo si no se encuentra un método con este nombre

  • La lista de argumentos debe tener exactamente el número correcto de argumentos, con el tipo correcto . Usted es responsable de verificar esto en otro lugar. Esto es más difícil de lo que sería en un lenguaje dinámico, ya que el tiempo de ejecución hará mucho menos (si corresponde) de tipo de coerción por usted.

  • method.invoke() puede lanzar una serie de excepciones (IllegalAccessException, IllegalArgumentException, InvocationTargetException, etc.) que este ejemplo ignora. Deberá detectar y tratar esos errores de forma adecuada

  • si el método que se está llamando no es público, tendrá que hacer aún más trabajo que este para llamarlo.

  • este ejemplo ni siquiera intenta tratar el caso en el que tiene un método sobrecargado. Dos métodos llamados "theMethodIWant" con diferentes listas de argumentos requerirán un enfoque diferente para obtener el manejador de método.

En general, recomendaría no utilizar la reflexión si es posible.

Cuestiones relacionadas