Puis-je passer un tableau comme argument à une méthode avec des arguments variables en Java?
j'aimerais pouvoir créer une fonction comme:
class A {
private String extraVar;
public String myFormat(String format, Object ... args){
return String.format(format, extraVar, args);
}
}
le problème ici est que args
est traité comme Object[]
dans la méthode myFormat
, et est donc un seul argument à String.format
, alors que je voudrais que chaque Object
dans args
soit passé comme un nouvel argument. Puisque String.format
est aussi une méthode avec des arguments variables, cela devrait être possible.
si cela n'est pas possible, y a-t-il une une méthode comme String.format(String format, Object[] args)
? Dans ce cas, je pourrais préparer extraVar
à args
en utilisant un nouveau tableau et le passer à cette méthode.
5 réponses
le type sous-jacent d'une méthode variadique function(Object... args)
est function(Object[] args)
. Sun a ajouté des varargs de cette façon pour préserver la compatibilité ascendante.
donc vous devriez juste pouvoir préparer extraVar
à args
et appeler String.format(format, args)
.
Oui, un T...
n'est qu'un sucre syntaxique pour un T[]
.
JLS 8.4.1 paramètres de Format
le dernier paramètre formel dans une liste est spécial; il peut être un paramètre arity variable , indiqué par un elipsis suivant le type.
si le dernier paramètre formel est un paramètre arity variable de type
T
, il est considéré pour définir un paramètre formel de typeT[]
. La méthode est alors une arité variable la méthode. Autrement, il s'agit d'une méthode fixe arity . Les Invocations d'une méthode arity variable peuvent contenir plus d'expressions d'arguments réels que de paramètres formels. Toutes les expressions d'arguments réelles qui ne correspondent pas aux paramètres formels précédant le paramètre arity variable seront évaluées et les résultats stockés dans un tableau qui être transmis à l'invocation de la méthode.
voici un exemple pour illustrer:
public static String ezFormat(Object... args) {
String format = new String(new char[args.length])
.replace(""151900920"", "[ %s ]");
return String.format(format, args);
}
public static void main(String... args) {
System.out.println(ezFormat("A", "B", "C"));
// prints "[ A ][ B ][ C ]"
}
et oui, la méthode ci-dessus main
est valide, parce que là encore, String...
est juste String[]
. En outre, parce que les tableaux sont covariants , un String[]
est un Object[]
, de sorte que vous pouvez également appeler ezFormat(args)
dans les deux cas.
voir aussi
Varargs gotchas #1: passage null
Comment varargs sont résolus est assez compliqué, et parfois il fait des choses qui peuvent vous surprendre.
considérons cet exemple:
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!!!
en raison de la façon dont les varargs sont résolus, la dernière déclaration invoque avec objs = null
, qui, bien sûr, causerait NullPointerException
avec objs.length
. Si vous voulez donner un argument null
à un paramètre varargs, vous pouvez faire l'un des suivants:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
questions connexes
ce qui suit est un échantillon de quelques-unes des questions que les gens ont posées lorsqu'ils traitaient avec varargs:
- bug avec varargs et surcharge?
- comment travailler avec varargs et réflexion
- méthode la plus spécifique avec les allumettes d'arité fixe/variable (varargs)
Vararg gotchas #2: Ajout d'arguments supplémentaires
comme vous l'avez découvert, ce qui suit ne "fonctionne" pas:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
en raison de la façon dont les varargs fonctionnent, ezFormat
obtient en fait 2 arguments, le premier étant un String[]
, le second être un String
. Si vous passez un tableau à varargs, et que vous voulez que ses éléments soient reconnus comme des arguments individuels, et que vous devez aussi ajouter un argument supplémentaire, alors vous n'avez pas d'autre choix que de créer un autre tableau qui accepte l'élément supplémentaire.
voici quelques méthodes d'aide utiles:
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;
}
Maintenant vous pouvez faire ce qui suit:
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 pièges #3: le passage d'un tableau de primitives
Ce n'est pas un "travail":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs fonctionne uniquement avec les types de référence. L'Autoboxing ne s'applique pas au tableau de primitives. Les œuvres suivantes:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
c'est ok de passer un tableau - en fait cela revient à la même chose
String.format("%s %s", "hello", "world!");
est le même que
String.format("%s %s", new Object[] { "hello", "world!"});
c'est juste du sucre syntaxique - le compilateur convertit le premier en deuxième, puisque la méthode sous-jacente attend un tableau pour le paramètre vararg .
voir
jasonmp85 a raison en passant un tableau différent à String.format
. La taille d'un tableau ne peut pas être changée une fois construit, donc vous devez passer un nouveau tableau au lieu de modifier le tableau existant.
Object newArgs = new Object[args.length+1];
System.arraycopy(args, 0, newArgs, 1, args.length);
newArgs[0] = extraVar;
String.format(format, extraVar, args);
j'avais le même problème.
String[] arr= new String[] { "A", "B", "C" };
Object obj = arr;
et ensuite passé l'obj comme argument varargs. Il a travaillé.