Varargs gir muligheten til å gi et variablelt antall argumenter til en Java-metode.

Det er ikke uvanlig at en har behov for å gi inn et variabelt antall verdier til en metode. Dette håndteres som regel ved at en deklararer et parameter av typen tabell eller samling verdier (Collection, List eller Iterable). Et eksempel på dette er addAll-metoden i Collection-grensesnittet, som tar inn en Collection som sitt eneste argument:

Person grandmother = new Person()
Collection<Person> grandchildren = new ArrayList<Person>();
// Person.getChildren() returns the children as a Collection 
for (Person child : grandmother.getChildren()) {
	// Collection.addAll takes another Collection as its only argument
	grandchildren.addAll(child.getChildren());
}

Et Collection-parameter er praktisk når en gjerne har verdiene i en eksisterende datastruktur, f.eks. som et felt i et objekt eller et resultat fra en tidligere operasjon, slik som over. Men hvis en ofte må lage Collection-objektet kun for dette formålet, så er det imidlertid ikke så praktisk. Anta f.eks. at en ønsker å initialisere en Person med en samling barn og bruke en eksisterende addChild- eller addChildren-metode. Dette er ikke særlig praktisk, som kode-eksemplene under viser:

Person hallvard = p1, anne = p2, jens = p3
// Person.addChild adds a single child
hallvard.addChild(anne);
hallvard.addChild(jens);
Person hallvard = p1, anne = p2, jens = p3
// Person.addChildren takes a Collection-argument and adds them all
Collection<Person> anneOgJens = new ArrayList<Person>();
anneOgJens.add(anne);
anneOgJens.add(jens);
hallvard.addChildren(anneOgJens);

Deklarasjon og bruk av varargs-parameter

Java tilbyr en mekanisme kalt varargs, for dette formålet. Enkelt sagt kan en definere at siste argument er en samling verdier som angis etter hverandre i argumentlista, istedenfor å eksplisitt lage en tabell eller liste. Argumentene samles automatisk opp i en (ny-allokert) tabell, som metoden så kan iterere over. Merk at det godt kan være andre parametre før varargs-parameteret, men det kan ikke være noen etter. Dette skyldes at det da lett blir tvetydig om et argument hører til varargs-parameteret eller et påfølgende parameter. Merk også at en ikke kan spesifisere minimum og/eller maksimum antall argumenter. Med varargs så kan en gi inn 0, 1 eller flere verdier.

I koden under til venstre så er en addChildren-metoden definert med et slikt varargs-parameter. Vi ser at metoden kan så iterere over elementene i children-tabellen og legge inn hvert enkelt. (Her kunne vi også brukt en vanlig foreach-løkke, men vi ville få frem at children er en vanlig Java-tabell). I eksemplet i midten så kalles addChildren-metoden ved å angi alle barna som enkelt-argumenter.

Metode med varargs-parameter
public void addChildren(Person... children) {
    // children er en tabell (array) av Person-objekter,
    // som om den var deklarert Person[] children
	for (int i = 0; i < children.length; i++) {
		this.addChild(children[i]);
	}
}
Bruk av metode med varargs-parameter
Person hallvard = p1, anne = p2, jens = p3
// Person.addChildren adds alle its arguments
hallvard.addChildren(anne, jens);
Alternativ bruk av metode med varargs-parameter
Person hallvard = p1, anne = p2, jens = p3
Person[] anneOgJens = {anne, jens}
hallvard.addChildren(anneOgJens);

Sett fra innsiden av en metode med et varargs-parameter, så er parameteret en tabell av angitt type, f.eks. Person[] i eksemplet over. Det er også mulig å kalle metoden med et tabell-argument istedenfor å angi enkelt-verdiene i argumentlista, dersom det er enklere. Dette er vist i kode-eksemplet helt til høyre.

Varargs er ikke så mye brukt i Java-API'et, men et nyttig eksempel er Arrays.asList(...)-metoden, som tar alle argumentene og legger dem i en (ikke-modifiserbar) liste, som så returneres. Eksemplet nest øverst til høyre, kunne vært forenklet til følgende kode:

Person hallvard = new Person("H"), anne = new Person("A"), jens = new Person("J")
// Person.addChildren takes a Collection-argument and adds them all
hallvard.addChildren(Arrays.asList(anne, jens)); // utlize that Arrays.asList is a varargs-method
  • No labels