Bei vielen Methoden ist es klar, wie viele Argumente sie haben; eine Sinus-Methode bekommt nur ein Argument, equals(Object) ein Objekt, println(…) nichts oder genau ein Argument, usw. Es gibt jedoch Methoden, bei denen die Zahl mehr oder weniger frei ist. Ein paar Beispiele:
· Wenn der Aufruf System.out.printf(formatierungsstring, arg1, args2, arg3, …) etwas auf dem Bildschirm ausgibt, ist erst einmal nicht bekannt, wie viele Argumente die Methode besitzt, denn sie sind abhängig vom Formatierungsstring.
· Fügt Collections.addAll(sammlung, elem1, elem2, elem3, …) etwas einer Sammlung hin, ist frei, wie viele Elemente es sind.
· Wird ein Pfad für das Dateisystem zusammengebaut, ist vorher unbekannt, wie viele Segmente Paths.get( anfang, segment1, segment2, … ) besitzt.
· Startet new ProcessBuilder("kommando", "arg1", "arg1", …).start() ein Hintergrundprogramm, ist der Methode unbekannt, wie viele Argumente dem externen Programm übergeben werden.
Um die Anzahl der Parameter beliebig zu gestalten, sieht Java Methoden mit variabler Argumentanzahl, auch Varargs genannt, vor.
Eine Methode mit variabler Argumentanzahl nutzt die Ellipse (»…«) zur Verdeutlichung, dass eine beliebige Anzahl Argumente angegeben werden dürfen, dazu zählt auch die Angabe keines Elements. Der Typ fällt dabei aber nicht unter den Tisch; er wird ebenfalls angegeben.
System.out.printf() nimmt eine beliebige Anzahl von Argumenten an
Eine Methode mit Varargs haben wir schon einige Male verwendet: printf(…). Die Deklaration ist wie folgt:
class java.io.PrintStream extends FilterOutputStream implements Appendable, Closeable
PrintStream printf(String format, Object… args)
Nimmt eine beliebige Liste von Argumenten an und formatiert sie nach dem gegebenen Formatierungsstring format.
Gültige Aufrufe von printf(…) sind demnach:
Aufruf
|
Variable Argumentliste
|
System.out.printf("%n")
|
ist leer
|
System.out.printf("%s", "Eins")
|
besteht aus nur einem Element: "Eins"
|
System.out.printf("%s,%s,%s", "1", "2", "3")
|
besteht aus drei Elementen: "1", "2", "3"
|
Maximum eines Feldes finden
Die Klasse java.lang.Math sieht eine statische max(…)-Methode mit zwei Argumenten vor, doch grundsätzlich könnte die Methode auch beliebig viele Argumente entgegennehmen und von diesen Elementen das Maximum bilden. Die Methode könnte so aussehen:
static int max( int… array ) {
}
max(…) behandelt den Parameter array wie ein Feld. Da wir Argumente vom Typ int fordern, ist array vom Typ int[] und kann so zum Beispiel mit dem erweiterten for durchlaufen werden:
for ( int e : array )
…
Werden variable Argumentlisten in der Signatur definiert, so dürfen sie nur den letzten Parameter bilden; andernfalls könnte der Compiler bei den Parametern nicht unbedingt zuordnen, was nun ein Vararg und was schon der nächste gefüllte Parameter ist:
public class MaxVarArgs {
static int max( int… array ) {
if ( array == null || array.length == 0 )
throw new IllegalArgumentException( "Array null oder leer" );
int currentMax = Integer.MIN_VALUE;
for ( int e : array )
if ( e > currentMax )
currentMax = e;
return currentMax;
}
public static void main( String[] args ) {
System.out.println( max(1, 2, 9, 3) ); // 9
}
}
Tipp: Vararg-Design. Muss eine Mindestanzahl von Argumenten garantiert werden – bei max(…) sollten das mindestens zwei sein – ist es besser, eine Deklaration wie folgt zu nutzen: max(int first, int second, int… rest).
Compiler baut Array auf
Der Nutzer kann jetzt die Methode aufrufen, ohne ein Feld für die Argumente explizit zu definieren. Er bekommt auch gar nicht mit, dass der Compiler im Hintergrund ein Feld mit vier Elementen angelegt hat. So übergibt der Compiler:
System.out.println( max( new int[] { 1, 2, 9, 3 } ) );
An der Schreibweise lässt sich gut ablesen, dass wir ein Feld auch von Hand übergeben können:
int[] ints = { 1, 2, 9, 3 };
System.out.println( max( ints ) );
Hinweis. Da Varargs als Felder umgesetzt werden, sind überladene Varianten wie max(int… array) und max(int[] array), also einmal mit einem Vararg und einmal mit einem Feld, nicht möglich. Besser ist es hier, immer eine Variante mit Varargs zu nehmen, da diese mächtiger ist. Einige Autoren schreiben auch die Einstiegsmethode main(String[] args) mit variablen Argumenten, also main(String… args). Das ist gültig, denn im Bytecode steht ja ein Array.