Konverzia primitívnych typov v Jave. Typová konverzia a odlievanie. Automatická propagácia typu vo výrazoch

  • 29.07.2019

Často je potrebné konvertovať reťazce na hodnoty iných typov, ako je int alebo boolean a naopak. Podľa dohovoru zodpovednosť za konverziu reťazca v hodnota iného typu je priradená zodpovedajúcej metóde tohto typu. Takže napríklad prevod reťazca na hodnotu int sa vykonáva statickou metódou z triedy Integer wrapper. Nasledujúca tabuľka uvádza všetky typy, ktoré dokážu konvertovať hodnoty na reťazce a naopak, a uvádza zodpovedajúce metódy.

TYPE Metóda na prevod Metóda na prevod z reťazca

riadok

boolean String.valueOf(boolean) new.Boolean(String). booleanvalue()

byte String.valueOf(byte) Byte.parseByte(reťazec, int)

short String.valueOf(short) Short.parseShort(string, int)

int String.valueOf(int) Integer.parseInteger(reťazec, int)

long String.valueOf(long) Long.parseLong(String, int)

float String.valueOf(float) Float.parseFloat(String)

double String.valueOf(double) Double.parseDouble(String)

Ak chcete skonvertovať reťazec na boolovskú hodnotu, musíte vytvoriť boolovský objekt a potom dopytovať jeho hodnotu. Všetky ostatné triedy obalov obsahujú zodpovedajúce metódy rozobrať. Metódy rozobrať celočíselné typy existujú v dvoch preťažených formách: prvý okrem reťazca vyžaduje dodatočný argument typu int reprezentujúci základ číselnej sústavy - od 2 do 32; druhý preberá iba reťazcový parameter a predvolene je desiatkový. Vo všetkých prípadoch okrem booleovských predpokladov je predpoklad, že ak reťazec predstavuje hodnotu, ktorú nemožno správne previesť na číslo vhodného typu, vyvolá sa výnimka NumberFormatException. Trieda Boolean sa riadi konvenciou, že akýkoľvek reťazec parametra, ktorý sa nerovná hodnote „true“ (nerozlišuje sa malé a veľké písmená), vedie k vytvoreniu boolovského objektu s hodnotou false.

Metódy, ktoré vám umožňujú konvertovať znaky, ktoré sú reprezentované v jednej z foriem podporovaných jazykom (napríklad \b, \uxxxx atď.) na hodnotu typu char a naopak neexistuje. Ak chcete získať objekt String obsahujúci jeden znak, stačí zavolať metódu String.valueOf a odovzdať jej príslušnú hodnotu znaku ako parameter.

Neexistujú ani spôsoby, ako vytvoriť reťazcové reprezentácie čísel uvedených v jednom z formátov podporovaných jazykom – s úvodnou nulou (O), označujúcou osmičkové číslo, a predponou Ox (alebo OX), ktorá je znakom hexadecimálny číselný systém. Naproti tomu celočíselné obalové triedy podporujú verzie metódy dekódovania, ktoré dokážu konvertovať reťazce na číselné hodnoty vhodného typu a „pochopia“, že počiatočná 0 je osmičková a jedna z predpôn Ox OR Ox je hexadecimálna.

Akákoľvek aplikačná trieda môže poskytnúť podporu pre konverziu natívnych objektov na reťazce a naopak, ak jej deklarácia vhodne prepíše metódu toString a poskytne špeciálny konštruktor, ktorý vytvorí objekt triedy na základe reťazca odovzdaného ako parameter. K dispozícii máte aj metódu String.valueOf(Object obj), ktorá vracia buď objekt typu string „null“ (ak je hodnota obj null), alebo výsledok metódy obj.toString. Trieda String obsahuje dostatok preťažených verzií metódy valueOf, aby ste mohli previesť akúkoľvek hodnotu akéhokoľvek typu na objekt String jednoduchým volaním valueOf s požadovaným argumentom.

Ide o pomerne rozsiahlu tému, ale pokúsime sa ju pokryť čo najúplnejšie a najkompaktnejšie. Čiastočne sme sa tejto témy už dotkli, keď sme sa pozreli na primitívne typy Java.

Java umožňuje prevody medzi celočíselnými hodnotami a hodnotami s pohyblivou rádovou čiarkou. Môžete tiež previesť celé čísla a hodnoty s pohyblivou rádovou čiarkou na hodnoty znakov a naopak, pretože každý znak zodpovedá číslici Unicode. V skutočnosti je booleovský typ jediným primitívnym typom v Jave, ktorý nemožno konvertovať na iný primitívny typ. Žiadny iný primitívny typ tiež nemožno skonvertovať na booleovský.

Konverzia typov v jazyku Java je dvoch druhov: implicitné a explicitné.

Konverzia implicitného typu vykonaná, ak sú splnené tieto podmienky:

  1. Oba typy sú kompatibilné
  2. Dĺžka cieľového typu je väčšia alebo rovná dĺžke zdrojového typu

Vo všetkých ostatných prípadoch použite explicitná konverzia typu.

Existujú tiež dva typy transformácií:

  1. Rozširujúca konverzia
  2. Zužujúca konverzia

Rozširujúca sa transformácia ( rozšírenie konverzie) nastane, keď sa hodnota jedného typu skonvertuje na širší typ s väčším rozsahom platných hodnôt. Java vykonáva rozširujúce konverzie automaticky, napríklad ak priradíte literál typu int k premennej typu double alebo hodnotu typu char k premennej typu int. Implicitná konverzia je vždy rozširujúceho typu.

Ale môžu tu byť nejaké malé hrable. Napríklad, ak sa hodnota int skonvertuje na plávajúcu hodnotu. A hodnota int v binárnej reprezentácii má viac ako 23 platných bitov, potom je možná strata presnosti, pretože typ float má 23 bitov pre celú časť. Všetky nízke bity Hodnoty int, ktoré sa nezmestia do 23-bitovej mantisy float, budú vyradené, takže aj keď sa poradie čísel zachová, presnosť sa stratí. To isté platí pre konverziu long na double.

Rozšírenie konverzie typu Java možno znázorniť aj takto:

Plné čiary označujú konverzie vykonané bez straty údajov. Prerušované čiary označujú, že počas konverzie môže dôjsť k strate presnosti.

Stojí za to trochu vysvetliť, prečo sa napríklad typ bajtu automaticky (implicitne) neprevedie na typ char, hoci typ bajtu má šírku 8 bitov a typ char je 16, to isté platí pre prevod krátkeho typu na char. Je to preto, že byte a short sú podpísané dátové typy, zatiaľ čo char je bez znamienka. Preto v tomto prípade musíte použiť pretypovanie explicitného typu, pretože kompilátor musí explicitne uviesť, že viete, čo chcete a ako sa pri prevode na typ char spracuje znamienkový bit typu byte a short.

Správanie hodnoty char je vo väčšine prípadov rovnaké ako správanie hodnoty typu celé číslo, takže hodnotu char možno použiť všade, kde sa vyžaduje hodnota int alebo long. Pripomeňme si však, že typ char je bez znamienka, takže sa správa inak ako krátky typ, aj keď rozsah oboch typov je 16 bitov.

krátky s = ( krátky ) 0xffff; // Tieto bity predstavujú číslo -1
char c = "\ffff"; // Rovnaké bity predstavujú znak Unicode
int i1 = s; // Prevod z short na int dáva -1
int i2 = c; // Prevod char na int dáva 65535

Zužujúca sa transformácia ( zužujúca konverzia) nastane, ak sa hodnota skonvertuje na hodnotu typu, ktorého rozsah nie je širší ako pôvodná hodnota. Zúžené prevody nie sú vždy bezpečné: napríklad prevod celočíselnej hodnoty 13 na bajt dáva zmysel, ale prevod 13 000 na bajt je nerozumný, pretože bajt môže uchovávať iba čísla medzi -128 a 127. Keďže údaje sa môžu počas zužujúceho prevodu stratiť, Objekty kompilátora Java na akúkoľvek takúto konverziu, aj keď konvertovaná hodnota spadá do užšieho rozsahu určeného typu:

int i = 13 ;
byte b = i ; // Kompilátor tento výraz nevyrieši

Jedinou výnimkou z pravidla je priradenie celočíselného literálu (hodnota typu int) k bajtu alebo krátkej premennej, ak literál zodpovedá rozsahu premennej.

Zužujúca konverzia je vždy explicitná konverzia typu..

Explicitná konverzia primitívnych typov

Explicitný operátor konverzie typu, alebo presnejšie, pretypovanie typu, sú zátvorky, v ktorých je uvedený typ, na ktorý sa konverzia vykonáva - (typ). Napríklad:

int i = 13 ;
byte b = ( byte ) i ; // Vynútená konverzia int na bajt
i = ( int ) 13.456 ; // Vynútená konverzia literálu dvojitého typu na int 13

Najčastejšie sa používa odlievanie primitívneho typu na prevod hodnôt s pohyblivou rádovou čiarkou na celé čísla. V čom zlomková časť hodnoty s pohyblivou rádovou čiarkou sa jednoducho zahodí(to znamená, že hodnota s pohyblivou rádovou čiarkou je zaokrúhlená smerom k nule, nie k najbližšiemu celému číslu). V podstate berie sa iba celá časť skutočného typu a už je pretypovaný na cieľový celočíselný typ.

Pri privádzaní priestrannejšieho celočíselný typ do menej priestranného sa vysoké bity jednoducho vyhodia. Je to v podstate to isté ako modulo delenie hodnoty pretypovania rozsahom cieľového typu (napríklad 256 pre bajt).

Príliš veľké zlomkové číslo sa pri prenesení na celé číslo zmení na MAX_VALUE alebo MIN_VALUE.

Príliš veľký dvojitý pri privedení do plavák sa zmení na Float.POSITIVE_INFINITY alebo Float.NEGATIVE_INFINITY.

Nasledujúca tabuľka je mriežka, kde sú pre každý primitívny typ uvedené typy, na ktoré je možné ich previesť, a spôsob prevodu. List N v tabuľke znamená, že prevod nie je možný. List Y znamená rozšírenie konverzie, ktorá sa vykonáva automaticky. List OD znamená zužujúcu konverziu, ktorá vyžaduje explicitné obsadenie. nakoniec Y* znamená automatickú konverziu rozšírenia, počas ktorej môže hodnota stratiť niektoré z najmenej významných bitov. To sa môže stať pri prevode int alebo long na float alebo double. Typy s pohyblivou rádovou čiarkou majú väčší rozsah ako celočíselné typy, takže int alebo long môžu byť reprezentované ako float alebo double. Typy s pohyblivou rádovou čiarkou sú však približné čísla a nemusia vždy obsahovať toľko platných číslic v mantise ako typy celých čísel.

Automatické rozširovanie typu vo výrazoch

Za zmienku ešte raz stojí automatická propagácia (rozširovanie) typov vo výrazoch. Už sme sa s tým stretli, keď sme uvažovali o celočíselných dátových typoch a operáciách s nimi, ale aj tak sa to tu oplatí pripomenúť, aby to bolo ešte lepšie pochopiteľné a navyše to priamo súvisí s touto témou. V nižšie uvedenom príklade znak @ + , , * , / atď.

Teda všetky celočíselné literály vo výrazoch, ako aj typy byte, krátky a char rozšíriť na int . Ak, ako je popísané vyššie, vo výraze nie sú prítomné iné väčšie typy údajov ( dlhý, plavák alebo dvojitý). Preto vyššie uvedený príklad spôsobí chybu kompilácie, pretože premenná c má typ byte, a výraz b+1, ako výsledok automatického povýšenia, je typu int.

Implicitné pretypovanie v kombinovaných priraďovacích výrazoch

Hoci sa v tejto časti hovorí o implicitnej konverzii typu (casting), tu sme jej vysvetlili, keďže v tomto prípade funguje aj automatické rozširovanie typu vo výrazoch a potom implicitné pretypovanie. Tu je baletný zbor. Nižšie uvedený príklad to podľa mňa objasní. Rovnako ako v predchádzajúcom vysvetlení, znamenie @ znamená akýkoľvek platný operátor, napr + , , * , / atď.

Treba to vysvetliť na jednoduchom príklade:

byte b2 = 50 ;
b2 = b2 * 2 ; // nebude kompilovať
b2 *= 2 ; //kompiluje, hoci je ekvivalentné s b2 = b2 * 2

Druhý riadok v príklade sa neskompiluje kvôli automatickému rozširovaniu typu vo výrazoch, pretože výraz b2*2 má typ int, pretože dochádza k automatickému rozširovaniu typu (celočíselné literály vo výrazoch sú vždy int). Tretí riadok sa ľahko skompiluje, pretože v ňom bude fungovať implicitné pretypovanie v kombinovanom priraďovacom výraze.

Boxing/unboxing – konvertovanie primitívnych typov na obalové objekty

Boxovanie a rozbaľovanie je tiež dosť rozsiahla téma, no je celkom jednoduchá.

V podstate box a unboxing je konverzia primitívnych typov na obalové objekty a naopak.

Pre obalové objekty primitívnych typov platí všetko, čo bolo povedané vyššie.

Triedy obalov boli uvedené v tabuľkách pri analýze každého z primitívnych typov. Ale vtedy to bola len zmienka v tabuľke.

Takže pre každý primitívny typ existuje jeho starší brat a vôbec nie je primitívny, ale je to skutočná trieda s poľami a metódami. A pre každý takýto pár je možná automatická konverzia.

Zvyčajne, ak má program veľa matematických výpočtov, je lepšie použiť primitívne typy, pretože je to rýchlejšie a úspornejšie z hľadiska zdrojov, ale niekedy je potrebné previesť primitívny typ na objekt.

Uvediem jednoduchý príklad:

int i3 ;
byte b2 = 3 ;
bajtov myB ;
myB= b2;
myB++;
b2= myB;
i3= myB;

Ak ešte nie je jasné, prečo je to potrebné, potom to nie je strašidelné, stačí uviazať uzol na pamiatku.

Daný článok:

  • napísal tím. Dúfame, že to bude pre vás užitočné. Príjemné čítanie!
  • toto je jeden z našich článkov

Konverzia typov je téma, ktorá sa začínajúcim programátorom Java môže zdať skľučujúca. Uisťujeme vás však, že v skutočnosti je všetko jednoduché. Hlavná vec je pochopiť podľa akých zákonov dochádza k interakcii medzi premennými a pamätajte na to pri písaní programov. Takže, poďme na to.

V Jave existujú 2 typy transformácií - obrázok, ktorý vám pomôže:

Pripomeňme, že celý „Java Universe“ pozostáva z:

  • primitívne typy (byte, short, int, long, char, float, double, boolean)
  • predmety

V tomto článku:

  • zvážte konverziu typu pre primitívne typy premenných
  • transformácia objektov (String, Scanner atď.) sa v tomto článku nezohľadňuje, pretože s objektmi sa deje samostatná „mágia“ - toto je téma na samostatný článok.
Automatická konverzia

Nuž, dobre, skúsme prísť na to, čo je to „automatická konverzia“.

Pamätajte si, že keď sme sa pozreli na typy premenných (v článku), povedali sme to premenná je nejaký druh „kontajnera“ A, ktorý môže uložiť hodnotu pre neskoršie použitie v programe. Hovorili sme aj o tom, že každý typ premennej má svoj vlastný rozsah platných hodnôt a množstvo pamäte, ktorú zaberá. Tu je znak, kde to bolo napísané:

Takže k tomu sa vlastne dostávame. Navyše pre vás nebolo vôbec jednoduché dostať rozsahy platných hodnôt a množstvo obsadenej pamäte 🙂

Porovnajme napr.

1. bajt a krátky. bajt má menší rozsah platných hodnôt ako krátky. To znamená, že byte je ako menší box a short je väčší box. A to znamená môžeme skrátka vnoriť bajt.

2. bajt a int. byte má menší rozsah platných hodnôt ako int. To znamená, že byte je ako menší box a int je väčší box. A to znamená môžeme vnoriť bajt do int.

3.int a dlhé. int má menší rozsah platných hodnôt ako long. To znamená, že int je ako menšia krabica a long je väčšia krabica. A to znamená môžeme hniezdiť int v dlhom.

Toto je príklad automatickej konverzie. Schematicky to možno znázorniť vo forme nasledujúceho obrázka:

Pozrime sa, ako to funguje v praxi.

Príklad #1

Kód #1 – ak tento kód spustíte na svojom počítači,

class Test ( public static void main(String args) ( bajt a = 15; byte b = a; System.out.println(b); ) )

triedny test(

bajt a = 15;

byte b = a ;

Kód #2 – ak tento kód spustíte na svojom počítači, na konzole sa zobrazí číslo 15

class Test ( public static void main(String args) ( bajt a = 15; int b = a; System.out.println(b); ) )

triedny test(

public static void main(String args )(

bajt a = 15;

int b = a;

systém. von . println(b);

A-a-a? Myslíš si to koľkokrát bolo na konzole vytlačené rovnaké číslo, a kód #1 sa líši od kódu #2 len typom premennej b potom nie je medzi nimi rozdiel? E nie je to tak.

Kód #2 obsahuje automatickétypová konverzia , ale v kóde č. 1 - nie:

Počet je síce v podstate rovnaký, ale teraz je v b o väčší kontajner, ktorý zaberá viac miesta na disku. V tomto prípade JVM vykoná automatické transformácie za vás. Ona to vie int viac ako byte .

Obsadenie

Iná vec je, ak sa snažíte niečo preniesť z väčšej nádoby do menšej.

Možno viete, že väčší kontajner obsahuje niečo, čo sa zmestí do malého – ale JVM to nevie a snaží sa vás chrániť pred chybami.

Preto musíte „priamo povedať“, že situácia je pod kontrolou:

class Test ( public static void main(String args) ( int a=0; long b=15; a = (int) b; ) )

triedny test(

public static void main(String args )(

int a = 0;

dlhé b = 15;

a = (int) b;

Tu sme pridali (int) predtým b. Ak premenná a bol napr. byte, v zátvorkách by bolo (bajt). Všeobecný vzorec vyzerá takto:

Hovorí, že „vyrobte (väčšiu) hodnotu b premenná typu (cieľ), ktorý potrebujem int ".

Ak sa niečo pokazilo.

Doteraz sme sa na situácie pozerali za predpokladu, že presne vieme, čo robíme. Ale čo keď sa pokúsite dať do kontajnera niečo, čo sa tam nezmestí?

Ukazuje sa, že v nádobe zostane len to, čo sa „zmestí“. Napríklad zlomková časť čísel s pohyblivou rádovou čiarkou bude „odrezaná“:

//príklad 1 triedy Test ( public static void main(String args) ( double a=11,2345; int b=(int)a; System.out.println(b); // konzola zobrazí číslo 11 ) )

//príklad 1

triedny test(

public static void main(String args )(

dvojité a = 11,2345;

int b = (int ) a ;

systém. von . println(b); // konzola zobrazí číslo 11

Treba mať na pamäti, že zlomková časť nezaokrúhlené, a vyradené.

Čo sa však stane, ak sa pokúsime zadať číslo, ktoré je mimo rozsahu? Napríklad, ak do bajtu (rozsah bajtov od -128 do 127) zadajte číslo 128? Myslíš, že dostaneme 1? Nie Dostávame -128:

class Test ( public static void main(String args) ( double a=128; byte b=(byte)a; System.out.println(b); //uvidíme -128 v konzole) )

Hodnotu premennej je možné vypočítať pomocou tohto prevodu, ale cieľom programátora je predísť situáciám, kedy je hodnota mimo hraníc, pretože to môže viesť k nesprávnej činnosti programu.

Úlohy:
  1. Postupne zapíšte do kompilátora konverzie všetkých primitívnych typov medzi sebou, vrátane typov znakov a vytvorte tabuľku takto:
byte krátky char int dlhý plavák dvojitý boolovská hodnota
byte
krátky
char
int
Dlhé
plavák
dvojitý
boolovská hodnota

Na križovatke napíšte: a - ak konverzia prebieha automaticky, na - ak potrebujete použiť explicitnú konverziu, x - ak konverzia nie je možná.

* vrhanie typu na seba sa nazýva identické- nie je potrebné písať

  1. Znova sa pozrite, akú veľkosť majú jednotlivé primitívne typy. Pokúste sa vytvoriť blokovú schému, ktorá ukazuje, kam sa ktoré typy nachádzajú. Prejdite prstom po šípkach označených ako „rozširujúca sa transformácia“ a „zužujúca sa transformácia“.
Otázky

Pri pohovore na pozíciu Junior Java Developer sa vás môžu opýtať:

Čo viete o konverzii primitívnych dátových typov, dochádza k strate dát, je možné konvertovať booleovský typ?

Skúste odpovedať na otázku.

Zhrnúť:
  • Ak obsah menšej nádoby „vložíte“ ​​do nádoby väčšej, konverzia prebehne automaticky a nemali by nastať žiadne chyby.
  • Ak je potrebné vložiť „hodnotu z väčšieho kontajnera do menšieho“, musíte byť opatrní a použiť explicitné typové liatie.
  • Pri odlievaní plavákových alebo dvojitých až integrálnych typov nie je zlomková časť zaokrúhlená, ale jednoducho vyradená.
  • Booleovský typ sa nepretypuje na žiadny z typov.
  • Typ char sa prenáša na číselné typy, ako je kód znaku v systéme UNICODE.
  • Ak je číslo väčšie ako jeho kontajner, výsledok bude nepredvídateľný.

Tento článok popisuje iba časť materiálu na tému typového odlievania. Nechýbajú ani vrhanie typu objektu, vrhanie reťazcov (napokon, do reťazca sa dá napísať čokoľvek, nie?) a automatická propagácia typu vo výrazoch.

Dúfame, že náš článok bol pre vás užitočný. Je tiež možné prihlásiť sa do našich kurzov Java v Kyjeve. Trénujeme od nuly. Podrobné informácie nájdete na našej webovej stránke.


Anotácia: Táto prednáška je venovaná problematike typovej konverzie. Keďže Java je silne typizovaný jazyk, kompilátor a virtuálny stroj vždy poznajú typy, aby sa zabezpečilo, že program beží spoľahlivo. V mnohých prípadoch však musí byť vykonaná jedna alebo druhá transformácia, aby sa implementovala logika programu. Na druhej strane Java umožňuje vývojárom isté bezpečné prechody medzi typmi implicitným spôsobom, čo môže viesť k nepochopeniu fungovania programu. Prednáška zahŕňa všetky druhy transformácií a potom všetky situácie v programe, kde sa dajú použiť. Končí sa začiatkom klasifikácie typov premenných a typov hodnôt, ktoré môžu uchovávať. Tejto problematike sa budeme podrobnejšie venovať v budúcich prednáškach.

Čo to všetko znamená? Začnime pekne po poriadku. Pre jednoduché typy rozšírenie znamená, že sa vykoná prechod z menej priestranného typu na priestrannejší. Napríklad od typu byte (dĺžka 1 bajt) po typ int (dĺžka 4 bajty). Takéto konverzie sú bezpečné v tom zmysle, že nový typ vždy zaručene obsahuje všetky dáta, ktoré boli uložené v starom type, a teda nedochádza k strate dát. Preto ho kompilátor implementuje sám, pre vývojára nepostrehnuteľne:

bajt=3; int a=b;

V poslednom riadku sa hodnota premennej b typu byte prevedie na typ premennej a (teda int ) automaticky, nie je na to potrebná žiadna špeciálna akcia.

Nasledujúcich 19 transformácií sa rozširuje:

  • od bajtu po short , int , long , float , double
  • from short to int , long , float , double
  • from char to int , long , float , double
  • from int to long , float , double
  • z dlhých na plávať, dvojité
  • plávať na dvojnásobok

Všimnite si, že nemôžete konvertovať na char z typov s menšou alebo rovnakou dĺžkou (byte , short ) a naopak na short z char bez straty údajov. Je to preto, že znak char na rozdiel od iných celočíselných typov je bez znamienka.

Malo by sa však pamätať na to, že aj pri rozšírení môžu byť údaje v špeciálnych prípadoch stále poškodené. Už o nich bola reč v predchádzajúcej prednáške, ide o prehadzovanie hodnôt int na typ float a prehadzovanie dlhých hodnôt na typ float alebo double. Hoci tieto zlomkové typy môžu obsahovať oveľa väčšie čísla ako zodpovedajúce celé čísla, majú menej platných číslic.

Zopakujme si tento príklad:

dlhé a=111111111111L; plavák f = a; a = (dlhá) f; tlačiť(a);

Výsledkom bude:

Reverzná transformácia - zúženie - znamená, že sa uskutoční prechod z priestrannejšieho typu na menej priestranný. Pri takejto konverzii hrozí strata dát. Napríklad, ak bol int väčší ako 127, potom sa pri jeho pretypovaní na bajt stratia bitové hodnoty staršie ako osem. V Jave sa takáto konverzia musí urobiť vyslovene, t.j. programátor v kóde musí výslovne uviesť, že má v úmysle vykonať takúto konverziu a je pripravený stratiť dáta.

Nasledujúce transformácie sa zužujú:

  • z bajtu na char
  • od skratky po bajt, char
  • od znaku po bajt, krátky
  • od int po byte , short , char
  • od long po byte , short , char , int
  • float to byte , short , char , int , long
  • od double po byte , short , char , int , long , float

Pri zúžení celočíselného typu na užší celočíselný typ sa všetky bity vyššieho rádu, ktoré sa nehodia do nového typu, jednoducho zahodia. Na získanie správneho výsledku sa nevykonávajú žiadne zaokrúhľovanie ani iné akcie:

print((bajt)383); print((bajt)384); print((bajt)-384);

Výsledkom bude:

Je vidieť, že znamienkový bit nemal pri zúžení žiadny vplyv, keďže bol jednoducho vyradený - výsledok vrhnutia opačných čísel (384 a -384) sa ukázal byť rovnaký. V dôsledku toho sa môže stratiť nielen presná absolútna hodnota, ale aj znamienko množstva.

To platí aj pre typ znaku:

char c=40000; print((short)c);

Výsledkom bude:

Zúženie zlomkového typu na celočíselný typ je komplikovanejší postup. Vykonáva sa v dvoch etapách.

V prvom kroku sa zlomková hodnota skonvertuje na long, ak je cieľový typ long , alebo na int inak (cieľový typ je byte , short , char alebo int ). Na tento účel sa pôvodné zlomkové číslo najskôr matematicky zaokrúhli smerom k nule, to znamená, že sa zlomková časť jednoducho zahodí.

Napríklad číslo 3,84 sa zaokrúhli na 3 nahor a z -3,84 sa stane -3. V tomto prípade môžu nastať špeciálne prípady:

  • ak je pôvodná zlomková hodnota NaN , potom výsledkom prvého kroku je 0 zvoleného typu (t. j. int alebo long );
  • ak je pôvodná zlomková hodnota kladné alebo záporné nekonečno, potom výsledkom prvého kroku bude maximálna alebo minimálna možná hodnota pre vybraný typ (t. j. pre int alebo long );
  • nakoniec, ak zlomková hodnota bola konečná hodnota, ale v dôsledku zaokrúhlenia sa ukázalo, že číslo je príliš veľké v absolútnej hodnote pre vybraný typ (t. j. pre int alebo long ), potom, ako v predchádzajúcom odseku, výsledok prvého kroku bude maximálna alebo minimálna možná hodnota tohto typu. Ak výsledok zaokrúhľovania zapadá do rozsahu hodnôt zvoleného typu, bude výsledkom prvého kroku.
  • a int sú celkom zrejmé - zlomkové nekonečná boli prevedené na minimálne a maximálne možné hodnoty týchto typov. Výsledkom pre ďalšie tri typy (short , char , byte ) je v skutočnosti ďalšie zúženie hodnôt získaných pre int podľa druhého kroku konverznej procedúry. A to sa robí, ako je opísané, jednoducho vyradením vysokých bitov. Pripomeňme, že najmenšia možná hodnota v bitovej forme je reprezentovaná ako 1000..000 (iba 32 bitov pre int , teda jedna a 31 núl). Maximálne možné je 1111..111 (31 jednotiek). Zahodením vysokých bitov dostaneme výsledok 0 pre záporné nekonečno, ktorý je rovnaký pre všetky tri typy. Pre kladné nekonečno dostaneme výsledok, ktorého všetky bity sa rovnajú 1

    Na záver ešte raz venujme pozornosť skutočnosti, že primitívne hodnoty typu boolean sa môžu zúčastniť iba identických konverzií.

Niekedy nastanú situácie, keď máte hodnotu určitého typu a potrebujete ju priradiť k premennej iného typu. Pri niektorých typoch sa to dá urobiť bez typového odlievania, v takýchto prípadoch sa hovorí o automatickej typovej konverzii. V jazyku Java je automatická konverzia možná len vtedy, keď je číselná reprezentácia cieľovej premennej dostatočne presná, aby udržala pôvodnú hodnotu. K takejto konverzii dochádza napríklad vtedy, keď sa do premennej typu int zadá doslovná konštanta alebo hodnota premennej typu byte alebo short. To sa nazýva rozšírenie (rozširovanie) alebo zvýšiť (povýšenie), pretože typ s menšou bitovou hĺbkou je rozšírený (zvýšený) na väčší kompatibilný typ. Typ int je vždy dostatočne veľký na to, aby obsahoval čísla v rozsahu povolenom pre typ bajtu, takže v takýchto situáciách nie je potrebný explicitný operátor pretypovania. Opak vo väčšine prípadov neplatí, takže na pretypovanie hodnoty typu int do bajtovej premennej sa musí použiť operátor cast. Tento postup sa niekedy nazýva zúženie (zúženie), pretože prekladateľovi výslovne hovoríte, že hodnotu treba previesť, aby sa zmestila do premennej požadovaného typu. Ak chcete preniesť hodnotu na konkrétny typ, zadajte pred ňu tento typ v zátvorkách. Útržok kódu nižšie ukazuje pretypovanie zdrojového typu (premenná typu int) na cieľový typ (bajtová premenná). Ak by počas takejto operácie bola celočíselná hodnota mimo rozsah povolený pre typ bajtu, znížila by sa delením modulo povoleným rozsahom pre bajt (výsledkom delenia modulo číslom je zvyšok delenia týmto číslom) ,

int a = 100;
byteb = (bajt) a;

2.2.1. Automatická konverzia typu vo výrazoch

Pri výpočte hodnoty výrazu musí byť presnosť požadovaná na uloženie medzivýsledkov často väčšia ako presnosť požadovaná na vyjadrenie konečného výsledku,

bajt a = 40;
bajt b = 50;
byte s = 100;
int d = a* b / c;

Výsledok stredného výrazu (a * b) môže značne presiahnuť rozsah hodnôt povolených pre typ bajtu. To je dôvod, prečo Java automaticky povýši každú časť výrazu na typ int, takže je dostatok miesta pre medzivýsledok (a*b).

Automatická konverzia typov môže niekedy spôsobiť neočakávané chybové hlásenia kompilátora. Napríklad kód zobrazený nižšie, hoci vyzerá celkom správne, má za následok chybové hlásenie počas fázy prekladu. V ňom sa snažíme do bytovej premennej zapísať hodnotu 50 * 2, ktorá by mala perfektne zapadnúť do typu byte. Ale kvôli automatickej konverzii typu výsledku na int dostaneme od prekladača chybové hlásenie - koniec koncov pri prevode int na byte môže dôjsť k strate presnosti.

bajt b = 50;
b = b*2:
^ Nekompatibilný typ pre =. Na konverziu int na bajt je potrebné explicitné pretypovanie.
(Nekompatibilný typ pre =. Vyžaduje sa explicitná konverziaint inbajt)

Opravený text:
byteb = 50;
b = (bajt) (b*2);

čo spôsobí, že b sa naplní správnou hodnotou 100.

Ak výraz používa premenné typu byte, short a int, potom sa typ celého výrazu automaticky povýši na int, aby sa predišlo pretečeniu. Ak je typ aspoň jednej premennej vo výraze dlhý, potom sa typ celého výrazu tiež povýši na dlhý. Pamätajte, že všetky celočíselné literály, ktoré nekončia na L (alebo 1), sú typu int.

Ak výraz obsahuje operandy typu float, typ celého výrazu sa automaticky povýši na float. Ak je aspoň jeden z operandov typu double, potom sa typ celého výrazu povýši na double. Java štandardne považuje všetky literály s pohyblivou rádovou čiarkou za literály typu double. Nasledujúci program ukazuje, ako je typ každej hodnoty vo výraze podporovaný tak, aby sa zhodoval s druhým operandom každého binárneho operátora.

trieda povýšiť(
public static void main(String args )(
bajt=42;
char s= "a";
šortky = 1024;
int i = 50 000;
plavák f = 5,67f;
zdvojnásobený = 0,1234;
dvojitý výsledok = (f*b) + (i/ c) - (d* s);
Systém, von. println ((f* b)+ "+ "+ (i / c)+ "-" + (d* s));
Systém, von. println("vysledok = "+vysledok); )
}

Podvýraz f*b je float vynásobený bajtom, takže je automaticky povýšený na float. Typ nasledujúceho podvýrazu i/c (int delený znakom) sa povýši na int. Podobne sa podvýraz d*s (dvojité násobené krátkym) povýši na dvojnásobok. V ďalšom kroku výpočtov sa zaoberáme tromi medzivýsledkami typov float, int a double. Po prvé, po pridaní prvých dvoch sa typ int povýši na float a výsledkom je float. Pri odčítaní dvojitej hodnoty sa typ výsledku povýši na double. Konečným výsledkom celého výrazu je dvojnásobná hodnota.

Teraz, keď sme videli všetky jednoduché typy vrátane celých čísel, reálnych hodnôt, symbolov a boolovských hodnôt, skúsme dať všetky informácie dohromady. Nasledujúci príklad vytvára premenné každého z jednoduchých typov a zobrazuje hodnoty týchto premenných.

trieda SimpleTypes(
public static void main(String args ) (
bajt b = 0x55;
krátke s = 0x55ff;
int i = 1 000 000;
dlhé l = 0xffffffffL;
char s= 'a';
plavák f= 0,25f;
dvojité d = 0,00001234;
boolean bool = true;
System.out.println("byte b = " + b);
System.out.println("short s = " +s);
System.out.println("int i =" + i);
System.out.println("long 1 = " + l);
System.out.println("char with=” + s);
System.out.println("float f = " + f);
System.out.println("double d = " + d);
System.out.println("boolovský bool =" + bool); )
}

Keď spustíte tento program, mali by ste dostať výstup zobrazený nižšie:

bajt b = 85
šortky = 22015
int i = 1 000 000
dlhé 1 = 4294967295
char s= a
float f = 0,25
dvojité d=1,234e-005
boolean bool = pravda

Všimnite si, že celé čísla sú vytlačené v desiatkovej sústave, hoci niektoré z nich sme špecifikovali v šestnástkovej sústave.