webentwicklung-frage-antwort-db.com.de

Kann ich ein Array als Argumente an eine Methode mit variablen Argumenten in Java übergeben?

Ich möchte in der Lage sein, eine Funktion wie:

class A {
  private String extraVar;
  public String myFormat(String format, Object ... args){
    return String.format(format, extraVar, args);
  }
}

Das Problem hierbei ist, dass args in der Methode myFormat als Object[] Behandelt wird und somit ein einziges Argument für String.format Ist, während ich jeden haben möchte single Object in args, das als neues Argument übergeben werden soll. Da String.format Auch eine Methode mit variablen Argumenten ist, sollte dies möglich sein.

Wenn dies nicht möglich ist, gibt es eine Methode wie String.format(String format, Object[] args)? In diesem Fall könnte ich extraVar mit einem neuen Array args voranstellen und an diese Methode übergeben.

249
user362382

Der zugrunde liegende Typ einer variadischen Methode function(Object... args)isfunction(Object[] args). Sun fügte auf diese Weise Varargs hinzu, um die Abwärtskompatibilität zu erhalten.

Sie sollten also nur in der Lage sein, extraVar vor args zu stellen und String.format(format, args) aufzurufen.

168
jasonmp85

Ja, ein T... Ist nur ein syntaktischer Zucker für einen T[].

JLS 8.4.1 Formatparameter

Der letzte formale Parameter in einer Liste ist etwas Besonderes. Es kann sich um einen Parameter mit variabler Arität handeln, der durch ein Elipsenzeichen nach dem Typ angezeigt wird.

Wenn der letzte formale Parameter ein variabler Aritätsparameter vom Typ T ist, wird davon ausgegangen, dass er einen formalen Parameter vom Typ T[] Definiert. Die Methode ist dann eine Methode mit variabler Arität . Andernfalls handelt es sich um eine Methode mit fester Arität . Aufrufe einer variablen Aritätsmethode können mehr tatsächliche Argumentausdrücke als formale Parameter enthalten. Alle tatsächlichen Argumentausdrücke, die nicht den formalen Parametern vor dem Parameter variable arity entsprechen, werden ausgewertet und die Ergebnisse in einem Array gespeichert, das an den Methodenaufruf übergeben wird.

Hier ist ein Beispiel zur Veranschaulichung:

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 ]"
}

Und ja, die obige Methode main ist gültig, da String... Wiederum nur String[] Ist. Da Arrays kovariant sind, ist ein String[] Ein Object[], Sodass Sie auch ezFormat(args) aufrufen können.

Siehe auch


Varargs Fallstricke # 1: null übergeben

Wie Varargs gelöst werden, ist ziemlich kompliziert, und manchmal tut es Dinge, die Sie überraschen können.

Betrachten Sie dieses Beispiel:

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!!!

Aufgrund der Art und Weise, wie Varargs aufgelöst werden, wird die letzte Anweisung mit objs = null Aufgerufen, was natürlich mit objs.length Zu NullPointerException führen würde. Wenn Sie einem varargs-Parameter ein Argument null geben möchten, haben Sie folgende Möglichkeiten:

count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"

Verwandte Fragen

Das Folgende ist ein Beispiel für einige der Fragen, die Menschen im Umgang mit Varg gestellt haben:


Vararg Fallstricke # 2: Hinzufügen zusätzlicher Argumente

Wie Sie herausgefunden haben, funktioniert Folgendes nicht:

    String[] myArgs = { "A", "B", "C" };
    System.out.println(ezFormat(myArgs, "Z"));
    // prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"

Aufgrund der Funktionsweise von varargs erhält ezFormat zwei Argumente, von denen das erste ein String[] Und das zweite ein String ist. Wenn Sie ein Array an varargs übergeben und möchten, dass seine Elemente als einzelne Argumente erkannt werden, und Sie müssen auch ein zusätzliches Argument hinzufügen, müssen Sie ein anderes erstellen Array , das das zusätzliche Element aufnimmt.

Hier sind einige nützliche Hilfsmethoden:

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;
}

Jetzt können Sie Folgendes tun:

    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 Fallstricke # 3: Übergeben einer Reihe von Primitiven

Es "funktioniert" nicht:

    int[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ [[email protected] ]"

Varargs funktioniert nur mit Referenztypen. Autoboxing gilt nicht für Arrays von Primitiven. Die folgenden Arbeiten:

    Integer[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ 1 ][ 2 ][ 3 ]"
298

Es ist in Ordnung, ein Array zu übergeben - tatsächlich läuft es auf dasselbe hinaus

String.format("%s %s", "hello", "world!");

ist das gleiche wie

String.format("%s %s", new Object[] { "hello", "world!"});

Es ist nur syntaktischer Zucker - der Compiler konvertiert den ersten in den zweiten, da die zugrunde liegende Methode ein Array für den Parameter vararg erwartet.

Sehen

21
mdma

jasonmp85 hat Recht, ein anderes Array an String.format zu übergeben. Die Größe eines Arrays kann nach seiner Erstellung nicht mehr geändert werden. Sie müssen also ein neues Array übergeben, anstatt das vorhandene zu ändern.

Object newArgs = new Object[args.length+1];
System.arraycopy(args, 0, newArgs, 1, args.length);
newArgs[0] = extraVar; 
String.format(format, extraVar, args);
4
ebelisle

Ich hatte das gleiche Problem.

String[] arr= new String[] { "A", "B", "C" };
Object obj = arr;

Und dann das obj als varargs-Argument übergeben. Es funktionierte.

1
Srijit Paul