• Převod primitivních typů. Typ casting v Javě

    Každý výraz v Javě má ​​typ, který je určen strukturou výrazu a typy jeho operandů (konstanty, proměnné a metody). Někdy však můžeme potřebovat explicitně převést výraz na jiný typ. V některých situacích bude běhový systém Java tyto převody implicitně provádět.

    Převod typu Ti na typ T2 umožňuje, aby výraz typu T1 byl v době kompilace považován za výraz typu T2. V některých případech se jedná o čistě syntaktickou konstrukci, která neovlivňuje generovaný kód, v jiných vyžaduje konverze typu další akce za běhu pro změnu hodnoty výrazu nebo dodatečné kontroly správnosti použité konverze. Příklady:

    • Převod typu int podle typu dlouho vyžaduje, aby byla 32bitová celočíselná hodnota za běhu rozšířena na 64bitové celé číslo. V tomto případě nedochází ke ztrátě informací.
    • Převod typu plovák podle typu dlouho vyžaduje netriviální převod 32bitové plovoucí hodnoty na 64bitové celé číslo za běhu. V závislosti na počáteční hodnotě může nebo nemusí dojít ke ztrátě informací.
    • Převod z Thread na Object je přímočarý: protože třída Thread je potomkem třídy Object, jakýkoli odkaz na objekt typu Thread je automaticky odkazem na objekt typu Object .
    • Převod z objektu na vlákno vyžaduje kontrolu za běhu. Pokud je převáděný odkaz skutečně odkazem na objekt typu Thread , je vrácen jako výsledek převodu, jinak je vyvolána výjimka.

    5.4.1.1. Rozšiřující transformace čísel

    Rozšiřující transformace čísel Jedná se o převody z číselného typu na "větší" číselný typ, které jsou považovány za bezpečné, protože neztrácejí hodnotu převáděné hodnoty. Takové transformace v Javě jsou:

    • transformace byte PROTI krátký, int, dlouho, plovák A dvojnásobek;
    • transformace krátký PROTI int, dlouho, plovák A dvojnásobek;
    • transformace char PROTI int, dlouho, plovák A dvojnásobek;
    • transformace int PROTI dlouho, plovák A dvojnásobek;
    • transformace dlouho PROTI plovák A dvojnásobek;
    • transformace plovák PROTI dvojnásobek.

    Ve skutečnosti převod celočíselné hodnoty na plovoucí může vést ke ztrátě přesnosti, tj. ztrátě významných číslic. Takže další příklad

    Test třídy ( public static void main(String args) ( int velkéČíslo = 1234567890; přibližné plovoucí = velkéČíslo; System.out.println(přibližné); ) )

    zobrazí řetězec 1234567936 . To je způsobeno tím, že při převodu int PROTI plovák výsledná hodnota je 1,2345679E9 vzhledem k tomu, že mantisa čísel jako plovák obsahuje pouze 8 desetinných číslic (zde pro správné fungování měla by být použita konverze typu dvojnásobek). Běhový systém však nikdy negeneruje chyby při provádění uvedených transformací.

    5.4.1.2. Zužující transformace čísel

    Zužující transformace čísel Jedná se o převody z číselného typu na "menší" číselný typ, což může vést ke ztrátě velikosti i ke ztrátě přesnosti. Takové transformace v Javě jsou:

    • transformace byte PROTI char;
    • transformace krátký PROTI byte A char;
    • transformace int PROTI byte, krátký A char;
    • transformace dlouho PROTI byte, krátký, int A char;
    • transformace plovák PROTI byte, krátký, int, dlouho A char;
    • transformace dvojnásobek PROTI byte, krátký, int, dlouho, plovák A char;

    Nebudeme se zde podrobně zabývat pravidly, podle kterých k těmto transformacím dochází, protože jsou intuitivně srozumitelná, ale formálně značně těžkopádná. Při jejich aplikaci je důležité pamatovat na to, že Java na rozdíl od jiných jazyků negeneruje chyby přetečení nebo podtečení, takže kontrola nad správností transformací je plně na programátorovi.

    5.4.1.3. Rozšíření transformací odkazu

    Rozšíření transformací odkazu Jedná se o převody z odvozených referenčních typů na jejich předchůdce, které nevyžadují žádnou běhovou akci a nikdy negenerují chyby. Takové transformace v Javě jsou:

    • převod jakékoli třídy nebo rozhraní na svého předka (zejména na typ Object);
    • převod třídy na rozhraní, které implementuje;
    • převod libovolného pole na typ Object nebo typ Cloneable ;
    • převod pole typu S na pole typu T, pokud S a T jsou referenční typy a převod z S na T se rozšiřuje;
    • převod typu null na libovolný typ odkazu.

    5.4.1.4. Transformace zužujících se odkazů

    Transformace zužujících se odkazů jsou převody odvozených referenčních typů na jejich potomky. Tyto převody vyžadují kontrolu legitimity za běhu a mohou způsobit výjimku ClassCastException . Takové transformace v Javě jsou:

    • převod jakékoli třídy na jejího potomka (zejména převod typu Object na jakoukoli jinou třídu);
    • převod třídy na rozhraní, když třída není konečná a neimplementuje dané rozhraní (zejména převod typu Object na libovolné rozhraní);
    • převod typu Object na libovolné pole;
    • převod jakéhokoli rozhraní na třídu, která není konečná;
    • transformace jakéhokoli rozhraní na třídu, která je konečná a implementuje toto rozhraní;
    • převod rozhraní J na rozhraní K, když J není potomkem K a v J a K není deklarována žádná metoda se stejnou signaturou, ale různými typy výsledků;
    • převod z pole typu S na pole typu T, pokud S a T jsou referenční typy a převod z S na T se zužuje.

    5.4.1.5. Konverze řetězců

    Jakýkoli výraz v Javě, včetně nula, lze převést na typ String .

    5.4.1.6. Neplatné konverze

    Následující typy konverzí jsou v Javě zakázány:

    • převod libovolného referenčního typu na jakýkoli primitivní typ;
    • převod libovolného primitivního typu na jakýkoli referenční typ jiný než String ;
    • konverze typu null na libovolný primitivní typ;
    • převody na nulový typ nebo typ booleovský;
    • typové konverze booleovský na jakýkoli jiný typ než String ;
    • převod jedné třídy na jinou, pokud žádná z nich není předkem druhé třídy (kromě převodu na typ String);
    • převod třídy na rozhraní, pokud je třída konečná a neimplementuje se dané rozhraní;
    • převod třídy na pole, pokud třída není Object ;
    • převod rozhraní na třídu, která je konečná a neimplementuje dané rozhraní (kromě převodu na typ String);
    • převod rozhraní J na rozhraní K, pokud existuje metoda deklarovaná v J i K se stejnou signaturou, ale různými typy výsledků;
    • převod pole na jinou třídu než Object a String ;
    • převod pole na jiné rozhraní než Cloneable;
    • převod pole typu S na pole typu T, pokud je převod z S na T zakázán

    5.4.2. Kontexty transformace

    5.4.2.1. Konverze přiřazení

    Konverze přiřazení nastane, když je hodnota výrazu přiřazena proměnné. V tomto případě je typ výrazu převeden na typ proměnné. Při přiřazování jsou vždy možné převody typu rozšíření (číselné i referenční). Zužující převod je možný pouze při splnění následujících podmínek:

    • proměnná má typ byte, krátký nebo char;
    • hodnota výrazu je konstanta typu int, která spadá do rozsahu možných hodnot proměnné.

    Například bajt příkazu x = 123; platný, od konstanty 123 (typu int) leží v rozsahu povolených hodnot typu byte.

    Pokud typ výrazu nelze převést na typ proměnné, kompilátor vygeneruje chybu. Jinak říkáme, že typ výrazu přiřazení kompatibilní s typem proměnné. Takže další úryvek

    Krátké s = 123; char c = s; // generuje chybu kompilace

    vygeneruje chybu, protože typy char A krátký jsou přiřazení nekompatibilní podle výše uvedených definic (první je implementováno jako 16bitová slova bez znaménka a druhé je se znaménkem).

    5.4.2.2. Argumenty metody konverze

    Argumenty metody konverze nastane, když jsou skutečné hodnoty argumentů převedeny na typ parametrů metody nebo konstruktoru, když je volána. V tomto případě jsou převody typu rozšíření (číselné i referenční typy) vždy možné a převody typu zúžení nejsou povoleny. Důvody posledního zákazu lze vysvětlit na následujícím příkladu:

    Class Test ( static int m(byte a, int b) ( return a + b; ) static int m(short a, short b) ( return a - b; ) public static void main(String args) ( System.out. println( m(1, 2)); // vygeneruje chybu kompilace ) )

    Třída Test zde obsahuje dvě stejnojmenné metody, které se liší pouze typy parametrů. Pokud by byly v Javě povoleny konverze zužujících argumentů, pak by běhové prostředí muselo určit, na kterou z těchto metod se volání m(1, 2) vztahuje. Aby se podobným nejasnostem vyhnuli, vyřešili jazykoví návrháři problém radikálně: zakázali taková volání metod. V této situaci, abychom mohli volat například první metodu, musíme explicitně určit typ prvního operandu (druhý již má typ int), konkrétně m((byte)1, 2) .

    5.4.2.3. Převést na řetězec

    Převést na řetězec dochází pouze v jednom případě: když je binární operace + aplikována na dva operandy, z nichž jeden je typu String . V této situaci je druhý operand také převeden na typ String a výsledkem operace je zřetězení výsledných řetězců. Tento proces je podrobněji popsán v kap. 5.14.

    5.4.2.4. Explicitní konverze typu

    Explicitní konverze typu dochází, když je přetypování typu explicitně aplikováno na operand. V této situaci lze použít všechny typy převodů typů popsané výše, kromě převodu na řetězec. Pokus o explicitní převod na typ, který je výše označen jako zakázaný, způsobí chybu kompilace. Je také možné vyvolat ClassCastException za běhu, pokud je zadané přetypování neplatné.

    5.4.3. Typové převody číselných operandů

    Převod typů v procesu výpočtu číselných výrazů má řadu funkcí. Jde o dva případy: transformace operandů v unárních operacích a v binárních operacích.

    Před provedením unární operace:

    • pokud je operand typu byte, krátký nebo char, převede se na typ int;
    • jinak se jeho typ nemění.

    Před provedením binární operace:

    • pokud jeden z operandů typu dvojnásobek, pak se druhý také převede na typ dvojnásobek;
    • plovák, pak se druhý také převede na typ plovák;
    • jinak, pokud jeden z operandů typu dlouho, pak se druhý také převede na typ dlouho;
    • jinak jsou oba operandy převedeny na typ int.

    Jde o poměrně rozsáhlé téma, ale pokusíme se jej pokrýt co nejúplněji a nejkompaktněji. Částečně jsme se tohoto tématu již dotkli, když jsme se podívali na primitivní typy Java.

    Java umožňuje převody mezi celočíselnými a plovoucí desetinnou čárkou. Můžete také převést celočíselné hodnoty a hodnoty s plovoucí desetinnou čárkou na hodnoty znaků a naopak, protože každý znak odpovídá číslici Unicode. Ve skutečnosti je booleovský typ jediným primitivním typem v Javě, který nelze převést na jiný primitivní typ. Také žádný jiný primitivní typ nelze převést na booleovský.

    Převod typů v Javě je dvojího druhu: implicitní A explicitní.

    Konverze implicitního typu proveden, pokud jsou splněny následující podmínky:

    1. Oba typy jsou kompatibilní
    2. Délka cílového typu je větší nebo rovna délce zdrojového typu

    Ve všech ostatních případech použijte explicitní převod typu.

    Existují také dva typy transformací:

    1. Rozšíření konverze
    2. Zužující se konverze

    Rozšíření transformace ( rozšiřující konverze) dochází, když je hodnota jednoho typu převedena na širší typ s větším rozsahem platných hodnot. Java provádí rozšiřující převody automaticky, například pokud přiřadíte literál typu int typ proměnné double nebo hodnota proměnné typu char na proměnnou typu int. Implicitní konverze je vždy rozšiřujícího typu.

    Ale mohou zde být nějaké malé hrábě. Pokud je například hodnota int převedena na plovoucí hodnotu. A hodnota int v binární reprezentaci má více než 23 platných bitů, pak je možná ztráta přesnosti, protože typ float má 23 bitů pro celočíselnou část. Všechny nízké bity Hodnoty int, které se nevejdou do 23bitové mantisy plováku, budou vyřazeny, takže ačkoli je zachováno pořadí čísel, přesnost je ztracena. Totéž platí pro převod long na double.

    Rozšiřující se transformace Typy Java lze zobrazit i takto:

    Plné čáry označují konverze provedené bez ztráty dat. Přerušované čáry označují, že během převodu může dojít ke ztrátě přesnosti.

    Stojí za to trochu vysvětlit, proč se například typ bajtu automaticky (ne explicitně) převádí na typ char, ačkoli typ bajtu je široký 8 bitů a typ char je široký 16 bitů, totéž platí pro převod krátký typ char. Je to proto, že byte a short jsou podepsané datové typy, zatímco char je bez znaménka. Proto v tento případ musíte použít explicitní přetypování, protože musíte explicitně sdělit kompilátoru, že víte, co chcete a jak bude při převodu na znak naloženo se znaménkovým bitem bajtu a krátkými typy.

    Chování hodnoty char je ve většině případů stejné jako u hodnoty typu integer, takže hodnotu char lze použít všude, kde je vyžadována hodnota int nebo long. Připomeňme však, že typ char je bez znaménka, takže se chová odlišně od typu short, i když rozsah obou typů je 16 bitů.

    krátký s = ( krátký ) 0xffff; // Tyto bity představují číslo -1
    char C = "\ffff"; // Stejné bity představují znak unicode
    int i1 = s; // Převod z short na int dává -1
    int i2 = C; // Převod char na int dává 65535

    Zužující se transformace ( zužující konverze) nastane, pokud je hodnota převedena na hodnotu typu, jehož rozsah není širší než původní hodnota. Zužující převody nejsou vždy bezpečné: například převod celočíselné hodnoty 13 na bajt dává smysl, ale převod 13 000 na bajt je nerozumný, protože bajt může ukládat pouze čísla mezi −128 a 127. Vzhledem k tomu, že data mohou být během zužujícího převodu ztracena, Objekty kompilátoru Java pro jakoukoli takovou konverzi, i když převáděná hodnota spadá do užšího rozsahu zadaného typu:

    int i = 13 ;
    byte b = i ; // Kompilátor tento výraz nevyřeší

    Jedinou výjimkou z pravidla je přiřazení celočíselného literálu (hodnoty int) k bajtu nebo krátké proměnné, pokud literál odpovídá rozsahu proměnné.

    Zužující převod je vždy explicitní převod typu..

    Explicitní konverze primitivních typů

    Explicitní operátor převodu typu, přesněji přetypování typu, jsou závorky, uvnitř kterých je uveden typ, na který se převod provádí - (typ). Například:

    int i = 13 ;
    byte b = ( byte ) i ; // Vynucený převod int na bajt
    i = ( int ) 13.456 ; // Vynucená konverze literálu dvojitého typu na int 13

    Nejčastěji se používá odlévání primitivního typu pro převod hodnot s plovoucí desetinnou čárkou na celá čísla. V čem zlomková část hodnoty s pohyblivou řádovou čárkou se jednoduše zahodí(to znamená, že hodnota s pohyblivou řádovou čárkou je zaokrouhlena směrem k nule, nikoli k nejbližšímu celému číslu). V podstatě vzít pouze celočíselnou část skutečný typ a je již přetypován na cílový celočíselný typ.

    Při přivedení prostornějšího celočíselný typ na méně kapacitní jsou vysoké bity jednoduše vyřazeny. To je v podstatě stejné jako modulo dělení hodnoty přetypování rozsahem cílového typu (například 256 pro bajt).

    Příliš velké zlomkové číslo se při přetypování na celé číslo změní na MAX_VALUE nebo MIN_VALUE.

    Příliš velký dvojnásobek při přivedení do plovák se změní na Float.POSITIVE_INFINITY nebo Float.NEGATIVE_INFINITY.

    Níže uvedená tabulka je mřížka, kde jsou pro každý primitivní typ uvedeny typy, na které je lze převést, a způsob převodu. Dopis N v tabulce znamená, že převod není možný. Dopis Y znamená rozšiřující konverzi, která se provádí automaticky. Dopis S znamená zužující konverzi, která vyžaduje explicitní obsazení. Konečně, Y* znamená automatický převod rozšíření, během kterého může hodnota ztratit některé z nejméně významných bitů. To se může stát při převodu int nebo long na float nebo double. Typy s pohyblivou řádovou čárkou mají větší rozsah než celočíselné typy, takže int nebo long mohou být reprezentovány jako float nebo double. Typy s plovoucí desetinnou čárkou jsou však přibližná čísla a nemusí vždy obsahovat tolik platných číslic v mantise jako celočíselné typy.

    Automatické rozšiřování typu ve výrazech

    Za zmínku také ještě jednou stojí automatické povyšování (rozšiřování) typů ve výrazech. Už jsme se s tím setkali, když jsme uvažovali o celočíselných datových typech a operacích s nimi, ale i tak se to zde vyplatí připomenout, aby to bylo ještě lépe pochopitelné a navíc to přímo s tímto tématem souvisí. V níže uvedeném příkladu znak @ + , , * , / a tak dále.

    Tedy všechny celočíselné literály ve výrazech a také typy byte, krátký A char rozšířit na int . Pokud, jak je popsáno výše, výraz neobsahuje jiné, více velké typyúdaje ( dlouho, plovák nebo dvojnásobek). Výše uvedený příklad tedy způsobí chybu kompilace, protože proměnná C má typ byte, a výraz b+1, jako výsledek automatického povýšení, je typu int.

    Implicitní přetypování v kombinovaných přiřazovacích výrazech

    Přestože se tato část zmiňuje o implicitní konverzi typu (přetypování), uvedli jsme zde její vysvětlení, protože v tomto případě funguje také automatické rozšiřování typu ve výrazech a poté implicitní přetypování. Tady je baletní sbor. Níže uvedený příklad to, myslím, objasní. Stejně jako v předchozím výkladu, znak @ znamená například jakýkoli platný operátor + , , * , / a tak dále.

    To by mělo být vysvětleno na jednoduchém příkladu:

    byte b2 = 50 ;
    b2 = b2 * 2 ; // se nezkompiluje
    b2 *= 2 ; //kompiluje, i když je ekvivalentní b2 = b2 * 2

    Druhý řádek v příkladu se nezkompiluje kvůli automatickému rozšíření typu ve výrazech, protože výraz b2*2 má typ int, protože dochází k automatickému rozšíření typu (celočíselné literály ve výrazech jsou vždy int). Třetí řádek se snadno zkompiluje, protože v něm bude fungovat implicitní přetypování v kombinovaném přiřazovacím výrazu.

    Boxing/unboxing - převod primitivních typů na obalové objekty

    Box a unboxing je také docela obsáhlé téma, ale je celkem jednoduché.

    V podstatě box a unboxing je převod primitivních typů na obalové objekty a naopak.

    Pro objekty wrapper primitivních typů platí vše, co bylo řečeno výše.

    Třídy Wrapper byly zmíněny v tabulkách při analýze každého z primitivních typů. Pak už to ale byla jen zmínka v tabulce.

    Takže pro každý primitivní typ existuje jeho starší bratr, a ten vůbec není primitivní, ale je to skutečná třída s poli a metodami. A pro každý takový pár je možný automatický převod.

    Obvykle, pokud má program hodně matematických výpočtů, je lepší používat primitivní typy, protože je to rychlejší a ekonomičtější z hlediska zdrojů, ale někdy je potřeba převést primitivní typ na objekt.

    Uvedu jednoduchý příklad:

    int i3 ;
    byte b2 = 3 ;
    bajtů myB ;
    myB= b2;
    myB++;
    b2= myB;
    i3= myB;

    Pokud ještě není jasné, proč je to potřeba, pak to není děsivé, stačí uvázat uzel na památku.

    Poslední aktualizace: 29.10.2018

    Každý základní typ data zabírají určitý počet bajtů paměti. To ukládá omezení operací, ve kterých Různé typy data. Zvažte následující příklad:

    int a = 4; byte b = a; //! Chyba

    V tomto kódu narazíme na chybu. Ačkoli jak typ byte, tak typ int představují celá čísla. Navíc hodnota proměnné a, která je přiřazena proměnné typu bajt, je dobře v rozsahu hodnot pro typ bajtu (od -128 do 127). Narazíme však na chybu při kompilaci. Protože v tomto případě se snažíme přiřadit nějaká data, která zabírají 4 bajty, do proměnné, která zabírá pouze jeden bajt.

    Program však může vyžadovat provedení takové konverze. V tomto případě musím použít operaci převodu typu (operace ()):

    int a = 4; byteb = (byte)a; // převod typu: z typu int na typ byte System.out.println(b); // 4

    Operace převodu typu zahrnuje uvedení typu v závorkách, na který má být hodnota převedena. Například v případě operace (byte)a se datový typ int převede na typ byte. Ve výsledku dostaneme hodnotu typu byte.

    Explicitní a implicitní konverze

    Když jsou data zapojena do jedné operace odlišné typy, není vždy nutné použít operaci převodu typu. Některé typy transformací se provádějí implicitně, automaticky.

    Automatické převody

    Šipky na obrázku ukazují, které typy převodů lze provádět automaticky. Přerušované šipky ukazují automatické převody se ztrátou přesnosti.

    Automaticky vyráběno bez problémů rozšiřující se transformace(rozšíření) - rozšiřují reprezentaci objektu v paměti. Například:

    Byte b = 7; int d = b; // převod z bajtu na int

    V tomto případě je hodnota typu byte, která zabírá 1 bajt v paměti, rozšířena na typ int, který zabírá 4 bajty.

    Rozšíření automatických transformací představují následující řetězce:

    byte -> short -> int -> long

    int -> double

    krátký -> plovoucí -> dvojitý

    char -> int

    Automatická ztráta přesných převodů

    Některé převody lze provádět automaticky mezi datovými typy stejné bitové hloubky nebo dokonce z datového typu s větší bitovou hloubkou na datový typ s menší bitovou šířkou. Jedná se o následující řetězce převodů: int -> float , long -> float a long -> double jsou randomizovány bez chyb, ale při převodu se můžeme setkat se ztrátou informací.

    Například:

    Int a = 2147483647; plovák b = a; // z int do float System.out.println(b); // 2,14748365E9

    Explicitní konverze

    Ve všech ostatních převodech primitivních typů je operace převodu typu explicitně použita. Obvykle se jedná o zužující převody (zúžení) z typu s větší bitovou hloubkou na typ s nižší bitovou šířkou:

    Dlouhé a = 4; int b = (int) a;

    Ztráta dat během převodu

    Při použití explicitních převodů se můžeme setkat se ztrátou dat. Například následující kód pro nás nebude mít žádné problémy:

    Int a = 5; byte b = (byte) a; System.out.println(b); // 5

    Číslo 5 je dobře v rozsahu hodnot typu byte, takže po převodu bude proměnná b rovna 5. Co se ale stane v následujícím případě:

    Int a = 258; byte b = (byte) a; System.out.println(b); // 2

    Výsledkem bude číslo 2. V tomto případě je číslo 258 mimo rozsah pro typ bajtu (od -128 do 127), takže hodnota bude zkrácena. Proč je výsledek právě číslo 2?

    Číslo a, které je 258, v binární systém se bude rovnat 00000000 00000000 00000001 00000010. Hodnoty typu byte zabírají pouze 8 bitů v paměti. Proto je binární reprezentace int zkrácena na pravých 8 číslic, tj. 00000010 , což v desítková soustava dává číslo 2.

    Zkrácení racionálních čísel na celá čísla

    Při převodu hodnot s plovoucí desetinnou čárkou na celočíselné hodnoty je zlomková část zkrácena:

    Dvojité a = 56,9898; intb = (int)a;

    Zde by hodnota b byla 56, i když 57 by bylo blíže 56,9898. Abyste se takovým incidentům vyhnuli, musíte použít funkci zaokrouhlování, která je v matematické knihovně Java:

    Dvojité a = 56,9898; int b = (int)Math.round(a);

    Transakční transformace

    Není neobvyklé, že na hodnoty různých typů musíte použít různé operace, jako je sčítání a součin. I zde platí některá pravidla:

      pokud je jeden z operandů operace typu double , pak se druhý operand také převede na typ double

      pokud není splněna předchozí podmínka a jeden z operandů operace je typu float , pak se druhý operand převede na typ float

      pokud nejsou splněny předchozí podmínky, jeden z operandů operace je typu long , pak se druhý operand převede na typ long

      jinak se všechny operandy operace převedou na typ int

    Příklady transformace:

    Int a = 3; dvojité b = 4,6; dvojité c = a+b;

    Vzhledem k tomu, že do operace je zapojena hodnota typu double, je druhá hodnota také přetypována na typ double a součet dvou hodnot a + b bude představovat typ double.

    Další příklad:

    Byte a = 3; krátké b = 4; byte c = (byte)(a+b);

    Dvě proměnné typu byte a short (nikoli double, float nebo long), takže se po sečtení převedou na typ int a jejich součet a+b představuje hodnotu int. Pokud tedy tento součet přiřadíme proměnné typu byte, pak musíme znovu provést převod typu na byte.

    Pokud jsou data typu char zapojena do operací, jsou převedena na int:

    Int d = "a" + 5; System.out.println(d); // 102

    Někdy nastanou situace, kdy je potřeba přiřadit hodnotu proměnné jednoho typu proměnné jiného typu. Například:

    Příklad 1: Přiřazení hodnoty proměnné jednoho typu k jinému

    int i = 11; byte b = 22; i = b;

    V Javě existují 2 typy transformací - automatická konverze (implicitní) A přetypování (explicitní konverze).

    1. Automatická konverze

    Zvažte první automatickou konverzi. Pokud jsou oba typy kompatibilní, jejich převod provede automaticky Java. Například hodnota jako byte lze vždy přiřadit k proměnné typu int , jak je ukázáno v příkladu 1.

    Pro automatická konverze typ musí splňovat dvě podmínky:

    • oba typy musí být kompatibilní
    • délka cílového typu musí být větší než délka zdrojového typu

    V tomto případě se to stane expanzní konverze.

    Následující diagram ukazuje rozšiřující konverzi v Javě:

    Plné čáry označují konverze provedené bez ztráty dat. Přerušované čáry označují, že během převodu může dojít ke ztrátě přesnosti.

    Například datový typ int je vždy dostatečně velký, aby pojal všechny platné hodnoty typu byte , takže v tomto případě nejsou vyžadovány žádné explicitní operátory přetypování. Z hlediska převodu rozšíření jsou číselné datové typy, včetně integer a floating point, vzájemně kompatibilní. Zároveň nedochází k automatickým převodům číselné typy podle typu char nebo booleovský . Typy char A booleovský také vzájemně nekompatibilní.

    Stojí za to trochu vysvětlit, proč např. typ byte není automaticky (implicitně) převeden na typ char , i když typ byte má šířku 8 bitů a char - 16, totéž platí pro konverzi typu krátký PROTI char . To se děje, protože byte A krátký podepsané datové typy a char nepodepsaný. Proto v tomto případě musíte použít explicitní přetypování, protože kompilátor musí výslovně uvést, že víte, co chcete a jak bude znaménkový bit typů zpracován. byte A krátký při převodu na typ char .

    Typ Hodnota Chování char ve většině případů se shoduje s chováním hodnoty typu integer, tedy hodnoty typu char lze použít všude tam, kde jsou požadovány hodnoty int nebo dlouho . Připomínáme však, že typ char je bez znaménka, takže se chová odlišně od typu krátký , i když rozsah obou typů je 16 bitů.

    2. Casting

    Přes veškerou pohodlnost automatické konverze typů není schopen uspokojit všechny naléhavé potřeby. Například, co když hodnota typu int musí být přiřazena k proměnné typu byte ? Tento převod nebude proveden automaticky z důvodu délky typu byte méně než typ int . Někdy se tento druh transformace nazývá zužující transformace, protože hodnota je jasně zúžena, aby se vešla do cílového datového typu.

    Chcete-li převést dva nekompatibilní typy dat, musíte použít přetypování. Přetypování je pouze explicitní konverze typu. Obecná forma odlévání typu je následující:

    (target_type) value

    kde parametr target_type označuje typ, na který má být zadaná hodnota převedena.

    Příklad 2: Odlévání

    Například v následujícím fragmentu kódu zadejte int obsazení na typ byte:

    Int i = 11; byte b = 22; b = (byte)i;

    Příklad 3: Převod hodnot s plovoucí desetinnou čárkou na celá čísla

    Podívejme se na příklad převodu hodnot s plovoucí desetinnou čárkou na celá čísla. V tomto příkladu je zlomková část hodnoty s pohyblivou řádovou čárkou jednoduše zahozena (operace zkrácení):

    Dvojité d = 3,89; int a = (int) d; //Výsledek bude 3

    Příklad 4: Převod typu Larger Integer na typ Smaller Integer

    Při přetypování prostornějšího celočíselného typu na méně prostorný celočíselný typ se vysoké bity jednoduše zahodí:

    int i = 323; byte b = (byte) i; //Výsledek bude 67

    Příklad 5: Převod většího floatu na menší celé číslo

    Při přetypování větší hodnoty s plovoucí desetinnou čárkou na celé číslo jsou nejvýznamnější bity zkráceny a vyřazeny:

    Dvojité d = 389889877779,89; krátké s = (krátké) d; //Výsledek bude -1

    3. Automatické prosazování typů ve výrazech

    Kromě operací přiřazení lze ve výrazech provádět také určité převody typů.

    V jazyk Java platí následující pravidla:

    1. Pokud je jeden operand typu dvojnásobek dvojnásobek.
    2. plovák, druhý je také převeden na typ plovák.
    3. Jinak, pokud je jeden operand typu dlouho, druhý je také převeden na typ dlouho.
    4. Jinak jsou oba operandy převedeny na typ int.
    5. Kombinované přiřazovací výrazy (+=,-=,*=,/=) není nutné přetypovat.

    Zde je příklad:

    Příklad 6: Automatická podpora typu ve výrazech

    Při násobení proměnné b1 ( byte) dne 2 ( int) výsledek bude podobný int. Proto při pokusu o přiřazení výsledku do proměnné b2 ( byte) vygeneruje chybu kompilace. Ale při použití kombinovaného operátoru přiřazení (*=) tento problém nenastává.

    Byte b1 = 1; byte b2 = 2 * b1; //Chyba kompilace int i1 = 2 * b1; b2 *= 2;

    Příklad 7: Automatická podpora typu ve výrazech

    Následující příklad také vygeneruje chybu kompilace - navzdory skutečnosti, že čísla mají rádi byte, výsledkem operace bude typ int, ale ne krátký.

    Public class IntegerDemo1 ( public static void main(String args) ( byte b1 = 50, b2 = -99; short k = b1 + b2; //chyba kompilace System.out.println("k=" + k); ) )

    Příklad 8: Automatická podpora typu ve výrazech

    Tento příklad je podobný předchozímu, ale je použita operace kombinovaného přiřazení, při které dochází k přetypování automaticky.

    Public class IntegerDemo2 ( public static void main(String args) ( byte b1 = 50, b2 = -99; b1 += b2; System.out.println("b1=" + b1); ) )

    Náš poslední článek jsme ukončili tím, že jsem vám slíbil, že vám povím, jaké typy se dají odlévat a jak se to všechno dělá. Začněme.

    Obsazení v aritmetických výrazech se provádí automaticky.

    byte->short->int->long->float->double

    Pokud jsou operandy a a b kombinovány s binárním operátorem (probereme to níže), oba operandy se před provedením převedou na data stejného typu, a to následovně:

    • Pokud je jeden z operátorů typu double, druhý se také převede na double;
    • Pokud je jeden z operátorů typu float, druhý se také převede na float;
    • Pokud je jeden z operátorů typu long, druhý se také převede na long;
    • Pokud je jeden z operátorů typu int, druhý se také převede na int;

    Povolené převody typů

    Plné čáry ukazují transformaci provedenou bez ztráty informace. Tato konverze se provádí implicitně. Transformace, kde může dojít ke ztrátě informace, se nazývají casting. Jsou znázorněny přerušovanými čarami. Pokud na obrázku nejsou žádné řádky na datový typ, pak je takový převod nemožný. Transformace se ztrátou informací musí být prováděny velmi opatrně. Jak tedy můžete ztratit významnou část dat a přesto může program fungovat správně.

    Abychom zúžili kasty, je nutné to udělat explicitně. Například: byte b = (byte)128; cast int do typu byte.

    Navrhuji uvést několik příkladů.

    Možná tomuto kódu trochu nerozumíte, protože jsem ještě nevysvětlil, co je to kompilátor, konstanty atd. Dále na tréninku vám vše řeknu, i když jsem to měl udělat dříve. A nyní chci popsat, jaká pravidla by měla mít jména proměnných.

    • Názvy proměnných nemohou začínat číslicí, nelze je používat ve jménech jako symboly aritmetiky a logické operátory, stejně jako znak '#'.
    • Použití znaků '$' nebo '_' je přijatelné, včetně první pozice a jména.
    • Proměnná primitivního typu deklarovaná jako člen třídy (globální proměnná) je standardně nastavena na nulu.
    • Pokud je proměnná v metodě deklarována jako lokální proměnná, musí být před použitím inicializována. Protože místní proměnné nejsou ve výchozím nastavení inicializovány. To znamená, že nemůžete deklarovat lokální proměnnou a nechat ji neinicializovanou. Tedy takto: int i;. Pokud to uděláte v metodě, kompilátor vás požádá o nastavení výchozí hodnoty, zatímco při vytváření takové proměnné jako člena třídy (global) ji kompilátor sám nastaví na 0.
    • Rozsah a životnost proměnné je omezena blokem (), ve kterém je deklarována. Pokud jste vytvořili proměnnou uvnitř metody (jak jsme to udělali v příkladech), nemůžete ji použít mimo metodu, protože metoda je oddělena závorkami (). Globální proměnná je viditelná ve všech blocích.
    • Je také zakázáno používat vyhrazená slova Java. Seznam všech klíčová slova je vidět na obrázku níže.

    A protože jsem se v tomto článku dotkl výrazu binárního operátoru, navrhuji zvážit operátory v Javě. Navíc těch teorií není tolik.

    Java má několik typů operátorů: jednoduché přiřazení, aritmetický, unární, rovný a relační, podmíněný, porovnání typů, bitový a bitový posun.

    Spousta buzzwords, ale tento obrázek vše vysvětlí velmi jednoduše:

    Nejprve použijeme bitové porovnávání, přiřazení a postfixové operátory. Ostatní operátoři nejsou tak běžní, takže budeme uvažovat pouze ty, které budeme používat.

      public class OperatorsInJava(

      int a = 5;

      int b = 6;

      int součet = a + b;

      int rozdíl = a - b;