Elméleti alapozás
Java-nyelv (egyszerű) adattípusai
Karakter
A számítógépben nemcsak számokra van szükségünk, hanem egyéb szimbólumokra, például betűkre vagy vezérlőkarakterekre is (gondoljunk csak az összeadás jelére: ’+’). Az összes ilyen jellegű adat az úgynevezett Unicode-kódtáblába van rendezve (az alábbi kép csak részlet)...
Forrás - Source: unicode-table.com
...amely a világ (majdnem) összes nyelvének (majdnem) minden karakterét és rengeteg egyéb karaktert is tartalmaz.
Eredeti mérete (1991. október) 216 = 65536 byte volt, amelyet tárolási szempontból 5 évvel később közel kétszeresére bővítettek. Ma már (2018) több mint 1 millió karakter tárolására alkalmas. Elődjeivel az ASCII-, és ISO-Latin-1, valamint az EBCDIC-kódtáblával éppen emiatt voltak gondok, hiszen a kommunikációs technológia fejlődésével egyre több, sokszor nemzeti karakterre volt szükség, amelyet terjedelmük miatt (28 = 256) nem tudott teljesíteni, illetve sok karakter egyszerűen nem fért el a billentyűzeten sem.
Az Unikód-táblából szabványosított módon bármit be tudunk inzertálni egy Java-programba, ehhez ismernünk kell a karakter azonosítóját, például nézzük meg a PI (egyébiránt hexadecimálisan kódolt) kódját:
\u03C0
public class Main {
public static void main(String[] args) {
System.out.println("\u03C0");
}
}
Végeredmény:
PI karakter
Nem ide tartozik, de itt jegyezzük meg, hogy a Java-fordító String típusú bemeneti adatként értelmezi a Unikód-hivatkozást, amint azt az alábbi futtatható Java-kódban is észrevehetjük:
public class Main {
public static void main(String[] args) {
System.out.println("\u03C0");
}
}
Végeredmény:
PI karakter
A Java-programban megkülönböztetjük a kis-, és a nagybetűket!
Néha szükségünk lehet az éppen használt kódtábla átállítására is. Ezen igényünket általában valamilyen karakterkiírási hiba előzi meg. Az Eclipse fejlesztési környezeten belül ezt projektszinten tehetjük meg...
Projektnév + jobb egérgomb → Run configurations → Common → Encoding (other)
...amely parancsok kiadása után többféle kódtáblából válogathatunk.
Megjegyzem továbbá, hogy a karakterek tárolása a számítógépben szintén bináris számokkal történik, sőt ezeken matematikai műveletek is végezhetők, ám ennek alapértelmezésben nincs sok értelme, hiszen a bináris kódok nem numerikus, hanem a karaktert szimbolizáló bemeneti adatok (azaz nincs értelme ’a’ és ’b’ karakterkódjait például matematikailag összeadni). Ettől függetlenül főként adatrendszerezés végett a kódtábla minden egyes karaktere tízes (Dec) és tizenhatos (Hex) számformátummal is rendelkezésre áll.
Kódtábla-részlet
Most nézzünk egy futtatható Java-kódot a karakter-adattípus deklarációjára!
public class Main {
public static void main(String[] args) {
char character = 'J';
System.out.println(character);
}
}
Végeredmény:
J
public class Main {
public static void main(String[] args) {
char characterJ = 'J';
char characterA = 'a';
char characterV = 'v';
System.out.print("The best is " + characterJ + characterA +
characterV + characterA);
}
}
Végeredmény:
The best is Java
Vigyázzunk arra, hogy –ellentétben a String adattípussal-, a karakter-deklaráció NEM kettős (”X”), hanem csak egyes (’X’) aposztróffal történik!
Továbbá a megértést súlyosbítja azon tény, miszerint a Javában a karakterek értékeit (pozitív) integer számokkal is megadhatjuk (a Numerikus egész című fejezet):
public class Main {
public static void main(String[] args) {
char character = 120;
System.out.println(character);
}
}
Végeredmény:
x
Ám a velük végrehajtott műveletek (korlátozottan) már matematikailag értelmezettek. Alább 2 db character változó összeadása és kivonása már integer végeredményt fog szolgáltatni:
public class Main {
public static void main(String[] args) {
char character = 120;
System.out.println(character + character);
}
}
Végeredmény:
240
public class Main {
public static void main(String[] args) {
char character = 120;
System.out.println(character - character);
}
}
Végeredmény:
0
Sőt, még a zárójelezés is működik (Operátor-precedencia /kiértékelési sorrend/ című fejezet):
public class Main {
public static void main(String[] args) {
char character = 120;
System.out.println((character * character) / character);
}
}
Végeredmény:
120
Nézzük meg a műveletet 2 változóval is. A változók elnevezésében a Ladó-féle utónévkönyv alapján az általános névadási konvenciókat követem (Az adatok, metódusok elnevezésének problémái című fejezet), azaz char character1 = 1; helyett char egy = 1 elnevezést alkalmazok:
public class Main {
public static void main(String[] args) {
char egy = 1;
char ot = 5;
System.out.println(ot - egy);
}
}
Végeredmény:
4
Egyik tanítványom felvetette, hogy ha karaktertípus (implicit módon, azaz már maga a Java-rendszer által is) ilyen könnyen átkonvertálható integer típusba, akkor működik-e ez visszafelé?
A válasz nem 100%-os biztonsággal igen, a kasztolás (casting) műveletének segítségével (Típuskonverzió avagy casting nemcsak Hollywoodban című fejezet). Ennek során megpróbáljuk az új típust mintegy "ráerőltetni" a régi típusra. Ez néha sikerül, néha nem, attól függően, hogy a típuskonverzió mennyire logikus a rendszer számára, bár ha jobban belegondolunk, ebben az esetben sem egészen az.
Mindenesetre most működik a művelet (az int x = 120 változó kasztolása (char)x), de csakis azért, mert a karakterek számkódolása a fontos funkcionalitással rendelkező kódtáblához köthető:
public class Main {
public static void main(String[] args) {
char character = 120;
System.out.println(character);
int x = 120;
System.out.println((char)x);
}
}
Végeredmény:
x
x
Azonban vegyük észre a következőt: más ügy a karakter ASCII-kódjának elérése, valamint magának a számnak karakterré való átalakítása. Az utóbbira nézzünk meg egy konkrét példát:
public class Main {
public static void main(String[] args) {
int szam = 9;
char karakter = Integer.toString(szam).charAt(0);
System.out.println(karakter);
}
}
Végeredmény:
9
A karakter más adattípusú értelmezése tovább folytatható. Az alábbi futtatható Java-kódban egy relációs operátor segítségével összehasonlítjuk a (valójában matematikai) értékeket. 5 természetesen nagyobb 1-nél (5 > 1), ezért a System.out.println() függvény false értéket ad:
public class Main {
public static void main(String[] args) {
char egy = 1;
char ot = 5;
System.out.println(ot < egy);
}
}
Végeredmény:
false
Érdekes futtatható Java-kód! - Karakterek bemeneti, számok kimeneti adatokként
Ez a belső, valójában össze nem illő konvertálhatóság igencsak megnehezíti a rendszerrel való korrekt munkát, sőt a kasztolás (típuskényszerítés) eszközével további átjárási utak nyithatók az elvileg össze nem tartozó adattípusok között; bizony ez sem fogja megkönnyíteni a rendszer átlátását. A megoldás tehát csak az lehet, hogy a különböző adattípusokat szigorúan, programozás-technikailag jól szervezetten és nagy figyelemmel használjuk fel és ahol lehet, csakis saját hatáskörükben.
A programkód futtathatósága szempontjából nincs jelentősége a szóköz ( ) karakternek. A kód olvashatósága végett tehát érdemes azt bőségesen használni, azaz a kódot sok-sok szóközzel, levegősen szerkeszteni.
További, a programkód hibátlan működése szempontjából kulcsfontosságú szimbólumok a szeparátorok. Voltaképpen ezek szintén karakterek, csak nem karakterváltozóként használjuk fel őket, hanem natívan, a Java-nyelvbe mélyen beépítve a forráskódot tagolják és a kód alkotóelemeit választják el egymástól. Ezek a következők:
-
. , ;
-
() [] {}
Pontos felhasználásukat itt most nem részletezem, a hozzájuk kapcsolódó szintaktikai szabályokat később ismertetem (illetve a Java-kódok folyamatos olvasásával-írásával a szabályok előbb-utóbb úgyis ránk fognak ragadni), de jelzem, hogy az Eclipse platform rendkívül magas szinten képes az ilyen jellegű hibákat detektálni és megfelelő megoldási javaslatokat tenni.
Zárásképpen nézzünk egy érdekes, futtatható Java-kódot, amely előregyártott-beépített, karakteres függvényeket használ fel a Character osztályból (ezzel kapcsolatban bővebbet A csomagoló osztályok (wrapper classes) című fejezetben olvashatunk)!
public class Main {
public static void main(String[] args) {
char karakter = 'R';
System.out.println(Character.isUpperCase(karakter));
System.out.println(Character.isLowerCase(karakter));
System.out.println(Character.toUpperCase(karakter));
System.out.println(Character.toLowerCase(karakter));
System.out.println(Character.isDigit(karakter));
System.out.println(Character.isLetter(karakter));
System.out.println(Character.isLetterOrDigit(karakter));
System.out.println(Character.class);
}
}
Végeredmény:
true
false
R
r
false
true
true
class java.lang:character
isUpperCase
boolean típusú metódus, megvizsgálja, hogy a karakter nagybetűs-e
isLowerCase
boolean típusú metódus, megvizsgálja, hogy a karakter kisbetűs-e
toUpperCase
char típusú metódus, a karaktert nagybetűssé alakítja
toLowerCase
char típusú metódus, a karaktert kisbetűssé alakítja
isDigit
boolean típusú metódus, megvizsgálja, hogy a karakter szám-e
isLetter
boolean típusú metódus, megvizsgálja, hogy a karakter betű-e
isLetterOrDigit
boolean típusú metódus, megvizsgálja, hogy a karakter szám-e vagy betű-e
class
A fenti metódusok ősosztálya
Érdekes futtatható Java-kód! - Formai különbségek kezdő és haladó kód között