Varargs v Jave

1. Úvod

Varargs boli predstavené v Java 5 a poskytuje skratku pre metódy, ktoré podporujú ľubovoľný počet parametrov jedného typu.

V tomto článku uvidíme, ako môžeme použiť túto základnú funkciu Java.

2. Pred Varargs

Pred programom Java 5 sme vždy, keď sme chceli odovzdať ľubovoľný počet argumentov, museli odovzdať všetky argumenty v poli alebo implementovať N metód (jeden pre každý ďalší parameter):

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

3. Použitie Varargs

Varargs pomôžte nám vyhnúť sa písaniu štandardného kódu zavedením novej syntaxe, ktorá dokáže spracovať ľubovoľný počet parametrov automaticky - pomocou poľa pod kapotou.

Môžeme ich definovať pomocou štandardnej deklarácie typu, za ktorou nasleduje elipsa:

public String formatWithVarArgs (String ... values) {// ...}

A teraz môžeme našu metódu nazvať ľubovoľným počtom argumentov, napríklad:

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

Ako bolo spomenuté predtým, varargs sú polia, takže s nimi musíme pracovať, rovnako ako s normálnym poľom.

4. Pravidlá

Varargs sú priamo použiteľné. Je však potrebné pamätať na niekoľko pravidiel:

  • Každá metóda môže mať iba jednu varargs parameter
  • The varargs argument musí byť posledným parametrom

5. Znečistenie haldy

Použitím varargs môže viesť k takzvanému halde znečisťovaniu. Zvážte to, aby ste lepšie pochopili znečistenie haldy varargs metóda:

static String firstOfFirst (List ... strings) {List ints = Collections.singletonList (42); Objekt [] objekty = reťazce; objekty [0] = ints; // Reťazce návratu haldy znečistenia [0] .get (0); // ClassCastException}

Ak v teste nazveme túto podivnú metódu:

Reťazec one = firstOfFirst (Arrays.asList ("one", "two"), Collections.emptyList ()); assertEquals ("jeden", jeden);

Dostali by sme ClassCastException aj keď sme tu ani nepoužili žiadne explicitné obsadenia typu:

java.lang.ClassCastException: trieda java.lang.Integer nemôže byť obsadená do triedy java.lang.String

5.1. Bezpečné použitie

Zakaždým, keď používame varargs, kompilátor Java vytvorí pole na uchovanie daných parametrov. V takom prípade kompilátor vytvorí pole s komponentmi generického typu, ktoré budú obsahovať argumenty.

Keď použijeme varargs s generickými typmi, pretože existuje potenciálne riziko výnimky za behu programu, kompilátor Java nás upozorní na možné nebezpečné varargs použitie:

varovanie: [varargs] Možné znečistenie haldy parametrizovaným varargom typu T

The varargs použitie je bezpečné, len ak:

  • V implicitne vytvorenom poli nič neukladáme. V tomto príklade sme uložili a Zoznam v tom poli
  • Nenecháme uniknúť odkazu na vygenerované pole (viac o tom neskôr)

Ak sme si istí, že samotná metóda bezpečne používa varargy, môžeme použiť @SafeVarargs potlačiť varovanie.

Zjednodušene povedané varargs použitie je bezpečné, ak ich použijeme na prenos premenlivého počtu argumentov z volajúceho na metódu a nič viac!

5.2. Únik Varargs Odkaz

Zvážme ďalšie nebezpečné použitie aplikácie varargs:

statický T [] toArray (T ... argumenty) {návratové argumenty; }

Spočiatku by sa mohlo zdať, že toArray metóda je úplne neškodná. Pretože však nechalo varargsové pole uniknúť volajúcemu, porušuje to druhé pravidlo bezpečia varargs.

Aby sme zistili, ako môže byť táto metóda nebezpečná, použite ju v inej metóde:

static T [] returnAsIs (Ta, T b) {návrat do poľa (a, b); }

Ak teda nazveme túto metódu:

Reťazec [] args = returnAsIs ("Jeden", "Dva");

Znovu by sme dostali a ClassCastException. Tu je to, čo sa stane, keď zavoláme returnAsIs metóda:

  • Prejsť a a b do toArray Metóda vyžaduje, aby Java vytvorila pole
  • Keďže Objekt [] môže obsahovať položky ľubovoľného typu, kompilátor ich vytvorí
  • The toArray metóda vráti dané Objekt [] volajúcemu
  • Pretože stránka hovoru očakáva a Reťazec [], kompilátor sa pokúša obsadiť Objekt [] do očakávaného Reťazec [], teda ClassCastException

Pre podrobnejšiu diskusiu o znečistení haldy sa dôrazne odporúča prečítať si položku 32 knihy Effective Java od Joshua Blocha.

6. Záver

Varargs môže v Jave odísť z mnohých variet.

A vďaka ich implicitným autoboxing do A z Pole, zohrávajú úlohu pri zabezpečení nášho kódu v budúcnosti.

Všetky príklady kódov z tohto článku sú ako vždy dostupné v našom úložisku GitHub.


$config[zx-auto] not found$config[zx-overlay] not found