~/home of geeks

varargs done right

· 358 Wörter · 2 Minute(n) Lesedauer

red steam train travelling over arch bridge, in the style of swiss style, i cant believe how beautiful this is, biblical grandeur, cargopunk, bold colors, strong lines, pristine naturalism, konica big mini, romanesque, naturalistiv charm

Variable Argumentlisten (varargs) als Parameter für Methoden sind seit Java 5 möglich. Sie sind eine sehr praktische Möglichkeit, um Methoden mit einer variablen Anzahl von Parametern zu definieren.

Üblicherweise hat man eine Methode mit einem Parameter als Ausgangspunkt und möchte diese um eine weitere Variante erweitern, die mehrere Parameter akzeptiert:

public void foo(String arg) {
    System.out.println(arg);
}
public void foo(String... args) {
    if (args == null) {
        return;
    }
    for (String arg : args) {
        foo(arg);
    }
}

Die Aufrufe beider Methoden funktionieren auf den ersten Blick auch wunderbar:

foo("bar"); // Aufruf der Methode mit einem Parameter
foo("bar", "baz"); // Delegiert auf die varargs Methode
foo(new String[]{"foo", "bar"}); // Delegiert auf die varargs Methode
foo({"foo", "bar"}); // Delegiert auf die varargs Methode

Allerdings kann es Probleme mit diesen Methoden geben. Verwenden wir ein null als Argument, so kann der Compiler nicht entscheiden, welche Methode aufgerufen werden soll:

foo(null); // ambiguous method call

Das Problem ist, dass der Compiler nicht weiß, ob er die Methode mit einem Parameter oder die Methode mit der variablen Argumentliste aufrufen soll.

Dies kann uns dazu nötigen, beim Einsatz von null einen expliziten Cast zu verwenden:

foo((String) null); // Aufruf der Methode mit einem Parameter

In dynamischen Sprachen, wie Groovy kann das Problem sogar bei der Verwendung einer Variablen zur Laufzeit auftreten:

String value = null
print(value) // ambiguous method call

Weiterhin besteht nun die Möglichkeit, dass wir die Methode ohne Parameter aufrufen:

foo(); // Delegiert auf die varargs Methode

Dieser Aufruf ist in diesem Fall zwar nicht sinnvoll, aber dennoch möglich.

Daher macht es Sinn, die Methode mit der variablen Argumentliste anzupassen, um beide Probleme zugleich zu lösen:

public void foo(String arg0, String... args) {
    foo(arg0);
    if (args == null) {
        return;
    }
    for (String arg : args) {
        foo(arg);
    }
}

Nun ist der Aufruf mit null eindeutig und der Aufruf ohne Parameter ist per Compiler nicht mehr möglich.

foo(null); // Aufruf der Methode mit einem Parameter
foo(); // Compilerfehler

Dafür ist der Aufruf mit nur einem Parameter-Array auch per Compiler nicht mehr möglich:

foo(new String[]{"foo", "bar"}); // Compilerfehler
foo({"foo", "bar"}); // Compilerfehler