Učim sestru Javi: o konverziji osnovnih tipova podataka
"Sanmej, danas da porazgovaramo o konverziji tipova podataka u Javi," rekao sam Sanmej direktno.
"Važi," rekla je Sanmej veselo.
Svrha konverzije tipova podataka je da se pri izračunavanju izraza osigura međusobna kompatibilnost različitih tipova podataka.
01. Automatska konverzija tipova
Automatska konverzija tipova (automatsko proširenje tipa) je proces u kojem Java kompilator, bez eksplicitne konverzije, automatski prevodi jedan osnovni tip podataka u drugi. Ova konverzija se obično dešava tokom izračunavanja izraza, kada različiti tipovi podataka treba da budu međusobno kompatibilni. Automatska konverzija tipova sledi sledeća pravila:
- Ako je bilo koji operand tipa double, ostali operandi se prevode u tip double.
- U suprotnom, ako je bilo koji operand tipa float, ostali operandi se prevode u tip float.
- U suprotnom, ako je bilo koji operand tipa long, ostali operandi se prevode u tip long.
- U suprotnom, svi operandi se prevode u tip int.
Treba napomenuti da se automatska konverzija tipova dešava samo između kompatibilnih tipova. Na primer, konverzija iz manjeg tipa podataka (poput int) u veći tip (poput long ili double) je bezbedna, jer veći tip može da primi sve moguće vrednosti manjeg tipa.
byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> doubleEvo jednostavnog primera koji demonstrira automatsku konverziju tipova:
int intValue = 5;
double doubleValue = 2.5;
// automatska konverzija tipova: intValue se prevodi u tip double
double result = intValue * doubleValue;
System.out.println("Rezultat: " + result); // izlaz: Rezultat: 12.5U ovom primeru imamo promenljivu intValue tipa int i promenljivu doubleValue tipa double. Kada ih pomnožimo, prema pravilu automatske konverzije tipova, intValue će biti prevedena u tip double, kako bi se pomnožila dva operanda tipa double. Konačni rezultat biće vrednost tipa double: 12.5.
Još jedan primer: kupac u supermarketu kupuje 2 kutije paste za zube i 4 kutije maramica. Pasta za zube košta 10.9 yuana, a maramice 5.8 yuana; izračunajte ukupnu cenu. Kod je sledeći:
float price1 = 10.9f; // definiše cenu paste za zube, jednostruka preciznost float
double price2 = 5.8; // definiše cenu maramica, dvostruka preciznost double
int num1 = 2; // definiše količinu paste za zube, celi broj int
int num2 = 4; // definiše količinu maramica
double res = price1 * num1 + price2 * num2; // izračunava ukupnu cenu
System.out.println("Ukupno plaćeno kasirku " + res + " yuana"); // ispisuje ukupnu cenuU gorenavedenom kodu prvo je definisana promenljiva tipa float za cenu paste za zube, zatim promenljiva tipa double za cenu maramica, pa dve promenljive tipa int za količine artikala; na kraju se, nakon množenja i sabiranja, rezultat smešta u promenljivu tipa double i ispisuje.
Ukupno plaćeno kasirku 44.99999923706055 yuanaIz rezultata izvršavanja se vidi da u operaciji učestvuju tipovi float, int i double, a konačan ispisani rezultat je tipa double. Ova konverzija se obično naziva "automatsko proširenje tipa u izrazu".
Automatsko proširenje tipa ima prednosti, ali može izazvati i zbunjujuće greške pri prevođenju. Na primer, sledeći program koji izgleda ispravno zapravo stvara problem:
byte b = 50;
b = b * 2; // Type mismatch: cannot convert from int to byteKao što je prikazano, druga linija prijavljuje grešku "Type mismatch: cannot convert from int to bajt" (neslaganje tipova: ne može se prevesti iz int u bajt).
Ovaj program pokušava da potpuno legalnu vrednost tipa bajt, 50*2, smesti u promenljivu tipa bajt. Međutim, prilikom izračunavanja izraza operandi se automatski proširuju na tip int, pa i rezultat izračunavanja postaje tip int. Tako rezultat izraza sada jeste tip int i ne može se dodeliti tipu bajt bez eksplicitne konverzije.
Zato treba koristiti eksplicitnu prinudnu konverziju tipova, na primer:
byte b = 50;
b = (byte)(b*2);Tako se dobija ispravna vrednost 100.
Ali sledeći kod neće prijaviti grešku:
byte b = 50;
b *= 2;Zato što je b *= 2 isto što i b = (bajt)(b*2); kompilator automatski vrši prinudnu konverziju tipa.
Pored toga, ranije je jedan član zajednice slabo razumeo sledeći kod:
byte b = 50;Taj član smatra da je 50 podrazumevano tip int, i da bi konverzija iz većeg opsega u manji trebalo da zahteva prinudnu konverziju.
Moj odgovor je da kompilator za nas automatski radi implicitnu konverziju: vrednost je tipa int, ali ako je njena vrednost u opsegu tipa bajt (-127 do 128), kompilator će automatski prevesti tip int u tip bajt.

Nadamo se da razumete: automatska konverzija tipova nije ograničena sa malog tipa na veliki, može biti i sa velikog na mali — sve dok je vrednost u opsegu manjeg tipa, kompilator će za nas automatski odraditi implicitnu konverziju.
Napomena: tip char je poseban — char se automatski prevodi u int, long, float i double, ali bajt i short ne mogu automatski u char, a ni char ne može automatski u bajt ili short.
02. Prinudna konverzija tipova
Prinudna konverzija tipova je proces u kojem se u Javi jedan tip podataka eksplicitno prevodi u drugi. Za razliku od automatske konverzije tipova, prinudna konverzija zahteva da programer eksplicitno navede konverziju koja se izvršava. Prinudna konverzija tipova može biti potrebna u sledećim situacijama:
- Prevođenje većeg tipa podataka u manji.
- Prevođenje broja u pokretnom zarezu u celi broj.
- Prevođenje znakovnog tipa u numerički tip.
Treba napomenuti da prinudna konverzija tipova može dovesti do gubitka podataka ili smanjenja preciznosti, jer ciljni tip možda ne može da primi sve moguće vrednosti originalnog tipa. Stoga, prilikom prinudne konverzije tipova treba osigurati da vrednost nakon konverzije i dalje ostane u opsegu ciljnog tipa.
double -> float -> long -> int -> char -> short -> byteEvo jednostavnog primera koji demonstrira prinudnu konverziju tipova:
double doubleValue = 42.8;
// prinudna konverzija tipova: tip double se prevodi u tip int
int intValue = (int) doubleValue;
System.out.println("Celobrojna vrednost: " + intValue); // izlaz: Celobrojna vrednost: 42U ovom primeru imamo promenljivu doubleValue tipa double. Želimo da je prevedemo u promenljivu intValue tipa int. Zato koristimo sintaksu prinudne konverzije tipova, odnosno ispred promenljive koja se prevodi stavljamo zagradu sa ciljnim tipom (npr. (int)).
Treba napomenuti da se prilikom prevođenja doubleValue u tip int decimalni deo odseca. Zato će izlazni rezultat biti: Celobrojna vrednost: 42. U ovom slučaju gubitak preciznosti je prihvatljiv, ali u drugim situacijama možda treba pažljivije obraditi konverziju tipova kako bi se izbegao gubitak podataka.
Kupac u supermarketu kupuje 2 kutije paste za zube i 4 kutije maramica. Pasta za zube košta 10.9 yuana, a maramice 5.8 yuana; izračunajte ukupnu cenu, a prilikom izračunavanja ukupne cene za skladištenje koristite podatak tipa int. Kod je sledeći:
float price1 = 10.9f;
double price2 = 5.8;
int num1 = 2;
int num2 = 4;
int res2 = (int) (price1 * num1 + price2 * num2);
System.out.println("Ukupno plaćeno kasirku " + res2 + " yuana");U gorenavedenom primeru u operaciji učestvuju podaci tipova double, float i int; rezultat operacije je podrazumevano tip double, a zadatak traži rezultat tipa int. Pošto je opseg tipa int manji od opsega tipa double, potrebna je prinudna konverzija tipova.
Ukupno plaćeno kasirku 44 yuanaRezime
Razmotrite rezultate sledećih izraza:
int a = 1500000000, b = 1500000000;
int sum = a + b;
long sum1 = a + b;
long sum2 = (long)a + b;
long sum3 = (long)(a + b);"Ovi rezultati bi trebalo da budu isti, svi su rezultat a+b," zaključila je Sanmej pomislivši.
"Nisu, Sanmej, pogledaj vrednosti ovih rezultata," rekao sam.
-1294967296
-1294967296
3000000000
-1294967296"Šta je ovo? Zašto rezultati nisu isti?" Sanmej je bila pomalo zbunjena.
"Zato što je opseg tipa int -2147483648~2147483647, a vrednosti i a i b su 1500000000; zbir prelazi opseg tipa int, pa dolazi do preliva (overflow)," objasnio sam.
"A zašto je onda rezultat sum2 3000000000?" pitala je Sanmej.
"Zato što se sum2 izračunava tako što se prvo a prevodi u tip long (prinudna konverzija tipova), a zatim sabira sa b (implicitna konverzija tipova); tada je i rezultat tipa long, a 3000000000 ne prelazi opseg tipa long," rekao sam.
int sum = a + b: a i b su tipa int, pa je i rezultat a+b tipa int, ali zbir a+b prelazi opseg tipa int, pa dolazi do preliva.long sum1 = a + b: a i b su tipa int, pa je i zbir a+b tipa int, ali prelazi opseg tipa int, pa dolazi do preliva; da zbir a+b ne prelazi opseg tipa int, rezultat a+b bi se implicitno preveo u tip long.long sum2 = (long)a + b: a je tipa int, ali(long)aprevodi a u tip long, a zatim se sabira sa b; tada se b implicitno proširuje na tip long, pa je i rezultat desne strane tipa long, a 3000000000 ne prelazi opseg tipa long.long sum3 = (long)(a + b): a i b su tipa int, pa je i rezultat a+b tipa int, ali prelazi opseg tipa int, pa dolazi do preliva; čak i ako spolja postoji sloj prinudne konverzije u long, pre nego što je stigla da se izvrši, rezultat a+b već je prelio, pa prinudna konverzija ne pomaže.
Time su, uglavnom, jasno objašnjene konverzije osnovnih tipova u Javi.
