MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Conversii ale tipurilor de date de bază

Fiecare tip de date de bază ocupă o anumită cantitate de memorie, ceea ce impune restricții asupra operațiilor care implică diverse tipuri de date. Să luăm următorul exemplu:

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

În acest cod ne confruntăm cu o eroare. Deși tipul byte și tipul int reprezintă ambele numere întregi, iar valoarea variabilei a, care este atribuită variabilei de tip byte, se încadrează în intervalul valorilor pentru tipul byte (de la -128 la 127), întâlnim totuși o eroare la compilare. Asta deoarece încercăm să atribuim date care ocupă 4 octeți unei variabile care ocupă doar 1 octet.

Cu toate acestea, uneori poate fi necesar ca o astfel de conversie să fie efectuată. În acest caz, trebuie să utilizăm operația de conversie a tipurilor (operația ()):

int a = 4;
byte b = (byte) a;  // conversie de la tipul int la tipul byte
System.out.println(b); // 4

Operația de conversie presupune specificarea în paranteze a tipului la care vrem să convertim valoarea. De exemplu, în cazul operației (byte) a, se face conversia datelor de tip int în tip byte. În final, obținem o valoare de tip byte.

Conversii explicite și implicite

Când într-o operație sunt implicate date de tipuri diferite, nu este întotdeauna necesar să folosim operația de conversie a tipurilor. Unele conversii se efectuează implicit, automat.

Conversii automate

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

Conversiile de tipuri în limbajul Java se fac automat în cazul conversiilor de extindere (widening), care extind reprezentarea obiectului în memorie. De exemplu:

byte b = 7;
int d = b;  // conversie de la byte la int

În acest caz, valoarea de tip byte, care ocupă 1 octet în memorie, este extinsă la tipul int, care ocupă 4 octeți.

Conversiile automate de extindere sunt reprezentate de următoarele lanțuri:

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

Conversii automate cu pierdere de precizie

Unele conversii pot fi efectuate automat între tipuri de date cu aceeași lățime sau chiar de la tipuri de date cu o lățime mai mare la una mai mică. Acestea includ lanțurile de conversii: int -> float, long -> float și long -> double. Aceste conversii nu generează erori, dar pot duce la pierderi de informații.

De exemplu:

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

Conversii explicite

În toate celelalte conversii ale tipurilor primitive, se folosește explicit operația de conversie a tipurilor. Acestea sunt de obicei conversii de îngustare (narrowing), de la tipuri cu o lățime mai mare la tipuri cu o lățime mai mică:

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

Pierderea de date la conversie

La conversiile explicite putem întâmpina pierderi de date. De exemplu, în următorul cod nu vom avea nicio problemă:

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

Numărul 5 se încadrează în intervalul valorilor de tip byte, deci după conversie, variabila b va fi egală cu 5. Dar ce se întâmplă în cazul următor:

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

Rezultatul va fi 2. În acest caz, numărul 258 este în afara intervalului pentru tipul byte (de la -128 la 127), deci va avea loc o trunchiere a valorii. De ce rezultatul este 2?

Numărul a, care este egal cu 258, în sistem binar este reprezentat astfel: 00000000 00000000 00000001 00000010. Valorile de tip byte ocupă în memorie doar 8 biți. Prin urmare, reprezentarea binară a numărului int este trunchiată la 8 biți din dreapta, adică 00000010, care în sistem zecimal este 2.

Trunchierea numerelor raționale la întregi

La conversia valorilor cu virgulă mobilă în valori întregi, partea zecimală este trunchiată:

double a = 56.9898;
int b = (int) a;

Aici valoarea lui b va fi 56, chiar dacă 57 ar fi mai aproape de 56.9898. Pentru a evita astfel de situații, putem folosi funcția de rotunjire din biblioteca matematică Java:

double a = 56.9898;
int b = (int) Math.round(a);

Conversii în timpul operațiilor

Sunt frecvente situațiile în care trebuie să aplicăm diverse operații, cum ar fi adunarea sau înmulțirea, asupra valorilor de tipuri diferite. Și aici se aplică câteva reguli:

  • dacă unul dintre operanzi este de tip double, atunci și celălalt operand este convertit la double
  • dacă primul caz nu se aplică, iar unul dintre operanzi este de tip float, atunci și celălalt operand este convertit la float
  • dacă nici una dintre situațiile anterioare nu se aplică, iar unul dintre operanzi este de tip long, atunci și celălalt operand este convertit la long
  • în caz contrar, toți operanzii sunt convertiți la tipul int

Exemple de conversii:

int a = 3;
double b = 4.6;
double c = a + b;

Deoarece în operație este implicată o valoare de tip double, celălalt operand este convertit la double, iar suma celor două valori a + b va fi de tip double.

Alt exemplu:

byte a = 3;
short b = 4;
byte c = (byte) (a + b);

Două variabile de tip byte și short (nu double, float sau long), deci la adunare sunt convertite la tipul int, iar suma lor a + b va reprezenta o valoare de tip int. Prin urmare, dacă dorim să atribuim această sumă unei variabile de tip byte, trebuie din nou să facem conversia la byte.

Dacă în operații sunt implicate date de tip char, ele sunt convertite la int:

int d = 'a' + 5;
System.out.println(d);  // 102
← Lecția anterioară Lecția următoare →