¿Puedo pasar una matriz como argumentos a un método con argumentos variables en Java?
Me gustaría poder crear una función como:
class A {
private String extraVar;
public String myFormat(String format, Object ... args){
return String.format(format, extraVar, args);
}
}
El problema aquí es que args
se trata como Object[]
en el método myFormat
, y por lo tanto es un solo argumento para String.format
, mientras que me gustaría que cada Object
en args
se pase como un nuevo argumento. Dado que String.format
es también un método con argumentos variables, esto debería ser posible.
Si esto no es posible, hay un método como String.format(String format, Object[] args)
? En ese caso podría anteponer extraVar
a args
usando un nuevo array y pasarlo a ese método.
5 answers
El tipo subyacente de un método variadic function(Object... args)
es function(Object[] args)
. Sun agregó varargs de esta manera para preservar la compatibilidad con versiones anteriores.
Así que deberías poder anteponer extraVar
a args
y llamar a String.format(format, args)
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-27 21:58:41
Sí, un T...
es solo un azúcar sintáctico para un T[]
.
JLS 8.4.1 Parámetros de formato
El último parámetro formal en una lista es especial; puede ser un parámetro variable arity, indicado por un elipsis después del tipo.
Si el último parámetro formal es un parámetro de aridad variable de tipo
T
, se considera que define un parámetro formal de tipoT[]
. El método es entonces un método variable arity. De lo contrario, es un método de aridad fija. Las invocaciones de un método de aridad variable pueden contener más expresiones de argumento reales que parámetros formales. Todas las expresiones de argumento reales que no corresponden a los parámetros formales que preceden al parámetro variable arity se evaluarán y los resultados se almacenarán en un array que se pasará a la invocación del método.
Aquí hay un ejemplo para ilustrar:
public static String ezFormat(Object... args) {
String format = new String(new char[args.length])
.replace("\0", "[ %s ]");
return String.format(format, args);
}
public static void main(String... args) {
System.out.println(ezFormat("A", "B", "C"));
// prints "[ A ][ B ][ C ]"
}
Y sí, el método anterior main
es válido, porque de nuevo, String...
es solo String[]
. Además, debido a que los arrays son covariantes, a String[]
es un Object[]
, por lo que también puede llamar a ezFormat(args)
de cualquier manera.
Véase también
Varargs gotchas #1: pasando {[18]]}
Cómo se resuelven los varargs es bastante complicado, y a veces hace cosas que pueden sorprenderte.
Considere este ejemplo:
static void count(Object... objs) {
System.out.println(objs.length);
}
count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!
Debido a cómo se resuelven los varargs, la última declaración invoca con objs = null
, que por supuesto causaría NullPointerException
con objs.length
. Si desea dar un argumento null
a un parámetro varargs, puede hacer lo siguiente:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
Cuestiones conexas
La siguiente es una muestra de algunas de las preguntas que la gente ha hecho al tratar con varargs:
- error con varargs y sobrecarga?
- Cómo trabajar con varargs y reflexión
- Método más específico con coincidencias de aridad fija/variable (varargs)
Vararg gotchas #2: agregar argumentos adicionales
Como has descubierto, lo siguiente no"funciona":
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
Debido a la forma en que funciona varargs, ezFormat
en realidad obtiene 2 argumentos, el primero es a String[]
, el segundo es a String
. Si está pasando una matriz a varargs, y desea que sus elementos sean reconocidos como argumentos individuales, y también necesita agregar un argumento adicional, entonces no tiene más remedio que cree otro array que acomode el elemento extra.
Aquí hay algunos métodos de ayuda útiles:
static <T> T[] append(T[] arr, T lastElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
arr[N] = lastElement;
return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
System.arraycopy(arr, 0, arr, 1, N);
arr[0] = firstElement;
return arr;
}
Ahora puedes hacer lo siguiente:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(append(myArgs, "Z")));
// prints "[ A ][ B ][ C ][ Z ]"
System.out.println(ezFormat(prepend(myArgs, "Z")));
// prints "[ Z ][ A ][ B ][ C ]"
Varargs gotchas #3: pasando una matriz de primitivas
No "funciona":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs solo funciona con tipos de referencia. Autoboxing no se aplica a la matriz de primitivas. Las siguientes obras:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:43
Está bien pasar un array-de hecho equivale a lo mismo
String.format("%s %s", "hello", "world!");
Es lo mismo que
String.format("%s %s", new Object[] { "hello", "world!"});
Es solo azúcar sintáctico: el compilador convierte el primero en el segundo, ya que el método subyacente espera una matriz para el parámetro vararg.
Véase
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-27 22:17:47
Jasonmp85 tiene razón al pasar una matriz diferente a String.format
. El tamaño de una matriz no se puede cambiar una vez construida, por lo que tendría que pasar una nueva matriz en lugar de modificar la existente.
Object newArgs = new Object[args.length+1];
System.arraycopy(args, 0, newArgs, 1, args.length);
newArgs[0] = extraVar;
String.format(format, extraVar, args);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-12 20:36:17
Estaba teniendo el mismo problema.
String[] arr= new String[] { "A", "B", "C" };
Object obj = arr;
Y luego pasó el obj como argumento varargs. Funcionó.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-19 13:52:42