Varargs Java-ban

1. Bemutatkozás

Varargs ben vezették be Java 5 és rövid leírást ad azokról a módszerekről, amelyek tetszőleges számú paramétert támogatnak.

Ebben a cikkben megtudjuk, hogyan használhatjuk ezt a Java alapfunkciót.

2. Előtte Varargs

A Java 5 előtt, amikor tetszőleges számú argumentumot akartunk átadni, át kellett adnunk az összes argumentumot egy tömbben, vagy N metódust kellett végrehajtanunk (egyet minden további paraméterhez):

public String format () {...} public String format (String value) {...} public String format (String val1, String val2) {...}

3. Használata Varargs

Varargs segítsen elkerülni a kazán kód írását az új szintaxis bevezetésével, amely tetszőleges számú paramétert képes automatikusan kezelni - a motorháztető alatt található tömb segítségével.

Meghatározhatjuk őket egy szabványos típusú deklarációval, amelyet egy ellipszis követ:

public String formatWithVarArgs (String ... értékek) {// ...}

És most tetszőleges számú argumentummal hívhatjuk meg módszerünket, például:

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

Mint korábban említettük, varargs tömbök, ezért velük kell dolgozni, ugyanúgy, mint egy normál tömböt.

4. Szabályok

Varargs használata egyszerű. De van néhány szabály, amelyet szem előtt kell tartanunk:

  • Minden módszernek csak egy lehet varargs paraméter
  • A varargs argumentumnak kell lennie az utolsó paraméternek

5. Halomszennyezés

Használata varargs úgynevezett kupacszennyezéshez vezethet. A halomszennyezés jobb megértése érdekében fontolja meg ezt varargs módszer:

statikus String firstOfFirst (List ... stringek) {List ints = Gyűjtemények.singletonList (42); Object [] objektumok = karakterláncok; tárgyak [0] = ints; // Halomszennyezés visszatérő karakterláncai [0] .get (0); // ClassCastException}

Ha ezt a furcsa módszert nevezzük egy teszt során:

Első karakterlánc = firstOfFirst (Tömbök.asList ("egy", "kettő"), Gyűjtemények.emptyList ()); assertEquals ("egy", egy);

Kapnánk egy ClassCastException annak ellenére, hogy itt nem is használtunk explicit típusú szereplőket:

java.lang.ClassCastException: java.lang.Integer osztály nem adható át a java.lang.String osztályba

5.1. Biztonságos használat

Minden alkalommal, amikor használunk varargs, a Java fordító tömböt hoz létre a megadott paraméterek megtartására. Ebben az esetben a fordító létrehoz egy tömböt általános típusú összetevőkkel az argumentumok megtartására.

Amikor használjuk varargs általános típusokkal, mivel fennáll a végzetes futásidejű kivétel kockázata, a Java fordító figyelmeztet minket egy esetleges nem biztonságos varargs használat:

figyelmeztetés: [varargs] Lehetséges kupacszennyezés a paraméterezett vararg típusú T-től

A varargs a használat akkor és csak akkor biztonságos, ha:

  • Az implicit módon létrehozott tömbben nem tárolunk semmit. Ebben a példában valóban tároltunk egy Lista abban a tömbben
  • Nem hagyjuk, hogy a létrehozott tömbre való hivatkozás elkerülje a módszert (erről bővebben később)

Ha biztosak vagyunk benne, hogy maga a módszer biztonságosan használja a varargokat, akkor használhatjuk @SafeVarargs hogy elnyomja a figyelmeztetést.

Leegyszerűsítve: varargs a használat akkor biztonságos, ha változó számú argumentum átadására használjuk őket a hívótól a módszerig, és semmi mást!

5.2. Menekülés Varargs Referencia

Vegyük fontolóra a másik nem biztonságos használatát varargs:

statikus T [] toArray (T ... érvek) {return argumentumok; }

Eleinte úgy tűnhet, hogy a array módszer teljesen ártalmatlan. Mivel azonban a varargs tömb elhagyta a hívót, megsérti a széf második szabályát varargs.

Ha meg szeretné tudni, hogy ez a módszer hogyan lehet veszélyes, használjuk egy másik módszerben:

statikus T [] returnAsIs (T a, T b) {visszatérés Array (a, b); }

Akkor, ha ezt a módszert hívjuk:

Karakterlánc [] args = returnAsIs ("egy", "kettő");

Megint kapnánk egy ClassCastException. Itt történik, mi történik, amikor felhívjuk a returnAsIs módszer:

  • Átmenni a és b hoz array módszerrel a Java-nak létre kell hoznia egy tömböt
  • Mivel a Tárgy[] bármilyen típusú elemet képes tárolni, a fordító létrehoz egyet
  • A array metódus adja vissza az adott Tárgy[] a hívónak
  • Mivel a hívóhely arra számít, hogy a Húr[], a fordító megpróbálja leadni a Tárgy[] a vártnak Húr[], ezért a ClassCastException

A halomszennyezésről szóló részletesebb vita érdekében erősen ajánlott elolvasni Joshua Bloch Effective Java 32. cikkét.

6. Következtetés

Varargs sok kazán lemerülhet a Java-ban.

És, köszönhetően implicit autoboxing ki és vissza Sor, szerepet játszanak a kódunk jövőbiztosításában.

Mint mindig, a cikk összes kódpéldája elérhető a GitHub-adattárunkban.