CodeGym /Blog Java /Aleatoriu /Lărgirea și îngustarea tipurilor primitive
John Squirrels
Nivel
San Francisco

Lărgirea și îngustarea tipurilor primitive

Publicat în grup
Bună! Pe măsură ce ați progresat prin CodeGym, ați întâlnit tipuri primitive de multe ori. Iată o scurtă listă a ceea ce știm despre ei:
  1. Nu sunt obiecte și reprezintă o valoare stocată în memorie
  2. Există mai multe feluri
    • Numere întregi: octet , scurt , int , lung
    • Numere în virgulă mobilă (fracționale): flotant și dublu
    • Valori logice: boolean
    • Valori simbolice (pentru reprezentarea literelor și cifrelor): char
  3. Fiecare tip are propriul său interval de valori:

Tipul primitiv Dimensiunea în memorie Interval de valori
octet 8 biți -128 la 127
mic de statura 16 biți -32768 până la 32767
char 16 biți 0 la 65536
int 32 de biți -2147483648 până la 2147483647
lung 64 de biți -9223372036854775808 până la 9223372036854775807
pluti 32 de biți (2 la puterea lui -149) la ((2 - (2 la puterea lui -23)) * 2 la puterea lui 127)
dubla 64 de biți (-2 la puterea lui 63) la ((2 la puterea lui 63) - 1)
boolean 8 (când este folosit în matrice), 32 (dacă nu este utilizat în matrice) adevărat sau fals
Dar, pe lângă faptul că au valori diferite, diferă și prin cât spațiu ocupă în memorie. Un int ia mai mult de un octet. Și un lung este mai mare decât un scurt. Cantitatea de memorie ocupată de primitivi poate fi comparată cu păpușile rusești: Lărgirea și îngustarea tipurilor primitive - 2 fiecare păpușă are spațiu disponibil în interior. Cu cât păpușa de cuibărit este mai mare, cu atât este mai mult spațiu. O păpușă mare ( lungă ) va găzdui cu ușurință un int mai mic . Se potrivește ușor și nu trebuie să faci nimic altceva. În Java, atunci când lucrați cu primitive, aceasta se numește conversie implicită. Sau altfel spus, se numește lărgire.

Extindere în Java

Iată un exemplu simplu de conversie în creștere:

public class Main {

   public static void main(String[] args) {
      
       int bigNumber = 10000000;

       byte littleNumber = 16;

       bigNumber = littleNumber;
       System.out.println(bigNumber);
   }
}
Aici atribuim o valoare de octet unei variabile int . Atribuirea reușește fără probleme: valoarea stocată într-un octet ocupă mai puțină memorie decât ceea ce poate găzdui un int . Mica păpușă de cuibărit (valoarea octetului) se potrivește cu ușurință în interiorul păpușii de cuib mare ( variabilă int ). Este o altă problemă dacă încerci să faci invers, adică să pui o valoare mare într-o variabilă al cărei interval nu poate găzdui un tip de date atât de mare. Cu păpușile reale, numărul pur și simplu nu s-ar potrivi. Cu Java, se poate, dar cu nuanțe. Să încercăm să punem un int într-o variabilă scurtă :

public static void main(String[] args) {

   int bigNumber = 10000000;
  
   short littleNumber = 1000;

   littleNumber = bigNumber;// Error!
   System.out.println(bigNumber);
}
Eroare! Compilatorul înțelege că încercați să faceți ceva anormal prin împingerea unei păpuși de cuib mare ( int ) în una mică ( scurtă ). În acest caz, eroarea de compilare este un avertisment din partea compilatorului: „Hei, ești absolut sigur că vrei să faci asta?” Dacă ești sigur, atunci îi spui compilatorului: "Totul este în regulă. Știu ce fac!" Acest proces se numește conversie explicită de tip sau îngustare.

Îngustarea în Java

Pentru a efectua o conversie de restrângere, trebuie să indicați în mod explicit tipul în care doriți să vă convertiți valoarea. Cu alte cuvinte, trebuie să răspunzi la întrebarea compilatorului: „Ei bine, în care dintre aceste păpuși mici de cuibărit vrei să pui această păpușă mare de cuib?” În cazul nostru, arată astfel:

public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = (short) bigNumber;
   System.out.println(littleNumber);
}
Indicăm în mod explicit că vrem să punem un int într-o variabilă scurtă și că ne vom asuma responsabilitatea. Văzând că un tip mai restrâns a fost indicat în mod explicit, compilatorul efectuează conversia. Care este rezultatul? Ieșire din consolă: -27008 A fost puțin neașteptat. De ce exact am primit asta? De fapt, totul este foarte simplu. Inițial, valoarea era 10000000 A fost stocată într-o variabilă int , care ocupă 32 de biți. Aceasta este reprezentarea sa binară:
Lărgirea și îngustarea tipurilor primitive - 3
Scriem această valoare într-o variabilă scurtă , care poate stoca doar 16 biți! În consecință, doar primii 16 biți ai numărului nostru vor fi mutați acolo. Restul va fi aruncat. Ca rezultat, variabila scurtă primește următoarea valoare
Lărgirea și îngustarea tipurilor primitive - 4
care în formă zecimală este egală cu -27008 De aceea, compilatorul vă cere să „confirmați” indicând o conversie explicită de restrângere la un anumit tip. În primul rând, aceasta arată că îți asumi responsabilitatea pentru rezultat. Și în al doilea rând, îi spune compilatorului cât spațiu să aloce atunci când are loc conversia. La urma urmei, în ultimul exemplu, dacă am atribui o valoare int unei variabile octet mai degrabă decât unui short , atunci am avea doar 8 biți la dispoziție, nu 16, iar rezultatul ar fi diferit. Tipurile fracționale ( float și double ) au propriul lor proces de îngustare a conversiilor. Dacă încercați să turnați un număr fracțional într-un tip întreg, partea fracțională va fi eliminată.

public static void main(String[] args) {

   double d = 2.7;

   long x = (int) d;
   System.out.println(x);
}
Ieșire consolă: 2

char

Știți deja că char este folosit pentru a afișa caractere individuale.

public static void main(String[] args) {

   char c = '!';
   char z = 'z';
   char i = '8';
  
}
Dar acest tip de date are mai multe caracteristici care sunt importante de înțeles. Să ne uităm din nou la tabelul intervalelor de valori:
Tipul primitiv Dimensiunea în memorie Interval de valori
octet 8 biți -128 la 127
mic de statura 16 biți -32768 până la 32767
char 16 biți 0 la 65536
int 32 de biți -2147483648 până la 2147483647
lung 64 de biți -9223372036854775808 până la 9223372036854775807
pluti 32 de biți (2 la puterea lui -149) la ((2 - (2 la puterea lui -23)) * 2 la puterea lui 127)
dubla 64 de biți (-2 la puterea lui 63) la ((2 la puterea lui 63) - 1)
boolean 8 (când este folosit în matrice), 32 (dacă nu este utilizat în matrice) adevărat sau fals
Intervalul de la 0 la 65536 este indicat pentru tipul de caractere . Dar ce înseamnă asta? La urma urmei, un caracter nu reprezintă doar numere, ci și litere, semne de punctuație... Chestia este că în Java valorile de caractere sunt stocate în format Unicode. Am întâlnit deja Unicode într-una dintre lecțiile anterioare. Probabil vă amintiți că Unicode este un standard de codificare a caracterelor care include simbolurile aproape tuturor limbilor scrise ale lumii. Cu alte cuvinte, este o listă de coduri speciale care reprezintă aproape fiecare caracter în orice limbă. Întregul tabel Unicode este foarte mare și, desigur, nu este nevoie să-l înveți pe de rost. Iată o mică parte din el: Lărgirea și îngustarea tipurilor primitive - 5 Principalul lucru este să înțelegeți cum sunt stocate caracterele și să vă amintiți că, dacă cunoașteți codul pentru un anumit caracter, puteți oricând să produceți acel caracter în programul dvs. Să încercăm cu un număr aleator:

public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
Ieșire din consolă: 耰 Acesta este formatul folosit pentru stocarea caracterelor în Java. Fiecare simbol corespunde unui număr: un cod numeric de 16 biți (doi octeți). În Unicode, 32816 corespunde caracterului chinezesc 耰. Luați notă de următorul punct. În acest exemplu, am folosit o variabilă int . Ocupă 32 de biți în memorie, în timp ce un caracter ocupă 16. Aici am ales un int , deoarece numărul nostru (32816) nu va încadra într-un scurt . Deși dimensiunea unui caracter (la fel ca un scurt ) este de 16 biți, nu există numere negative în intervalul de caractere , deci partea „pozitivă” a caracteruluiintervalul este de două ori mai mare (65536 în loc de 32767 pentru tipul scurt ). Putem folosi un int atâta timp cât codul nostru rămâne sub 65536. Dar dacă creați o valoare int mai mare decât 65536, atunci aceasta va ocupa mai mult de 16 biți. Și acest lucru va avea ca rezultat o conversie îngustă

char c = (char) x;
biții suplimentari vor fi aruncați (așa cum am discutat mai sus) și rezultatul va fi destul de neașteptat.

Caracteristici speciale de adăugare de caractere și numere întregi

Să ne uităm la un exemplu neobișnuit:

public class Main {

   public static void main(String[] args) {

      char c = '1';

      int i = 1;

       System.out.println(i + c);
   }
}
Ieșire consolă: 50 O_О Cum are sens? 1+1. De unde au venit cei 50?! Știți deja că charvalorile sunt stocate în memorie ca numere în intervalul de la 0 la 65536 și că aceste numere sunt o reprezentare Unicode a unui caracter. Lărgirea și îngustarea tipurilor primitive - 6 Când adăugăm un caracter și un tip de număr întreg, caracterul este convertit în numărul Unicode corespunzător. În codul nostru, când am adăugat 1 și „1”, simbolul „1” a fost convertit în propriul cod, care este 49 (puteți verifica acest lucru în tabelul de mai sus). Prin urmare, rezultatul este 50. Să luăm din nou vechiul nostru prieten 耰 ca exemplu și să încercăm să-l adăugăm la un număr.

public static void main(String[] args) {

   char c = '耰';
   int x = 200;

   System.out.println(c + x);
}
Ieșire din consolă: 33016 Am descoperit deja că 耰 corespunde cu 32816. Și când adunăm acest număr și 200, obținem rezultatul nostru: 33016. :) După cum puteți vedea, algoritmul de aici este destul de simplu, dar nu ar trebui să-l uitați .
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION