Java Primitiv versus Objektů

Přehled

V tomto kurzu, ukážeme výhody a nevýhody použití Java primitivní typy a jejich zabalené protějšky.

Java Typ Systému

Java má dvojí typ systému se skládá z primitiv jako int, boolean a referenční typy, jako je Integer, Boolean. Každý primitivní typ odpovídá referenčnímu typu.

každý objekt obsahuje jednu hodnotu odpovídajícího primitivního typu. Třídy wrapper jsou neměnné (takže jejich stav se nemůže změnit, jakmile je objekt postaven) a jsou konečné (takže po nich nemůžeme zdědit).

Pod kapotou, Javě provádí konverzi mezi primitivní a referenční typy, pokud aktuální typ je odlišný od prohlásil:

Integer j = 1; // autoboxingint i = new Integer(1); // unboxing

proces převodu primitivní typ, odkaz se jmenuje autoboxing, opačný proces se nazývá rozbalení.

Klady a Zápory

rozhodnout, jaký objekt má být použit, je založen na tom, co výkon aplikací se snažíme dosáhnout, kolik paměti k dispozici máme, množství dostupné paměti, a to, co výchozí hodnoty bychom měli zvládnout.

Pokud se s žádným z nich nesetkáme, můžeme tyto úvahy ignorovat, i když stojí za to je znát.

3.1. Stopa paměti jedné položky

jen pro informaci mají proměnné primitivního typu následující dopad na paměť:

  • boolean – 1 bit
  • byte – 8 bitů
  • short, char – 16 bitů
  • int, float – 32 bitů
  • long, double – 64 bitů

V praxi se tyto hodnoty mohou lišit v závislosti na Virtuálním Stroji provádění. Například v Oracle VM je booleovský Typ mapován na hodnoty int 0 a 1, takže trvá 32 bitů, jak je popsáno zde: primitivní typy a hodnoty.

proměnné těchto typů žijí v zásobníku, a proto jsou přístupné rychle. Pro podrobnosti doporučujeme náš tutoriál o modelu paměti Java.

referenční typy jsou objekty, žijí na haldě a jsou relativně pomalé. Mají určitou režii týkající se jejich primitivních protějšků.

konkrétní hodnoty režie jsou obecně specifické pro JVM. Zde předkládáme výsledky pro 64-bitové virtuální stroje s těmito parametry:

java 10.0.1 2018-04-17Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

objekt je vnitřní strukturu, můžeme použít Objekt Java Layout tool (viz náš další návod na to, jak se dostat na velikost objektu).

ukazuje se, že jediné instance referenčního typu na této JVM zaujímá 128 bitů až na Long a Double, které zabírají 192 bitů:

  • Boolean – 128 bitů
  • Byte – 128 bitů
  • Krátká, Charakter – 128 bitů
  • Integer, Float – 128 bitů
  • Dlouho, Double – 192 bitů

můžeme vidět, že jediná proměnná typu Boolean zabírá tolik prostoru, kolik 128 primitivní, zatímco jeden Integer proměnná zabírá tolik prostoru jako čtyři int ty.

3.2. Paměťová stopa pro pole

situace se stává zajímavější, pokud porovnáme, kolik paměti zabírá pole uvažovaných typů.

Když jsme se vytvořit pole s různým počtem prvků, pro každý typ, získáme obrázek:

to ukazuje, že typy jsou rozděleny do čtyř rodin s ohledem na to, jak na paměť m(s) závisí na počtu prvků s pole:

  • dlouhé, dvojitá: m(s) = 128 + 64 y
  • short, char: m(s) = 128 + 64
  • byte, boolean: m(s) = 128 + 64
  • zbytek: m (s) = 128 + 64

kde hranaté závorky označují standardní funkci stropu.

překvapivě pole primitivních typů dlouhé a dvojité spotřebovávají více paměti než jejich třídy obalů dlouhé a dvojité.

můžeme vidět, že buď jeden prvek pole primitivních typů jsou téměř vždy dražší (s výjimkou pro long a double) než příslušné referenční typ.

3.3. Výkon

výkon Java kód je poměrně subtilní záležitost, záleží hodně na hardwaru, na kterém kód běží, na kompilátor, který by mohl provádět některé optimalizace, na stav virtuálního stroje, na činnost ostatních procesů v operačním systému.

jak jsme již zmínili, primitivní typy žijí v zásobníku, zatímco referenční typy žijí v haldě. Toto je dominantní faktor, který určuje, jak rychle se objekty dostanou.

prokázat, kolik operací pro primitivní typy jsou rychlejší, než pro wrapper tříd, pojďme vytvořit pět milionů prvku pole, v němž všechny prvky jsou stejné s výjimkou poslední; pak provádíme vyhledávání pro který prvek:

while (!pivot.equals(elements)) { index++;}

a porovnat výkon této operace pro případ, kdy pole obsahuje proměnné primitivních typů a pro případ, kdy to obsahuje objekty, referenční typy.

použijeme známý JMH benchmarking tool (viz náš návod na to, jak ho použít), a výsledky vyhledávání operace lze shrnout do této tabulky:

Dokonce i pro takové jednoduché operace, můžeme vidět, že je zapotřebí více času k provedení operace pro wrapper tříd.

v případě složitějších operací, jako je sčítání, násobení nebo dělení, může rozdíl v rychlosti vyletět.

3.4. Výchozí hodnoty

výchozí hodnoty primitivních typů jsou 0 (v odpovídající reprezentaci, tj. 0, 0.0d atd.) pro číselné typy, false pro booleovský Typ, \u0000 pro typ char. Pro třídy obalů je výchozí hodnota null.

to znamená, že primitivní typy mohou získat hodnoty pouze ze svých domén, zatímco referenční typy mohou získat hodnotu (null), která v jistém smyslu do jejich domén nepatří.

ačkoli se nepovažuje za dobré nechat proměnné neinicializované, někdy můžeme přiřadit hodnotu po jejím vytvoření.

v takové situaci, kdy má primitivní typová proměnná hodnotu, která se rovná její typové výchozí, bychom měli zjistit, zda byla proměnná skutečně inicializována.

neexistuje žádný takový problém s proměnnými třídy wrapper, protože hodnota null je zcela evidentní známkou toho, že proměnná nebyla inicializována.

použití

jak jsme viděli, primitivní typy jsou mnohem rychlejší a vyžadují mnohem méně paměti. Proto bychom je mohli chtít raději používat.

na druhé straně současná specifikace jazyka Java neumožňuje použití primitivních typů v parametrizovaných typech (generik), ve sbírkách Java nebo v rozhraní Reflection API.

Když naše aplikace potřebuje kolekce s velkým počtem prvků, měli bychom zvážit použití polí s co nejúspornějším typem, jak je znázorněno na grafu výše.

Závěr

tento kurz, jsme dokládá, že objekty v Javě jsou pomalejší a mají větší paměť dopad než jejich primitivní analogy.

jako vždy lze úryvky kódu nalézt v našem úložišti na Githubu.

začněte s Jarní 5 a na Jaře Boot 2, a to prostřednictvím Naučit Jarní kurz:

>>

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *