Cum se configurează smartphone-uri și PC-uri. Portal informativ

Java convertește dublu în int. Exemplu

Fiecare expresie din Java are un tip, care este determinat de structura expresiei și de tipurile operanzilor ei constituenți (constante, variabile și metode). Cu toate acestea, uneori este posibil să fie nevoie să convertim explicit o expresie într-un alt tip. În plus, în unele situații, runtime-ul Java în sine realizează astfel de conversii implicit.

Conversie de tip T 1 la tipul T 2 permite ca o expresie de tip T 1 să fie tratată în timpul compilării ca o expresie de tip T 2. În unele cazuri, aceasta este o construcție pur sintactică care nu afectează codul generat; în altele, conversia tipului necesită acțiuni suplimentare în timpul execuției pentru a modifica valoarea expresiei sau verificări suplimentare pentru corectitudinea conversiei aplicate. Exemple:

  • Conversie de tip intîn tip lung necesită un semn întreg de 32 de biți pentru a se extinde la un număr întreg de 64 de biți în timpul execuției. În acest caz, nu există nicio pierdere de informații.
  • Conversie de tip plutiîn tip lung necesită o conversie netrivială a unei valori flotante de 32 de biți într-un număr întreg de 64 de biți în timpul execuției. Pierderea informațiilor poate să apară sau nu, în funcție de valoarea inițială.
  • Conversia de la Thread la Object este simplă: deoarece Thread este un descendent al Object, orice referință la un obiect de tip Thread este automat o referință la un Object.
  • Conversia de la Object la Thread necesită validare la runtime. Dacă referința de convertit este într-adevăr o referință la un obiect de tip Thread, atunci este returnată ca rezultat al conversiei, în caz contrar se aruncă o excepție.

5.4.1.1. Extinderea numărului de conversii

Extinderea numărului de conversii- sunt conversii de tip numeric într-un tip numeric „mai mare”, care sunt considerate sigure, deoarece nu duc la pierderea valorii valorii convertite. Astfel de conversii în Java sunt:

  • transformări octet v mic de statura, int, lung, plutiși dubla;
  • transformări mic de statura v int, lung, plutiși dubla;
  • transformări char v int, lung, plutiși dubla;
  • transformări int v lung, plutiși dubla;
  • transformări lung v plutiși dubla;
  • transformări pluti v dubla.

De fapt, conversia unei valori întregi într-o valoare flotantă poate duce la o pierdere a preciziei, adică o pierdere a cifrelor semnificative. Deci următorul exemplu

Test de clasă (public static void main (String args) (int bigNumber = 1234567890; float approximate = bigNumber; System.out.println (aproximativ);))

va afișa șirul 1234567936. Acest lucru se datorează faptului că la conversie int v pluti valoarea rezultată este 1,2345679E9 datorită faptului că mantisa numerelor precum pluti găzduiește doar 8 cifre zecimale (aici conversia la tip ar trebui utilizată pentru a funcționa corect dubla). Cu toate acestea, sistemul de rulare nu generează niciodată erori atunci când efectuează transformările enumerate.

5.4.1.2. Reducerea numărului de conversii

Reducerea numărului de conversii- Acestea sunt conversii ale unui tip numeric într-un tip numeric „mai mic”, care pot duce atât la pierderea mărimii, cât și la pierderea preciziei. Astfel de conversii în Java sunt:

  • transformări octet v char;
  • transformări mic de statura v octetși char;
  • transformări int v octet, mic de staturași char;
  • transformări lung v octet, mic de statura, intși char;
  • transformări pluti v octet, mic de statura, int, lungși char;
  • transformări dubla v octet, mic de statura, int, lung, plutiși char;

Nu vom lua în considerare aici în detaliu regulile după care au loc aceste transformări, deoarece ele sunt de înțeles intuitiv și formal destul de greoaie. Atunci când le folosiți, este important să rețineți că Java, spre deosebire de alte limbi, nu generează erori de overflow sau underflow, astfel încât controlul asupra corectitudinii transformărilor revine în întregime programatorului.

5.4.1.3. Transformări extensibile de legături

Transformări extensibile de legături Sunt conversii ale tipurilor de referință derivate la tipurile strămoșilor lor, care nu necesită nicio acțiune în timpul execuției și nu generează niciodată erori. Astfel de conversii în Java sunt:

  • conversia oricărei clase sau interfețe la strămoșul ei (în special, la tipul Object);
  • conversia unei clase într-o interfață pe care o implementează;
  • conversia oricărei matrice în tip Object sau tip Cloneable;
  • conversia unui tablou de tip S într-un tablou de tip T dacă S și T sunt tipuri de referință și conversia de la S la T se extinde;
  • conversia unui tip nul în orice tip de referință.

5.4.1.4. Reducerea conversiilor de link

Reducerea conversiilor de link Sunt conversii de la tipurile de referință derivate la tipurile lor descendente. Aceste conversii necesită o verificare a legitimității lor și pot genera o excepție ClassCastException. Astfel de conversii în Java sunt:

  • conversia oricărei clase în descendentul acesteia (în special, conversia tipului Object în orice altă clasă);
  • conversia unei clase într-o interfață atunci când clasa nu este finală și nu implementează interfața dată (în special, conversia tipului Object în orice interfață);
  • conversia tipului de obiect în orice matrice;
  • conversia oricărei interfețe într-o clasă care nu este finală;
  • conversia oricărei interfețe într-o clasă care este finală și implementează această interfață;
  • conversia interfeței J în interfața K, când J nu este un descendent al lui K și nu există nicio metodă declarată atât în ​​J, cât și în K cu aceeași semnătură, dar tipuri de rezultate diferite;
  • conversia unei matrice de tip S într-o matrice de tip T dacă S și T sunt tipuri de referință și conversia de la S la T se îngustează.

5.4.1.5. Conversii în șiruri

Orice expresie în Java, inclusiv nul, poate fi convertit în String.

5.4.1.6. Conversii nevalide

Următoarele conversii de tip sunt interzise în Java:

  • conversia oricărui tip de referință în orice tip primitiv;
  • conversia oricărui tip primitiv în orice tip de referință, altul decât String;
  • conversia tipului zero în orice tip primitiv;
  • conversii la tip null sau tip boolean;
  • conversii de tip boolean la orice alt tip decât tipul String;
  • conversia unei clase în alta, dacă niciuna dintre ele nu este un strămoș al celeilalte (cu excepția conversiei la tipul String);
  • conversia unei clase într-o interfață dacă clasa este finală și nu implementează interfața dată;
  • conversia unei clase într-o matrice dacă clasa este diferită de Object;
  • conversia unei interfețe într-o clasă care este finală și nu implementează interfața dată (cu excepția conversiei la tipul String);
  • conversia interfeței J în interfața K, dacă există o metodă declarată atât în ​​J, cât și în K cu aceeași semnătură, dar tipuri de rezultate diferite;
  • conversia unui tablou într-o clasă diferită de Object și String;
  • conversia unui tablou într-o interfață diferită de Cloneable;
  • conversia unei matrice de tip S într-o matrice de tip T dacă conversia S în T este interzisă

5.4.2. Contexte de transformare

5.4.2.1. Conversie la miscare

Conversie la miscare apare atunci când valoarea unei expresii este atribuită unei variabile. Aceasta transformă tipul expresiei în tipul variabilei. La alocare, conversiile tip extindere (atât numerice, cât și de referință) sunt întotdeauna posibile. O conversie de îngustare este posibilă numai dacă sunt îndeplinite următoarele condiții:

  • variabila este de tip octet, mic de statura sau char;
  • valoarea expresiei este o constantă de tip int care se încadrează în intervalul de valori posibile ale variabilei.

De exemplu, operatorul octet x = 123; să spunem, deoarece constanta 123 (de tip int) se află în intervalul de valori admisibile ale tipului octet.

Dacă tipul expresiei nu poate fi convertit în tipul variabilei, atunci compilatorul generează o eroare. În caz contrar, spunem că tipul expresiei compatibil cu misiunea cu un tip variabil. Deci, următorul fragment

s scurt = 123; char c = s; // generează o eroare de compilare

va genera o eroare deoarece tipurile charși mic de statura sunt incompatibile în alocare conform definițiilor de mai sus (primul este implementat în cuvinte nesemnate de 16 biți, iar al doilea - cu un semn).

5.4.2.2. Conversia argumentelor metodei

Conversia argumentelor metodei apare atunci când valorile reale ale argumentelor sunt convertite în tipul parametrilor unei metode sau constructor atunci când este apelată. În acest caz, conversiile extinse ale tipurilor (atât numerice, cât și de referință) sunt întotdeauna posibile, iar conversiile de restrângere nu sunt permise. Motivele acestei din urmă interdicții pot fi explicate prin următorul exemplu:

Test de clasă (static int m (byte a, int b) (return a + b;) static int m (scurt a, short b) (return a - b;) public static void main (String args) (System.out. println ( m (1, 2)); // generează o eroare de compilare))

Aici clasa Test conține două metode cu același nume, care diferă doar prin tipurile de parametri. Dacă conversiile argumentelor de restrângere ar fi permise în Java, timpul de execuție ar trebui să descopere căreia dintre aceste metode îi aparține apelul la m (1, 2). Pentru a evita astfel de ambiguități, dezvoltatorii limbii au rezolvat problema în mod radical: au interzis astfel de apeluri de metodă. În această situație, pentru a apela, de exemplu, prima metodă, trebuie să specificăm în mod explicit tipul primului operand (al doilea are deja tipul implicit int), și anume m ((octet) 1, 2).

5.4.2.3. Conversia în șir

Conversia în șir apare doar într-un singur caz: când operația binar + este aplicată la doi operanzi, dintre care unul este de tip String. În această situație, al doilea operand este, de asemenea, convertit în tipul String, iar rezultatul operației este concatenarea șirurilor rezultate. Acest proces este descris mai detaliat în cap. 5.14.

5.4.2.4. Conversie explicită de tip

Conversie explicită de tip apare atunci când un tip cast este aplicat în mod explicit unui operand. În această situație, pot fi aplicate toate tipurile de conversii de tip descrise mai sus, cu excepția conversiei într-un șir. O încercare de a converti în mod explicit la un tip care este marcat ca interzis mai sus va avea ca rezultat o eroare de compilare. În plus, o excepție ClassCastException poate fi aruncată în timpul rulării dacă conversia specificată este nevalidă.

5.4.3. Conversii tip operand numeric

Conversia tipului în procesul de evaluare a expresiilor numerice are o serie de caracteristici. Acestea se rezumă la două cazuri: conversia operanzilor în operații unare și în operații binare.

Înainte de a efectua o operație unară:

  • dacă operandul este de tip octet, mic de statura sau char, se transformă în tip int;
  • în alte cazuri, tipul său nu se schimbă.

Înainte de a efectua o operație binară:

  • dacă unul dintre operanzi este de tip dubla, apoi al doilea este, de asemenea, convertit în tip dubla;
  • pluti, apoi al doilea este, de asemenea, convertit în tip pluti;
  • în caz contrar, dacă unul dintre operanzi este de tip lung, apoi al doilea este, de asemenea, convertit în tip lung;
  • în caz contrar, ambii operanzi sunt convertiți în tip int.

Acesta este un subiect destul de amplu, dar vom încerca să îl luăm în considerare cât mai complet posibil și, în același timp, compact. Am atins deja acest subiect în parte când ne-am uitat la tipurile primitive de Java.

Conversiile între valorile întregi și în virgulă mobilă sunt posibile în Java. În plus, puteți converti valorile întregi și cu virgulă mobilă în valori char și invers, deoarece fiecare caracter corespunde unei cifre Unicode. De fapt, tipul boolean este singurul tip primitiv din Java care nu poate fi convertit într-un alt tip primitiv. De asemenea, orice alt tip primitiv nu poate fi convertit în boolean.

Există două tipuri de conversii în Java: implicitși explicit.

Conversie implicită de tip se realizează dacă sunt îndeplinite următoarele condiții:

  1. Ambele tipuri sunt compatibile
  2. Lungimea tipului țintă este mai mare sau egală cu lungimea tipului sursă

În toate celelalte cazuri, trebuie utilizat conversie explicită de tip.

Există, de asemenea, două tipuri de transformări:

  1. Lărgirea conversiei
  2. Îngustarea conversiei

Transformare de extindere ( lărgirea conversiei) apare atunci când o valoare de același tip este convertită într-un tip mai larg cu o gamă mai largă de valori valide. Java realizează automat conversii de extindere, de exemplu, dacă atribuiți un literal int unui double sau un caracter neschimbat unui int. Conversia implicită este întotdeauna un tip de lărgire.

Dar aici poate avea propriile ei greble mici. De exemplu, dacă convertiți o valoare int într-o valoare float. Și valoarea int în reprezentarea binară are mai mult de 23 de biți semnificativi, atunci pierderea preciziei este posibilă, deoarece tipul float are 23 de biți alocați pentru partea întreagă. Toate LSB-urile valorile int care nu se încadrează în cei 23 de biți ai mantisei flotante vor fi aruncate, așa că, deși ordinea numerelor este păstrată, precizia se va pierde. Același lucru este valabil și pentru conversia lung în dublu.

Extinderea conversiei de tip Java poate fi, de asemenea, descrisă astfel:

Liniile continue reprezintă conversii fără pierderi de date. Liniile întrerupte indică pierderea preciziei în timpul conversiei.

Merită să explicăm puțin de ce, de exemplu, tipul de octet nu este convertit automat (nu explicit) în tipul char, deși tipul de octet are o lățime de 8 biți, iar caracterul este de 16, același lucru se aplică și conversiei scurte. a char. Acest lucru se datorează faptului că byte și short sunt tipuri de date semnate, în timp ce char este nesemnat. Prin urmare, în acest caz, trebuie să utilizați casting explicit, deoarece compilatorul trebuie să indice în mod explicit că știți ce doriți și cum va fi procesat bitul semn al tipurilor de octet și scurt la conversia la tipul char.

În cele mai multe cazuri, comportamentul unei valori char este același cu cel al unei valori întregi; prin urmare, o valoare char poate fi utilizată oriunde sunt necesare valori int sau long. Amintiți-vă, totuși, că char este nesemnat, deci se comportă diferit de scurt, chiar dacă intervalul ambelor tipuri este de 16 biți.

mic de statura s = ( mic de statura ) 0xffff; // Acești biți reprezintă numărul -1
char c = „\ uffff”; // Aceiași biți reprezintă caracterul unicode
int i1 = s; // Convertirea scurtă în int dă -1
int i2 = c; // Convertirea char în int dă 65535

Transformare de îngustare ( îngustarea conversiei) apare atunci când o valoare este convertită într-o valoare de tip al cărui interval nu este mai mare decât originalul. Conversiile de restrângere nu sunt întotdeauna sigure: de exemplu, conversia unei valori întregi 13 într-un octet are sens, dar conversia 13000 într-un octet este neînțeleaptă, deoarece octetul poate stoca doar numere de la -128 la 127. Deoarece datele se pot pierde în timpul unei restrângeri conversie, compilatorul Java obiectează la orice astfel de conversie, chiar dacă valoarea care trebuie convertită se încadrează în intervalul mai restrâns al tipului specificat:

int i = 13 ;
octet b = i ; // Compilatorul nu va rezolva această expresie

Singura excepție de la această regulă este alocarea unui literal întreg (valoare int) unei variabile octet sau scurt dacă literalul se potrivește cu intervalul variabilei.

Conversiile de restrângere sunt întotdeauna conversii explicite..

Conversia explicită a tipurilor primitive

Operatorul de conversie explicită de tip sau, mai precis, conversii de tip sunt paranteze, în interiorul cărora este indicat tipul la care se efectuează conversia - (tip)... De exemplu:

int i = 13 ;
octet b = ( octet ) i ; // Conversia forțată a int în octet
i = ( int ) 13.456 ; // Conversia forțată a unui literal de tip double în int 13

Turnarea tipurilor primitive este cel mai des folosită pentru a converti valorile în virgulă mobilă în numere întregi... în care partea fracțională a valorii în virgulă mobilă este pur și simplu aruncată(adică valoarea în virgulă mobilă este rotunjită la zero, mai degrabă decât la cel mai apropiat număr întreg). In esenta este luată numai partea întreagă a tipului realși este deja turnat la tipul întreg țintă.

Când aduceți un mai încăpător întreg tip la biți mai puțin încăpătoare de ordin înalt sunt pur și simplu aruncați... În esență, aceasta este echivalentă cu operarea modulo valorii care urmează să fie turnată de intervalul tipului țintă (de exemplu, pentru tipul octet, acesta este 256).

Numărul fracționar prea mare atunci când este transformat în număr întreg devine MAX_VALUE sau MIN_VALUE.

Prea mare dubla când se reduce la pluti devine Float.POSITIVE_INFINITY sau Float.NEGATIVE_INFINITY.

Tabelul de mai jos este o grilă în care, pentru fiecare tip primitiv, sunt indicate tipurile în care pot fi convertite și metoda de conversie. Scrisoare Nîn tabel înseamnă imposibilitatea conversiei. Scrisoare Yînseamnă o conversie de extindere care se face automat. Scrisoare CUînseamnă o conversie de restrângere care necesită o distribuție explicită. In cele din urma, Y *înseamnă o conversie automată de extindere, în timpul căreia valoarea poate pierde unele dintre cifrele cele mai puțin semnificative. Acest lucru se poate întâmpla la conversia int sau long în float sau double. Tipurile cu virgulă mobilă au o gamă mai largă decât tipurile întregi, astfel încât int sau long pot fi reprezentate ca float sau double. Cu toate acestea, tipurile cu virgulă mobilă sunt numere aproximative și este posibil să nu conțină întotdeauna la fel de mulți biți semnificativi în mantise ca tipurile întregi.

Extinderea automată a tipului în expresii

Merită menționată și promovarea (extinderea) automată a tipurilor în expresii. Am întâlnit deja acest lucru atunci când am luat în considerare tipurile de date întregi și operațiunile pe acestea, dar merită totuși amintit aici pentru a le obține și mai bine și, în plus, este direct legat de acest subiect. În exemplul de mai jos, semnul @ + , , * , / etc.

Adică, toate literalele întregi din expresii, precum și tipurile octet, mic de staturași char extinde la int ... Dacă, așa cum este descris mai sus, nu există alte tipuri de date mai mari ( lung, pluti sau dubla). Prin urmare, exemplul de mai sus va arunca o eroare de compilare ca variabilă c este de tip octet, iar expresia b + 1, ca urmare a promovării automate, are tipul int.

Coerciție implicită în expresiile de co-atribuire

Deși această secțiune se referă la conversia implicită (turnare) a tipurilor, am dat explicația ei aici, deoarece în acest caz funcționează și extinderea automată a tipurilor în expresii, și apoi turnarea implicită a tipurilor. Iată un corp de balet. Exemplul de mai jos cred că va clarifica totul. Ca și în explicația anterioară, semnul @ înseamnă orice operator valid, de exemplu + , , * , / etc.

Acest lucru merită explicat cu un exemplu simplu:

octet b2 = 50 ;
b2 = b2 * 2 ; // nu va compila
b2 *= 2 ; // va compila, deși este echivalent cu b2 = b2 * 2

A doua linie prezentată în exemplu nu se va compila din cauza extinderii automate a tipului în expresii, deoarece expresia b2 * 2 este de tip int, deoarece există o extindere automată a tipului (literalii întregi din expresie sunt întotdeauna int). A treia linie va fi ușor de compilat, deoarece tiparea implicită în expresia de atribuire combinată va funcționa în ea.

Boxing / unboxing - conversia tipurilor primitive în obiecte wrapper

Boxul și unboxinul sunt, de asemenea, subiecte destul de ample, dar sunt destul de simple.

In esenta boxul și unboxingul sunt tipuri primitive către și de la obiectele de ambalare.

Pentru obiectele ambalajelor de tipuri primitive, se aplică tot ceea ce s-a spus mai sus.

Clasele wrapper au fost menționate în tabele la analiza fiecăruia dintre tipurile primitive. Dar atunci a fost doar o mențiune în tabel.

Deci, pentru fiecare tip primitiv există fratele său mai mare, și nu este deloc primitiv, ci este o clasă reală, cu domenii și metode. Și pentru fiecare astfel de pereche este posibilă conversia automată.

De obicei, dacă programul are o mulțime de calcule matematice, atunci este mai bine să folosiți tipuri primitive, deoarece este mai rapid și mai economic în ceea ce privește resursele, dar uneori este necesar să convertiți un tip primitiv într-un obiect.

Permiteți-mi să vă dau un exemplu simplu:

int i3 ;
octet b2 = 3 ;
octet meuB ;
meuB= b2;
meuB++;
b2= meuB;
i3= meuB;

Dacă nu este încă clar de ce este nevoie de acest lucru, atunci acest lucru nu este înfricoșător, doar faceți un nod ca amintire.

Vorbitorul anterior a descris destul de complet transformarea de sus în jos, dar de jos în sus (în opinia mea) necesită explicații suplimentare, deoarece întrebarea este foarte populară și interesantă.

Cum funcționează castingul explicit

Exemplul dvs. arată o conversie ascendentă ( Upcasting):

List coll = new ArrayList ();

Se traduce în rusă după cum urmează: creați o cioară, cum ar fi o pasăre. Creați o matrice dinamică ca o foaie. În majoritatea situațiilor, o conversie ascendentă este complet inutilă.
Cu toate acestea, castingul funcționează în interviuri atunci când vi se pun întrebări despre moștenire. De exemplu, site-ul quizful.net conține în general multe întrebări despre tipare. Prin urmare, voi explica caracteristicile pe care le cunosc.

Deci, în exemplul de mai sus, am creat un obiect de tip ArrayList și o referință de tip List. Amintiți-vă axiomele pentru această metodă:

1. Link-ul poate indica orice părinte. Chiar și cu foarte mult timp în urmă. Adică, puteți trimite coll chiar și pentru a tasta Object. Compilatorul va omite orice referință la clasa părintelui, sau părinte-părinte, sau părinte-părinte ... părinte

2. Referitor la câmp - câmpul de referință este întotdeauna returnat, nu câmpul obiect. Dacă nu există un astfel de câmp în clasa de referință, va exista o eroare de compilare.

Clasa A (int x = 2; // Câmpul părintelui) Clasa B se extinde pe A (int x = 3; // Câmpul care ar trebui să se suprapună pe cel părinte int y = 5; // Câmpul care nu este în clasa părinte.) Test de clasă (public static void main (String args) (A ab = new B (); // Conversie ascendentă System.out.println ("Int x =" + ab.x);))

Va reveni Int x = 2 ... Dacă încercați să accesați un câmp de obiect:

System.out.println ("Int y =" + ab.y); // Eroare de compilare

Compilatorul dumneavoastră va spune că vă înșelați, deoarece nu vede un astfel de câmp prin referință (A ab). Toate cele de mai sus rămân valabile chiar dacă câmpurile dvs. sunt marcate cu modificatori statici.

3. Apelarea unei metode non-statice: în acest caz, va returna metoda obiectului. Dar atunci când accesați o metodă statică, returnează metoda de referință.

Clasa D (public void doSome () (// Metoda nonstatică System.out.println ("Nonstatic doSome din D")) public static void Action () (// Metoda statică System.out.println ("Acțiune statică din D") ");)) public class Okey extinde D (public void doSome () (System.out.println (" doSome din Okey ");) public static void Action () (System.out.println (" Acțiune statică de la Okey ") );) public static void main (Argumente șir) (D o = new Okey (); o.doSome (); // Din clasa Okey o.Action (); // Din clasa D))

DoSome nonstatic de la Okey

Acțiune statică din D

Răspunsul este simplu, o metodă non-statică este o metodă obiect, o metodă statică este o metodă de clasă. Când numim o metodă non-statică, compilatorul înțelege acest lucru: zboară ca o cioară. Când numim static - la propriu, zboară ca o pasăre.

4. Dacă există un apel la o metodă care este descrisă în clasa obiectului, dar nu este descrisă în clasa de referință, va apărea o eroare de compilare. Deoarece, metoda este numită prin referință:

Clasa A () Clasa B extinde A (void someMethod () (); public static void main (String args) (A ab = new B (); ab.someMethod (); // Eroare de compilare.))

5. Constructorul unui obiect (atunci când este creat cu noua comandă) funcționează la fel ca și cum ai da o referință la clasa ta.

Uneori există situații în care aveți o valoare de un anumit tip și trebuie să o atribuiți unei variabile de alt tip. Pentru unele tipuri, acest lucru se poate face fără conversie de tip, în astfel de cazuri vorbim de conversie automată de tip. În Java, conversia automată este posibilă numai dacă precizia variabilei de destinație este suficientă pentru a stoca valoarea inițială. O astfel de conversie are loc, de exemplu, atunci când o constantă literală sau valoarea unei variabile de tip octet sau scurt este introdusă într-o variabilă de tip int. Se numeste extensie (lărgirea) sau crește (promovare), deoarece un tip cu o adâncime de biți mai mică este extins (scalat) la un tip compatibil mai mare. Mărimea tipului int este întotdeauna suficientă pentru a stoca numere în intervalul permis pentru tipul octet, prin urmare, în astfel de situații, nu este necesar un operator de turnare explicit. Reversul nu este adevărat în majoritatea cazurilor, așa că trebuie să utilizați operatorul cast pentru a transforma o valoare int într-o variabilă octet. Această procedură este uneori numită îngustare (îngustarea), deoarece îi spuneți în mod explicit traducătorului să convertească valoarea pentru a se potrivi într-o variabilă de tipul dorit. Pentru a arunca o valoare într-un anumit tip, trebuie să specificați acest tip, cuprins între paranteze, înaintea acestuia. Următorul fragment de cod demonstrează proiectarea de la o sursă (variabilă de tip int) la tipul de destinație (variabilă de tip octet). Dacă în timpul unei astfel de operații valoarea întreagă a ieșit din intervalul permis pentru tipul de octet, aceasta ar fi redusă prin împărțirea modulo la intervalul permis pentru octet (rezultatul împărțirii modulo la un număr este restul împărțirii cu acest număr) ,

int a = 100;
octetb = (octet) a;

2.2.1. Conversie automată a tipurilor în expresii

Când se evaluează valoarea unei expresii, precizia necesară pentru stocarea rezultatelor intermediare trebuie adesea să fie mai mare decât cea necesară pentru a reprezenta rezultatul final,

octet a = 40;
octet b = 50;
octet cu = 100;
int d = a * b / s;

Rezultatul expresiei intermediare (a * b) poate merge în afara intervalului de valori permis pentru tipul de octet. Acesta este motivul pentru care Java promovează automat fiecare parte a expresiei la int, astfel încât există suficient loc pentru rezultatul intermediar (a * b).

Conversia automată a tipurilor poate provoca uneori mesaje de eroare neașteptate ale traducătorului. De exemplu, codul prezentat mai jos, deși pare destul de corect, are ca rezultat un mesaj de eroare în timpul fazei de traducere. În el, încercăm să scriem valoarea 50 * 2, care ar trebui să se potrivească perfect în tipul de octet, într-o variabilă de octet. Dar datorită conversiei automate a tipului rezultat în int, primim un mesaj de eroare de la traducător - la urma urmei, atunci când int este introdus în octet, poate apărea o pierdere de precizie.

octet b = 50;
b = b * 2:
^ Tip incompatibil pentru =. Este necesară transformarea explicită pentru a converti int în octet.
(Tip incompatibil pentru =. Este necesară conversia explicităint înoctet)

Text corectat:
octetb = 50;
b = (octet) (b * 2);

ceea ce face ca b să introducă valoarea corectă de 100.

Dacă o expresie folosește variabile de tip byte, short și int, atunci tipul întregii expresii este promovat automat la int pentru a evita overflow. Dacă tipul a cel puțin unei variabile din expresie este lung, atunci tipul întregii expresii este de asemenea promovat la lung. Amintiți-vă că toate literalele întregi care nu se termină cu un L (sau 1) sunt int.

Dacă expresia conține operanzi de tip float, atunci tipul întregii expresii este promovat automat la float. Dacă cel puțin unul dintre operanzi este de tip double, atunci tipul întregii expresii este promovat la dublu. În mod implicit, Java tratează toate literalele în virgulă mobilă ca fiind duble. Următorul program arată cum este promovat tipul fiecărei valori din expresie pentru a se potrivi cu al doilea operand al fiecărui operator binar.

Promovarea clasei (
public static void main (Argumente șir) (
octet b = 42;
char cu= „a”;
pantaloni scurți = 1024;
int i = 50000;
float f = 5,67f;
dublat = .1234;
rezultat dublu = (f * b) + (i / c) - (d * s);
Sistem, afară. println ((f * b) + "+" + (i / c) + "-" + (d * s));
Sistem, afară. println ("rezultat =" + rezultat); )
}

Subexpresia f * b este un float înmulțit cu un octet, deci este promovată automat la float. Următoarea subexpresie i/c (int împărțită la char) este promovată la int. La fel, tipul subexpresiei d * s (dublu ori scurt) este promovat la dublu. În pasul următor al calculelor, ne ocupăm de trei rezultate intermediare de tipuri float, int și double. În primul rând, când primele două sunt adăugate împreună, tipul int este promovat la float și rezultatul este un tip float. Când o valoare dublă este scăzută din aceasta, tipul de rezultat este promovat la dublu. Rezultatul final al întregii expresii este un dublu.

Acum că suntem familiarizați cu toate tipurile simple, inclusiv cu numere întregi și reale, simboluri și variabile booleene, să încercăm să punem toate informațiile împreună. Următorul exemplu creează variabile ale fiecăruia dintre tipurile simple și emite valorile acelor variabile.

clasa SimpleTypes (
public static void main (Argumente șir) (
octet b = 0x55;
s scurt = 0x55ff;
int i = 1000000;
lung l = 0xffffffffL;
char cu= „A”;
float f = .25f;
dublu d = .00001234;
boolean bool = adevărat;
System.out.println ("byte b =" + b);
System.out.println ("scurt =" + s);
System.out.println ("int i =" + i);
System.out.println ("lung 1 =" + l);
System.out.println ("char cu= ”+ S);
System.out.println ("float f =" + f);
System.out.println ("dublu d =" + d);
System.out.println ("boolean bool =” + bool);)
}

Prin rularea acestui program, ar trebui să obțineți rezultatul prezentat mai jos:

octet b = 85
pantaloni scurți = 22015
int i = 1000000
lung 1 = 4294967295
char cu= a
float f = 0,25
dublu d = 1.234e-005
boolean bool = adevărat

Rețineți că numerele întregi sunt tipărite în notație zecimală, deși am specificat valori pentru unele dintre ele în notație hexazecimală.

Ultima actualizare: 29.10.2018

Fiecare tip de date de bază ocupă un anumit număr de octeți de memorie. Acest lucru impune o restricție asupra operațiunilor care implică diferite tipuri de date. Luați în considerare următorul exemplu:

Int a = 4; octet b = a; //! Eroare

În acest cod, vom întâlni o eroare. Deși atât byte cât și int reprezintă numere întregi. În plus, valoarea variabilei a, care este atribuită unei variabile de tip octet, se încadrează bine în intervalul de valori pentru tipul octet (de la -128 la 127). Cu toate acestea, ne confruntăm cu o eroare de compilare. Pentru că în acest caz încercăm să atribuim niște date de 4 octeți unei variabile care are doar 1 octet.

Cu toate acestea, este posibil ca programul dumneavoastră să aibă nevoie să facă această conversie. În acest caz, trebuie să folosesc operația de conversie a tipului (operația ()):

Int a = 4; octet b = (octet) a; // conversie tip: de la int la octet System.out.println (b); // 4

Operația de conversie a tipului implică o indicație între paranteze a tipului în care urmează să fie convertită valoarea. De exemplu, în cazul operației (octet) a, tipul de date int este convertit în tipul octet. Ca rezultat, obținem o valoare de octet.

Conversii explicite și implicite

Când date de diferite tipuri sunt implicate în aceeași operațiune, nu este întotdeauna necesară utilizarea unei operații de conversie a tipului. Unele tipuri de conversii sunt efectuate implicit, automat.

Conversii automate

Săgețile din figură arată ce tipuri de conversii pot fi efectuate automat. Săgețile punctate arată conversii automate cu pierdere de precizie.

Produs automat fara nici o problema lărgirea transformărilor(largirea) - extind reprezentarea unui obiect în memorie. De exemplu:

Octet b = 7; int d = b; // convertesc din octet în int

În acest caz, un octet, care ocupă 1 octet în memorie, este extins la un int, care ocupă 4 octeți.

Transformările automate extinse sunt reprezentate de următoarele lanțuri:

octet -> scurt -> int -> lung

int -> dublu

scurt -> float -> dublu

char -> int

Conversii automate cu pierdere de precizie

Unele conversii se pot face automat între tipuri de date cu aceeași adâncime de biți sau chiar de la un tip de date cu o adâncime de biți mai mare la un tip cu o adâncime de biți mai mică. Acestea sunt următoarele lanțuri de conversii: int -> float, long -> float și long -> double sunt efectuate fără erori, dar ne putem confrunta cu pierderi de informații în timpul conversiei.

De exemplu:

Int a = 2147483647; float b = a; // de la int la float System.out.println (b); // 2.14748365E9

Conversii explicite

Toate celelalte conversii de tip primitiv aplică în mod explicit definiția conversiei de tip. De obicei, acestea sunt conversii de restrângere de la un tip cu o adâncime de biți mai mare la un tip cu o adâncime de biți mai mică:

Lung a = 4; int b = (int) a;

Pierderea datelor în timpul conversiei

Când folosim transformări explicite, este posibil să avem pierderi de date. De exemplu, cu următorul cod, nu vom avea probleme:

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

Numărul 5 se încadrează bine în intervalul de valori ale tipului de octet, deci după conversie variabila b va fi 5. Dar ce se întâmplă în următorul caz:

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

Rezultatul este 2. În acest caz, 258 este în afara intervalului pentru octet (de la -128 la 127), deci valoarea va fi trunchiată. De ce rezultatul este exact numărul 2?

Numărul a, care este 258, în binar va fi 00000000 00000000 00000001 00000010. Valorile octetilor ocupă doar 8 biți în memorie. Prin urmare, reprezentarea binară a lui int este trunchiată la dreapta cu 8 cifre, adică 00000010, ceea ce dă 2 în zecimală.

Trunchierea numerelor raționale în numere întregi

La convertirea valorilor în virgulă mobilă în valori întregi, partea fracțională este trunchiată:

dublu a = 56,9898; int b = (int) a;

Aici b ar fi 56, chiar dacă 57 ar fi mai aproape de 56,9898. Pentru a evita astfel de incidente, trebuie să utilizați funcția de rotunjire, care se află în biblioteca de matematică Java:

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

Transformări în operațiuni

Există adesea situații în care trebuie să aplicați diverse operații, de exemplu, adăugare și produs, pe valori de diferite tipuri. Unele reguli se aplică și aici:

    dacă unul dintre operanzii operației este de tip dublu, atunci al doilea operand este, de asemenea, convertit în tipul dublu

    dacă condiția anterioară nu este îndeplinită și unul dintre operanzii operației este de tip float, atunci al doilea operand este, de asemenea, convertit în tipul float

    dacă nu sunt îndeplinite condițiile anterioare, unul dintre operanzii operației este de tip long, atunci cel de-al doilea operand este și el convertit în tipul long

    în caz contrar, toți operanzii operației sunt convertiți la tipul int

Exemple de transformări:

Int a = 3; dublu b = 4,6; dublu c = a + b;

Deoarece operația implică o valoare dublă, cealaltă valoare este turnată la tipul dublu, iar suma celor două valori a + b va reprezenta tipul dublu.

Alt exemplu:

Octet a = 3; scurt b = 4; octet c = (octet) (a + b);

Cele două variabile sunt de tip byte și short (nu double, float sau long), deci sunt convertite în int atunci când sunt adăugate, iar suma lor a + b reprezintă un int. Prin urmare, dacă apoi atribuim această sumă unei variabile de tip octet, atunci trebuie să facem din nou o conversie de tip în octet.

Dacă operațiunile implică date de tip char, atunci acestea sunt convertite în int:

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

Top articole similare