Tüüpide teisendamine
Sissejuhatus
Java on staatiliselt tüübitud keel ehk igal muutujal peab olema tüüp, mis määrab ära, milliseid väärtuseid see endas hoida saab. Samas on sageli vaja teisendada muutujaid ühest tüübist teise, näiteks arvutustes või andmete töötlemisel.
Tüüpide teisendamine (type casting) võimaldab teisendada väärtusi ühest andmetüübist teise. Javas eristatakse seda võtet kahel viisil:
- Implicit casting (widening) - Ühest tüübist teise tüüpi teisendamine toimub automaatselt
- Explicit casting (narrowing) - Ühest tüübist teise tüüpi teisendamine toimub käsitsi ehk programmeerija peab ise määrama mis sihttüüp on.
Miks see vajalik on?
Võtame näiteks ühe enam-levinud probleemi: täisarvude jagamine. Olgu näiteks järgnev kood:
int a = 5;
int b = 2;
double result = a / b;
Mis on antud tehte tulemus?
Kui result välja printida saame 2.0:
System.out.println(result); // 2.0
Kuid miks ei ole tulemuseks 2.5?
Kuna a ja b mõlemad on int tüüpi, siis tehakse nende mõlema vahel täisarvuline jagamine.
Tulemuseks on samuti täisarv ehk int, mis seejärel teisendatakse automaatselt double tüübiks.
2 muutub 2.0-iks.
Selle lahendamiseks tuleks üks tehtepooltest teisendada double tüüpi arvuks:
int a = 5;
int b = 2;
double result = (double) a / b;
või
int a = 5;
int b = 2;
double result = a / (double) b;
Kui vähemalt üks jagamistehte operand on double-tüüpi, teisendatakse teine operand automaatselt double-tüübiks ning tehe sooritatakse ujukomaarvuna.
Implicit casting (widening)
Implicit casting ehk tüübi laiendamine tähedab andmete teisendamist väiksemast tüübist suuremasse. See toimub automaatselt ning on ohutu, kuna suurem tüüp suudab alati hoida väiksema tüübi väärtusi ilma andmekaduta.
Laiendava teisendamise hierarhia on järgmine:
Koodinäited:
// int to larger types
int x = 10;
long y = x; // int to long
float z = y; // long to float
double w = z; // float to double
// Char to int
char letter = 'A';
int code = letter; // char to int (A = 65)
// Byte to int
byte small = 100;
int bigger = small; // byte to int
Explicit casting (narrowing)
Explicit casting ehk tüübi kitsendamine tähendab andmete teisendamist suuremast tüübist väiksemasse. Selle võtte peab programmeerija sihttüübi ise määrama ehk see ei toimu automaatselt. Samuti esinevad selle võttega ka teatud ohud.
Süntaks on järgmine:
(targetType) value
Koodinäited:
// Double to int - fracional part is discarded
double pi = 3.14159;
int roundedPi = (int) pi; // 3
// Long to int - May result in overflow
long bigNumber = 123456789L;
int smallerNumber = (int) bigNumber; // Works as long as the value fits into int
Explicit casting puhul on ka teatud ohud, näiteks:
- Murduosa kaotsiminek komaarvu täisarvuks muutmisel
- Overflow ehk väärtus ei mahu sihttüüpi ära
- Täpsuse kadu näiteks
long->floatteisendamisel
Näiteks:
// Overflow
long tooBig = 3_000_000_000L; // 3 billion
int overflow = (int) tooBig; // -1294967296 (overflow)
// Loss of fractional part
double exact = 9.99;
int rounded = (int) exact; // 9 (0.99 got discarded)
Explicit casting sisuliselt tähendab, et programmeerija võtab kompilaatorilt vastutuse enda kanda, juhendades kompilaatorit eirama teatud takistusi tüüpide puhul. Sellest tulenevalt muutub kood raskemini loetavamaks ning vigade esinemine võib tõenäolisem olla. Explicit casting-ut tohiks kasutada ainult juhul, kui kuidagi muud moodi ilma ei saa ning kui see on tõepoolest vajalik.