parametros - Parámetros genéricos del método varargs de Java
vararg kotlin (6)
Cambiando la firma de merge
a:
public<T> void merged(T ... p)
Al menos te permitirá llamar a fusionar sin problemas. Sin embargo, tendrías que tratar con matrices de cadena como parámetro.
Me pregunto si hay una manera fácil, elegante y reutilizable de pasar una cadena y una matriz de cadenas a un método que espere varargs.
/**
* The entry point with a clearly separated list of parameters.
*/
public void separated(String p1, String ... p2) {
merged(p1, p2, "another string", new String[]{"and", "those", "one"});
}
/**
* For instance, this method outputs all the parameters.
*/
public void merged(String ... p) {
// magic trick
}
¿Incluso si todos los tipos son coherentes ( String
) no puedo encontrar una manera de indicarle a la JVM que aplaste p2 e inyectarlo en la lista de parámetros combinados?
En este punto, la única forma es crear una nueva matriz, copiar todo en ella y pasarla a la función.
¿Alguna idea?
EDITAR
La base de su propuesta aquí es el método genérico que usaré:
/**
* Merge the T and T[] parameters into a new array.
*
* @param type the destination array type
* @param parameters the parameters to merge
* @param <T> Any type
* @return the new holder
*/
@SuppressWarnings("unchecked")
public static <T> T[] normalize(Class<T> type, Object... parameters) {
List<T> flatten = new ArrayList<>();
for (Object p : parameters) {
if (p == null) {
// hum... assume it is a single element
flatten.add(null);
continue;
}
if (type.isInstance(p)) {
flatten.add((T) p);
continue;
}
if (p.getClass().isArray() &&
p.getClass().getComponentType().equals(type)) {
Collections.addAll(flatten, (T[]) p);
} else {
throw new RuntimeException("should be " + type.getName() +
" or " + type.getName() +
"[] but was " + p.getClass());
}
}
return flatten.toArray((T[]) Array.newInstance(type, flatten.size()));
}
normalize(String.class, "1", "2", new String[]{"3", "4", null}, null, "7", "8");
Creo que crear una nueva matriz es el camino a seguir.
Por ejemplo, puedes usar ArrayUtils
de Apache Commons para lograrlo.
ArrayUtils.addAll(p2, p1);
Saludos cordiales, Thomas
Dentro de los separated
, el parámetro p2
es una String[]
. El método merged
puede tomar un solo parámetro String[]
o una secuencia de cadenas, pero no una mezcla de las dos, así que no creo que tengas otra opción más que construir una nueva matriz (que es lo que hace varargs detrás del escenas de todos modos).
Desde varargs doc
Los tres períodos posteriores al tipo de parámetro final indican que el argumento final se puede pasar como una matriz o como una secuencia de argumentos.
Indica claramente an array OR a sequence of arguments
, por lo tanto, usted debe aplanarla, por ejemplo, como lo sugiere la NPE.
Dudo que puedas hacer eso, el compilador de Java debería convertir fusionado (p1, p2) en fusionado (p1, p2 [0], p2 [1] ... p2 [p2.length]), pero no creo que Alguna vez quise crear un compilador tan inteligente (también crearía problemas si existiera la fusión (p1, p2)).
Puedes hacer esto en su lugar (usando pseudo-sintaxis):
import com.google.common.collect.Lists
import java.util.Arrays
separated ( String p1, String... p2 ) {
merged ( Lists.asList ( p1, p2 ) )
}
merged ( List<String> p ) {
...
}
merged ( String ... p ) {
merged ( Arrays.asList ( p )
}
Las matrices son del JDK estándar, las Lists son de guayaba. Ambos métodos asList () crean vistas sobre las matrices de subrayado, no una copia, por lo que no hay muchos problemas de velocidad / memoria.
No creo que exista un enfoque más simple. Sí, copiar en una nueva matriz, como lo sugieren otros, es más simple, pero consume tiempo y memoria. Si sus arreglos son pequeños, puede suceder que crear y acceder a listas pueda ser más lento que copiar, pero para arreglos más grandes, el copiado se convertirá en una sobrecarga mayor.
Me gustan las sugerencias de Sebastian: usted define una envoltura de merge () que aplana la matriz en el vuelo. Esto funciona bien siempre que merge () no sea un método de terceros y puede cambiarlo. Si no, estoy haciendo algo similar aquí.
No creo que haya una manera de que el escalar y la matriz se aplanen implícitamente en una sola matriz.
La solución más limpia que se me ocurre es usar una función auxiliar:
// generic helper function
public static<T> T[] join(T scalar, T[] arr) {
T[] ret = Arrays.copyOfRange(arr, 0, arr.length + 1);
System.arraycopy(ret, 0, ret, 1, arr.length);
ret[0] = scalar;
return ret;
}
public void separated(String p1, String ... p2) {
merged(join(p1, p2));
}