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.

213
demandé sur jasonmp85 2010-05-28 01:36:38

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) .

149
répondu jasonmp85 2010-05-27 21:58:41

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 type T[] . 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:


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 ]"
260
répondu polygenelubricants 2017-05-23 11:54:43

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

18
répondu mdma 2010-05-27 22:17:47

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);
4
répondu ebelisle 2014-03-12 20:36:17

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é.

0
répondu Srijit Paul 2017-12-19 13:52:42