Típusok - 1. java bevezető

|
1. java bevezető
|
bet | 4/51 | Sana | 07.04.2017 | Hajmi | 1,08 Mb. | | #3295 |
3.2. Típusok
A Java nyelv - hasonlóan a Pascal és a C/C++ nyelvhez - alapvetően bináris számítógépeken futó programok készítésére használatos: egyszerűbb a mi fogalmainkat használva megírni egy programot, amelyet aztán lefordítunk a számítógép nyelvére (gépi kód), amelyet ugyan meg lehet tanulni, de hatékonyabban tudunk felhasználói igényeket kielégíteni, ha magas szinten programozunk. A bináris számítógépek hatékony kihasználásához nem feltétlen szükséges ismernünk a számítógép magját alkotó CPU által kezelhető adattípusokat, ezt megteszik helyettünk az említett programnyelvek, mégpedig a primitív típusok által.
3.2.1. Primitív típusok
Egy bináris (más néven digitális) számítógép számára minden a világon két számból épül fel: 0 és 1, amelyeket bináris számnak (binary digit, vagyis bit) nevezünk. Bármi, amit a számítógépünkön találunk, az mind bináris számok különféle kombinációja és sorozata, s a kettes számrendszer írja le a kombinációk és sorozatok kódolását. A különféle hosszúságú kettes számrendszerben kódolt számoknak a szakma neveket adott, nézzük át őket (a teljesség igénye nélküli):
-
bit (boolean) - bit: a legkisebb egység, értéke lehet 0 vagy 1, illetve igaz (true) vagy hamis (false).
-
byte - bájt: 8 bináris szám által reprezentált szám, értéktartománya 28, vagyis 0 – 255 vagy -128 – 127.
-
char - karakter: egy bájt által reprezentált karakter, kódolása általában ASCII.
-
word - egy gépi szó: két bájt, 16 bit által reprezentált szám, értéktartománya 216, vagyis 0 – 65535 vagy -32768 – 32767.
-
integer - egész szám: egy vagy több gépi szó által reprezentált szám, értéktartománya tipikusan 232, vagyis 0 – 4 milliárd vagy -2 milliárd – 2 milliárd.
-
long (integer) - nagy egész szám: általában négy gépi szó által reprezentált szám, értéktartománya általában 264, vagyis 0 – 16 trillió vagy -8 trillió – 8 trillió.
-
real (float) - valós szám: két gépi szóból álló egyszerű (lebegőpontos) valós szám, értéktartománya előjel nélkül ~1.4-45 – ~3.438.
-
double - nagy valós szám: négy gépi szóból álló (lebegőpontos) valós szám, értéktartománya előjel nélkül: ~4.9-324 – ~1.8308.
A lebegőpontos számok használata során ismernünk kell a trükköt, hiszen nyilvánvaló kell legyen, hogy 32 bitbe nem fér el minden valós szám 1.4-45 és 3.438 között. A megoldás egyszerű: az egész számokat tároló megoldások a szám összes számjegyét tárolják, míg az utóbbi kettő - valós szám tárolására használt számkódolási eljárás - kerekít. A megadott tartományon belül tetszőlegesen nagy számot tudunk tárolni, de csak 7-8 számjegy pontossággal. További trükk, hogy a nulla értéket csak megközelíteni tudjuk, a legkisebb érték és a nulla között mindig lesz egy tartomány, amelyet nem tudunk használni. Az alábbi számegyenesre tekintve láthatjuk, hogy a kék pontok jelentik a kódolás határértékeit, a zöld részen tudunk számokat tárolni 7-8 számjegy pontossággal, és a piros területeket már nem tudjuk tárolni:
A Java nyelvben a felsorolás sorrendjében a boolean, a byte, a char, a short, az int, a long, a float és a double használatos, ezeket nevezzük primitív típusnak. Fontos tudni, hogy nincs előjel nélküli típus, az összes primitív típus előjeles szám, nézzünk példát ezen típusok használatára.
Vegyük elő a NetBeans környezetben a már létrehozott Kocsma projektet, és keressük meg benne a kocsma csomagot, majd azon belül a Main osztályt, majd az alábbi programot írjuk bele:
view plaincopy to clipboardprint?
-
package kocsma;
-
-
public class Main
-
{
-
-
public static void main(String[] args)
-
{
-
// Ide fogjuk írni az alábbi programrészleteket
-
}
-
}
A // kezdetű sor helyére kell írni az alábbiakban megemlített programrészleteket, majd az F6 gomb megnyomásával futtatni tudjul a (helyesen megírt) programot.
A boolean
A boolean típust akkor használjuk, ha egy eldönthető kérdésekre adott válasz csak igen/igaz vagy nem/hamis lehet, a boolean ugyanis nem képes a talán vagy a nem tudom válaszokat értelmezni. A C/C++ nyelvektől eltérően egy boolean típusú változó értéke csak a truevagy a false értéket veheti fel, a számszerűen jelzett értékeket nem képes értelmezni.
view plaincopy to clipboardprint?
-
boolean igaz = true;
-
boolean hamis = false;
-
boolean válasz;
-
válasz = igaz;
Vannak olyan műveletek, amelyek természetszerűleg boolean értéket adnak eredményül:
view plaincopy to clipboardprint?
-
válasz = 9 < 3;
-
System.out.println(válasz);
-
válasz = 3 < 10;
-
System.out.println(válasz);
Az első esetben false (hamis) eredményt kapunk, hiszen a kilenc nem kisebb, mint a három; a második esetben az eredmény true(igaz), hiszen a három kisebb, mint a tíz.
A példában említett true és false literál, vagyis a nyelvbe épített és értékkel bíró fogalom. Láthatunk továbbá több deklarációt és értékadásokat is - ezekről később több szót ejtek.
A byte
A byte típust akkor célszerű használnunk, ha nulla közeli egész számokkal számolunk, hiszen értéktartománya mindössze a -128 és a 127 közötti számokra érvényes:
view plaincopy to clipboardprint?
-
byte szám;
-
szám = 12;
-
szám = -12;
-
szám = -128;
-
szám = 127;
A példában láthatunk egy deklarációt és négy értékadást, ahol a szám nevű változónak adunk más-más értéket, s itt már szám literálokat használunk. Fontos tudni, hogy a primitív típusok képesek a csöndes túlcsordulásra:
view plaincopy to clipboardprint?
-
byte szám;
-
szám = 127;
-
szám++;
-
System.out.println(szám);
A rövidke programrészlet eredménye -128 lesz, nem pedig a matematikailag várható 128. Ennek oka, hogy a változó túlcsordult, túllépte az értékkészlete egyik határát, és ezért értékül az értékkészletének másik határértékét veszi fel. Nagyon oda kell figyelnünk erre a tulajdonságra, mivel a programunk mindezt csöndben teszi, legtöbbször igen keserves és hosszú munkával tudjuk csak megkeresni a hiba okát.
A short, az int és a long
A short, az int és a long teljesen azonos módon használható, mint a byte, a különbség mindössze az értéktartományban van (illetve abban, hogy a long típus literál használatához a szám mögé egy l karaktert kell írnunk):
-
short: -32768 – 32768
-
int: –2147483648 – 2147483647
-
long: -9223372036854775808l – 9223372036854775807l
Ha nem adunk meg egy egész szám literál után módosító karaktert, akkor a nyelv szabályai szerint a fordító megpróbálja konvertálni arra a típusra, ami a használt változó típusa, egyéb esetben a literál típusa int lesz.
A char
A többi nyelvhez hasonlóan a char egy öszvér adattípus, alapvetően számokat tartalmaz, de ha az értékét kiírjuk, akkor karaktereket kapunk eredményül. A Java nyelv úttörő volt a tekintetben, hogy a char típus alapja nem a 8 bites byte, hanem az 32 bites integer, hiszen a Java nem ASCII alapú, hanem UTF-8 az alapértelmezett karakter kódolása, mivel ismert világ összes karaktere nem fér el 8 biten.
Nézzük meg ezt a gyakorlatban:
view plaincopy to clipboardprint?
-
char betű = 64;
-
System.out.print(betű);
-
betű = ’\n’;
-
System.out.print(betű);
-
betű = ’a’;
-
System.out.print(betű);
-
betű = ’\t’;
-
System.out.print(betű);
-
betű = ’\\’;
-
System.out.print(betű);
-
betű = ’\’’;
-
System.out.print(betű);
-
betű = ’"’;
-
System.out.print(betű);
-
betű = ’\070’;
-
System.out.print(betű);
-
betű = ’\u003F’;
-
System.out.print(betű);
Eredményül az alábbi (ránézésre értelmetlen) karakter halmazt kapjuk:
view plaincopy to clipboardprint?
-
@
-
a \’"8?
Lássuk a dekódolást:
-
A @ karakter UTF-8 (és ASCII) kódja a 64 szám, ezért a @ az első kiírt karakter.
-
A \n karakter az újsor kódja, ez nem látható karakter, viszont a (szintén nem látható) kurzort a következő sorba teszi.
-
A következő sor elején kiírt a betű egyértelmű kell legyen, hiszen ezt adtuk értékül a betű nevű változónak.
-
A negyedik kiírt karakter ismét egy nem látható karakter (\t), amely egy tabulátor pozícióval jobbra mozgatja a kurzort.
-
Biztos felmerült, hogy a \ karaktert hogy tudjuk kiírni: egyszerűen a \\ karaktert kell használnunk. A \ (backslash vagy visszaper jel) egy speciális karakter, amely az őt követő karakternek is speciális jelentést ad.
-
A szimpla idézőjel kiírásához a \’ karaktereket kell használnunk.
-
A dupla idézőjel kiírható, ha szimpla idézőjelek között van.
-
A \070 kódolás oktális formátumú számot hordoz, a 070 oktális szám azonos az 56 decimális számmal, amely az UTF-8 kódrendszerben a ’8’ karakternek felel meg.
-
A \u003F kódolás hexadecimális formátumú számot jelent, a 003F szám azonos a 63 decimális számmal, amelynek a ’?’ karakter felel meg.
Mint láthatjuk, eléggé változatos módon tudunk karaktereket megadni, azonban a char kettős természetét az is meghatározza, hogy tudunk vele műveleteket végezni:
view plaincopy to clipboardprint?
-
char betű = 64;
-
betű++;
-
System.out.print(betű);
-
betű += 0;
-
System.out.print(betű);
-
betű += ’0’;
-
System.out.print(betű);
Az eredmény az AAq karaktersorozat lesz, hiszen a 64 az ’@’ karaktert kódolja, amihez ha hozzáadunk egyet, akkor ’A’ betű lesz, amit a 65 kódol. Ha ehhez hozzáadunk nullát (0), akkor az eredmény továbbra is 65 marad, de ha karakteresen adunk hozzá nullát (’0’), amelynek a számszerű értéke 48, akkor az eredmény 113 lesz (mivel 65+48 az 113), amely szám a ’q’ karaktert kódolja.
A karakter literálok két szimpla idézőjel közötti karakterek. Általában egy karakter, de ha az első karakter visszaper jel (\), akkor több karakter is lehet a két idézőjel között. Érdemes megtanulni a speciális karakter literálok használatát, mivel használatuk sok esetben szükséges a szövegfeldolgozáshoz.
A float és a double
A valós számok használata akkor kerül előtérbe, amikor olyan számolásokat végzünk, amelyek nem végezhetők el könnyedén egész számokon. A valós számok használata lassíthatja a program működését, mivel ezek kezelése néhány processzoron nincsen kellően gyorsítva, ezért csak akkor használjunk valós számokat, amikor feltétlenül szükséges. Nézzük a float típus használatát:
view plaincopy to clipboardprint?
-
float szám = 0;
-
System.out.println(szám);
-
szám = 1/3;
-
System.out.println(szám);
-
szám = 1f/3f;
-
System.out.println(szám);
-
szám = -1*0f;
-
System.out.println(szám);
-
System.out.println(szám == 0f);
-
szám = 100000000000000000000000000000000000000f;
-
System.out.println(szám);
-
szám = 1.0E38f;
-
System.out.println(szám);
Eredményül nem pont azt kapjuk, amit várnánk:
view plaincopy to clipboardprint?
-
0.0
-
0.0
-
0.33333334
-
-0.0
-
true
-
1.0E38
-
1.0E38
Az első 0.0 érthető, hiszen ezt adtuk értékül a szám nevű változónak. A második 0.0 azonban elgondolkodtató: az egyharmad értéke nem szabadna nulla legyen. Ennek oka az, hogy a Java nyelv két egész számot lát: elosztja az egyet hárommal: hányszor van meg egyben a három? Ugye egyszer sem, ezért kaptunk eredményül nullát. A problémát úgy tudjuk kikerülni, hogy a szám mögé írt f betűvel mondjuk meg, hogy ez a szám nem egész szám, hanem float. A 1f/3f művelet eredménye már 0.33333334, mivel a float csak nyolc számjegy pontosságú, azt követően nincs több értékes számjegy. A -0.0 eredmény a számábrázolás érdekessége, ugyanis van plusz nulla és mínusz nulla is, és ahogy a következő sorban látjuk: a kettő egyenlő egymással. A nagy számokat megadhatjuk a számjegyekkel is, de rövidebb a normálforma: 1.0·1038, amely a program forrásában 1.0E38 formán kódolódik.
A double használata annyiban tér el a float használatától, hogy az f karakter helyett d karaktert kell használnunk a literál megadásakor (amelyet akár el is hagyhatunk, hiszen a double típus az alapértelmezett lebegőpontos típus).
3.2.2. Primitív burkoló osztályok (primitive wrappers)
Mindegyik primitív típusnak van egy burkoló osztálya, amely már használható objektum orientált módon, s képes önmagán néhány egyszerű (nem matematikai) műveletet elvégezni.
A Boolean osztály
A boolean típushoz tartozó burkoló osztály, amelynek leginkább azt a tudását használjuk fel, hogy szövegből képes önmagát legyártani:
view plaincopy to clipboardprint?
-
Boolean válasz= new Boolean("tRuE");
-
System.out.println(válasz);
A paraméterben átadott szöveg hatására a válasz nevű változó értéke true lesz. Akkor és csak akkor lesz az eredmény true, ha az átadott szöveg karakterhelyesen "true", azonban a kis és nagybetű nincs megkülönböztetve (case insensitive). Ugyanígy használható a valueOfmetódus is, amely egy picit gyorsabb is:
view plaincopy to clipboardprint?
-
Boolean válasz= Boolean.valueOf("tRuE");
-
System.out.println(válasz);
Az eredmény jelen esetben is true lesz. Az 1.5 Java verziótól használhatjuk az automatikus konverziót is:
view plaincopy to clipboardprint?
-
Boolean válasz = true;
-
boolean érték = válasz;
Az 1.5 verzió előtt ezt csak hosszabban tudtuk leírni:
view plaincopy to clipboardprint?
-
Boolean válasz = Boolean.valueOf(true);
-
boolean érték = válasz.booleanValue();
A Byte, a Short, az Integer, a Long, a Float és a Double osztály
Ezen osztályok mind a Number osztályból származnak, amely a számokat kezelő osztályok őse. A Number őstől örökölt kényszer szerint van hat metódusuk, amely a burkoló osztály által hordozott szám primitív típusát adja vissza:
view plaincopy to clipboardprint?
-
Double szám = new Double(3.141592653589793);
-
System.out.println(szám.doubleValue());
-
System.out.println(szám.floatValue());
-
System.out.println(szám.longValue());
-
System.out.println(szám.intValue());
-
System.out.println(szám.shortValue());
-
System.out.println(szám.byteValue());
-
-
szám = Double.parseDouble("2.718281828459045");
-
System.out.println(szám.doubleValue());
-
System.out.println(szám.floatValue());
-
System.out.println(szám.longValue());
-
System.out.println(szám.intValue());
-
System.out.println(szám.shortValue());
-
System.out.println(szám.byteValue());
A fenti programrészlet eredménye:
view plaincopy to clipboardprint?
-
3.141592653589793
-
3.1415927
-
3
-
3
-
3
-
3
-
2.718281828459045
-
2.7182817
-
2
-
2
-
2
-
2
Mint látható, a valós számot hordozó Double esetén az egész számra való alakítás is megtörténik, ha egész típusú primitív típust kérek el, azonban az átalakítás során csonkolás történik (eltűnik a tizedespont mögötti számsor), nem pedig kerekítés!
Ezek az osztályok már több műveletet is lehetővé tesznek, nekünk azonban egyelőre elég a valueOf ismerete, amely szöveges formából alakít számmá, akárcsak a Boolean esetén:
view plaincopy to clipboardprint?
-
szám = Double.valueOf("-2");
-
System.out.println(szám);
-
szám = Double.valueOf("-2.2E3");
-
System.out.println(szám);
-
szám = Double.valueOf("-2.2E3000");
-
System.out.println(szám);
-
System.out.println(szám.isInfinite());
Ennek eredménye:
view plaincopy to clipboardprint?
-
-2.0
-
-2200.0
-
-Infinity
-
true
Fontos, hogy a valós típusoknak lehet negatív és pozitív végtelen értéke - ha túl nagy számot szeretnénk szöveges formából átalakítani vagy a művelet eredménye túl nagy, ezt lekérdezhetjük az isInfinite metódussal.
A Character osztály
A karakter ismét kilóg a sorból, hiszen a célja alapvetően nem a számolás, hanem karakterek ábrázolása.
view plaincopy to clipboardprint?
-
Character karakter = new Character(’a’);
-
System.out.println(karakter);
-
System.out.println(Character.isDigit(’0’));
-
System.out.println(Character.isDigit(’a’));
-
System.out.println(Character.isWhitespace(’\t’));
-
System.out.println(Character.isWhitespace(’a’));
-
System.out.println(Character.isISOControl(’\t’));
-
System.out.println(Character.isISOControl(’a’));
-
System.out.println(Character.toLowerCase(’A’));
-
System.out.println(Character.toUpperCase(’a’));
A futás eredménye:
view plaincopy to clipboardprint?
-
a
-
true
-
false
-
true
-
false
-
true
-
false
-
a
-
A
A Character osztálynak van egy rakás statikus metódusa, amely a megadott karakterről döntést hoz. A példában rákérdeztünk párosával arra, hogy az átadott karakter szám-e, helykitöltő karakter-e, valamit ISO vezérlőkarakter-e. Az utolsó két metódus pedig konvertálta az átadott karaktert kis-, illetve nagybetűsre. Ezen túl sok egyéb metódust megtalálunk a Character osztályban (írásirány, tükörírás, stb.), ezeket nem részletezném.
Közös konstansok
A Boolean osztályt leszámítva az összes burkoló osztálynak van négy hasznos konstansa:
-
TYPE, amely a primitív típust adja vissza
-
SIZE, amely a primitív típus által elfoglalt bitek számát adja vissza
-
MAX_VALUE, amely a legnagyobb ábrázolható értéket hordozza
-
MIN_VALUE, amely a legkisebb ábrázolható értéket hordozza, lebegőpontos típus esetén a legkisebb ábrázolható pozitív számot
Lássunk rá példát:
view plaincopy to clipboardprint?
-
System.out.println(Byte.TYPE);
-
System.out.println(Byte.MAX_VALUE);
-
System.out.println(Byte.MIN_VALUE);
-
System.out.println(Byte.SIZE);
-
-
System.out.println(Short.TYPE);
-
System.out.println(Short.MAX_VALUE);
-
System.out.println(Short.MIN_VALUE);
-
System.out.println(Short.SIZE);
-
-
System.out.println(Integer.TYPE);
-
System.out.println(Integer.MAX_VALUE);
-
System.out.println(Integer.MIN_VALUE);
-
System.out.println(Integer.SIZE);
-
-
System.out.println(Long.TYPE);
-
System.out.println(Long.MAX_VALUE);
-
System.out.println(Long.MIN_VALUE);
-
System.out.println(Long.SIZE);
-
-
System.out.println(Float.TYPE);
-
System.out.println(Float.MAX_VALUE);
-
System.out.println(Float.MIN_VALUE);
-
System.out.println(Float.SIZE);
-
-
System.out.println(Double.TYPE);
-
System.out.println(Double.MAX_VALUE);
-
System.out.println(Double.MIN_VALUE);
-
System.out.println(Double.SIZE);
-
-
System.out.println(Character.TYPE);
-
System.out.println(Character.MAX_VALUE);
-
System.out.println(Character.MIN_VALUE);
-
System.out.println(Character.SIZE);
Az eredményt mindenki nézze meg a saját gépén... :)
|
| |