365 Stimmen

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

Ich würde gerne eine Funktion erstellen wie:

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

Das Problem dabei ist, dass args wird behandelt als Object[] in der Methode myFormat und ist somit ein einziges Argument für String.format Ich möchte zwar, dass jeder einzelne Object en args als neues Argument übergeben werden. 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 vorangestellt extraVar a args mit einem neuen Array und übergeben es an diese Methode.

385voto

polygenelubricants Punkte 362173

Ja, eine T... ist nur ein syntaktischer Zucker für eine T[] .

JLS 8.4.1 Formatparameter

Der letzte formale Parameter in einer Liste ist etwas Besonderes; er kann ein Arität der Variablen Parameter, gekennzeichnet durch einen Auslassungspunkt nach dem Typ.

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

Hier 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 oben genannten main Methode ist gültig, weil wieder, String... ist nur String[] . Da Arrays außerdem kovariant sind, ist eine String[] ist ein Object[] so können Sie auch ezFormat(args) so oder so.

Siehe auch


Varargs-Fehler Nr. 1: Passieren null

Die Auflösung von varargs ist recht kompliziert, und manchmal werden Dinge getan, die Sie vielleicht überraschen.

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, ruft die letzte Anweisung mit objs = null was natürlich dazu führen würde NullPointerException con objs.length . Wenn Sie eine geben wollen null Argument zu einem varargs-Parameter zu machen, können Sie eine der folgenden Möglichkeiten nutzen:

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

Verwandte Fragen

Im Folgenden finden Sie einige Beispiele für Fragen, die im Zusammenhang mit varargs gestellt wurden:


Vararg-Fehler Nr. 2: Hinzufügen zusätzlicher Argumente

Wie Sie festgestellt haben, "funktioniert" das Folgende nicht:

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

Wegen der Art und Weise, wie varargs funktionieren, ezFormat bekommt eigentlich 2 Argumente, das erste ist ein String[] , die zweite ist eine String . Wenn Sie ein Array an varargs übergeben und möchten, dass dessen Elemente als einzelne Argumente erkannt werden, und Sie außerdem ein zusätzliches Argument hinzufügen müssen, dann haben Sie keine andere Wahl als anderes Array die 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-Fehler Nr. 3: Übergabe eines Arrays von Primitiven

Es "funktioniert" nicht:

    int[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ [I@13c5982 ]"

Varargs funktioniert nur mit Referenztypen. Autoboxing gilt nicht für Arrays von Primitiven. Das Folgende funktioniert:

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

208voto

jasonmp85 Punkte 6619

Der zugrunde liegende Typ einer variadisch Methode function(Object... args) es function(Object[] args) . Sun hat varargs auf diese Weise hinzugefügt, um die Abwärtskompatibilität zu wahren.

Sie sollten also in der Lage sein, einfach voranzustellen extraVar a args und rufen String.format(format, args) .

30voto

mdma Punkte 55529

Es ist in Ordnung, ein Array zu übergeben - im Grunde läuft es auf das Gleiche hinaus

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

ist dasselbe wie

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

Es ist nur syntaktischer Zucker - der Compiler wandelt die erste in die zweite um, da die zugrunde liegende Methode ein Array für die vararg Parameter.

Siehe

6voto

ebelisle Punkte 1147

Jasonmp85 hat Recht mit der Übergabe eines anderen Arrays an String.format . Die Größe eines Arrays kann nicht mehr geändert werden, wenn es einmal konstruiert ist. Sie müssen also ein neues Array übergeben, anstatt das bestehende 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);

5voto

Srijit Paul Punkte 31

Ich hatte dasselbe Problem.

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

Und dann das obj als varargs Argument übergeben. Es hat funktioniert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X