Varargs i Java

1. Introduktion

Varargs blev introduceret i Java 5 og give en kort hånd til metoder, der understøtter et vilkårligt antal parametre af en type.

I denne artikel vil vi se, hvordan vi kan bruge denne centrale Java-funktion.

2. Før Varargs

Før Java 5, når vi ønskede at videregive et vilkårligt antal argumenter, var vi nødt til at videregive alle argumenter i en matrix eller implementere N-metoder (en for hver yderligere parameter):

offentlige strengformat () {...} offentlige strengformat (strengværdi) {...} offentlige strengformat (streng val1, streng val2) {...}

3. Brug af Varargs

Varargs hjælpe os med at undgå at skrive kedelpladekode ved at indføre den nye syntaks, der automatisk kan håndtere et vilkårligt antal parametre - ved hjælp af en matrix under emhætten.

Vi kan definere dem ved hjælp af en standardtypedeklaration efterfulgt af en ellips:

offentlig streng formatWithVarArgs (streng ... værdier) {// ...}

Og nu kan vi kalde vores metode med et vilkårligt antal argumenter som:

formatWithVarArgs (); formatWithVarArgs ("a", "b", "c", "d");

Som nævnt tidligere, varargs er arrays, så vi er nødt til at arbejde med dem ligesom vi ville arbejde med et normalt array.

4. Regler

Varargs er ligetil at bruge. Men der er et par regler, vi skal huske på:

  • Hver metode kan kun have en varargs parameter
  • Det varargs argumentet skal være den sidste parameter

5. Bunforurening

Ved brug af varargs kan føre til såkaldt bunkeforurening. Overvej dette for at forstå dyngens forurening bedre varargs metode:

statisk String firstOfFirst (List ... strings) {List ints = Collections.singletonList (42); Objekt [] objekter = strenge; objekter [0] = ints; // Returstrenge for bunkeforurening [0] .get (0); // ClassCastException}

Hvis vi kalder denne mærkelige metode i en test:

Streng en = firstOfFirst (Arrays.asList ("en", "to"), Collections.emptyList ()); assertEquals ("en", en);

Vi ville få en ClassCastException selvom vi ikke engang brugte nogen eksplicit type casts her:

java.lang.ClassCastException: klasse java.lang.Integer kan ikke kastes til klasse java.lang.String

5.1. Sikker brug

Hver gang vi bruger varargs, Java-kompilatoren opretter et array, der indeholder de givne parametre. I dette tilfælde opretter kompilatoren en matrix med komponenter af generisk type, der holder argumenterne.

Når vi bruger varargs med generiske typer, da der er en potentiel risiko for en fatal undtagelse, run Java advarer os om en mulig usikker varargs brug:

advarsel: [varargs] Mulig dyngeforurening fra parametreret vararg type T

Det varargs brugen er sikker, hvis og kun hvis:

  • Vi gemmer ikke noget i det implicit oprettede array. I dette eksempel lagrede vi en Liste i den matrix
  • Vi lader ikke en henvisning til det genererede array undslippe metoden (mere om dette senere)

Hvis vi er sikre på, at selve metoden bruger varargs sikkert, kan vi bruge det @SafeVarargs for at undertrykke advarslen.

Enkelt sagt, den varargs brug er sikkert, hvis vi bruger dem til at overføre et variabelt antal argumenter fra den, der ringer op til metoden og intet mere!

5.2. Undslipper Varargs Reference

Lad os overveje en anden usikker brug af varargs:

statisk T [] til Array (T ... argumenter) {returner argumenter; }

Først ser det ud til, at toArray metoden er fuldstændig harmløs. Men fordi det lader varargs-arrayet flygte til den, der ringer op, overtræder det den anden regel om sikker varargs.

For at se, hvordan denne metode kan være farlig, lad os bruge den i en anden metode:

statisk T [] returnAsIs (Ta, Tb) {return toArray (a, b); }

Så hvis vi kalder denne metode:

String [] args = returnAsIs ("One", "Two");

Vi ville igen få en ClassCastException. Her er hvad der sker, når vi kalder returnAsIs metode:

  • At bestå -en og b til toArray metode, skal Java oprette en matrix
  • Siden den Objekt[] kan indeholde emner af enhver type, opretter compileren en
  • Det toArray metode returnerer det givne Objekt[] til den, der ringer op
  • Da opkaldswebstedet forventer en Snor[], compileren forsøger at kaste Objekt[] til det forventede Snor[], derfor ClassCastException

For en mere detaljeret diskussion om dyngeforurening anbefales det stærkt at læse punkt 32 i Effektiv Java af Joshua Bloch.

6. Konklusion

Varargs kan få en masse kedelplade til at forsvinde i Java.

Og takket være deres implicitte autoboxing til og fra Array, de spiller en rolle i fremtidssikring af vores kode.

Som altid kan alle kodeeksempler fra denne artikel findes i vores GitHub-arkiv.