Varargs i Java
1. Introduksjon
Varargs ble introdusert i Java 5 og gi en kort hånd for metoder som støtter et vilkårlig antall parametere av en type.
I denne artikkelen vil vi se hvordan vi kan bruke denne kjerne-Java-funksjonen.
2. Før Varargs
Før Java 5, hver gang vi ønsket å sende et vilkårlig antall argumenter, måtte vi sende alle argumentene i en matrise eller implementere N-metoder (en for hver ekstra parameter):
offentlig strengformat () {...} offentlig strengformat (strengverdi) {...} offentlig strengformat (streng val1, streng val2) {...}
3. Bruk av Varargs
Varargs hjelpe oss med å unngå å skrive kjelekode ved å introdusere den nye syntaksen som kan håndtere et vilkårlig antall parametere automatisk - ved hjelp av en matrise under panseret.
Vi kan definere dem ved hjelp av en standard typedeklarasjon, etterfulgt av en ellips:
offentlig strengformatWithVarArgs (streng ... verdier) {// ...}
Og nå kan vi kalle metoden vår med et vilkårlig antall argumenter, som:
formatWithVarArgs (); formatWithVarArgs ("a", "b", "c", "d");
Som nevnt tidligere, varargs er matriser, så vi må jobbe med dem akkurat som vi ville jobbe med et vanlig utvalg.
4. Regler
Varargs er enkle å bruke. Men det er noen få regler vi må huske på:
- Hver metode kan bare ha en varargs parameter
- De varargs argumentet må være den siste parameteren
5. Haugforurensning
Ved hjelp av varargs kan føre til såkalt Heap Pollution. For å bedre forstå haugforurensningen, bør du vurdere dette varargs metode:
statisk streng førstOfFirst (Liste ... strenger) {Liste ints = Collections.singletonList (42); Objekt [] objekter = strenger; objekter [0] = ints; // Hengeforurensningstrenger [0] .get (0); // ClassCastException}
Hvis vi kaller denne rare metoden i en test:
Streng en = firstOfFirst (Arrays.asList ("en", "to"), Collections.emptyList ()); assertEquals ("en", en);
Vi ville fått en ClassCastException selv om vi ikke en gang brukte noen eksplisitte type casts her:
java.lang.ClassCastException: klasse java.lang.Integer kan ikke kastes til klasse java.lang.String
5.1. Sikker bruk
Hver gang vi bruker varargs, oppretter Java-kompilatoren en matrise som inneholder de gitte parametrene. I dette tilfellet oppretter kompilatoren en matrise med komponenter av generisk type for å beholde argumentene.
Når vi bruker varargs med generiske typer, da det er en potensiell risiko for et dødelig unntak for kjøretid, advarer Java-kompilatoren oss om en mulig usikker varargs bruk:
advarsel: [varargs] Mulig haugforurensning fra parametriserte vararg type T
De varargs bruk er trygt hvis og bare hvis:
- Vi lagrer ikke noe i den implisitt opprettede matrisen. I dette eksemplet lagret vi en Liste i den matrisen
- Vi lar ikke en referanse til den genererte matrisen unnslippe metoden (mer om dette senere)
Hvis vi er sikre på at selve metoden trygt bruker vargs, kan vi bruke @SafeVarargs for å undertrykke advarselen.
Enkelt sagt, den varargs bruk er trygt hvis vi bruker dem til å overføre et variabelt antall argumenter fra innringeren til metoden og ingenting mer!
5.2. Rømmer Varargs Henvisning
La oss vurdere en annen usikker bruk av varargs:
statisk T [] til Array (T ... argumenter) {returner argumenter; }
Først kan det se ut til at toArray metoden er helt ufarlig. Imidlertid, fordi det lar varargs-arrayet flykte til den som ringer, bryter det den andre regelen om safe varargs.
For å se hvordan denne metoden kan være farlig, la oss bruke den i en annen metode:
statisk T [] returnAsIs (T a, T b) {tilbake til Array (a, b); }
Så hvis vi kaller denne metoden:
Streng [] args = returnAsIs ("One", "Two");
Vi vil igjen få en ClassCastException. Her er hva som skjer når vi kaller returnAsIs metode:
- Å sende en og b til toArray metode, må Java opprette en matrise
- Siden Gjenstand[] kan inneholde gjenstander av hvilken som helst type, lager kompilatoren en
- De toArray metoden returnerer den gitte Gjenstand[] til innringeren
- Siden anropssiden forventer a Streng [], kompilatoren prøver å kaste Gjenstand[] til det forventede Streng [], derav ClassCastException
For en mer detaljert diskusjon om haugeforurensning, anbefales det sterkt å lese punkt 32 i Effektiv Java av Joshua Bloch.
6. Konklusjon
Varargs kan få mye kokeplate til å forsvinne i Java.
Og takket være deres implisitte autoboksing til og fra Array, de spiller en rolle i fremtidssikring av koden vår.
Som alltid kan alle kodeeksempler fra denne artikkelen være tilgjengelige i GitHub-depotet vårt.