A Java-át James Gosling, Patrick Naughton, Chris Warth, Ed Frank, és Mike Sheridan hozta létre a Sun Microsystems, Inc. cégnél 1991-ben. 18 hónap telt el az első verzió megjelenéséig. Ennek az első nyelvnek a neve Oak volt, később 1995-ben lett átnevezve Java-ra. 2009-ben a Sun Microsystems-t felvásárolta az Oracle, így a Java rendszert ők viszik tovább.
Java-át úgy tervezték, hogy az így megírt programok minden operációs rendszeren fussanak minden változtatás nélkül. Ez úgy lehetséges, hogy a Java program nem az operációs rendszeren fut natív módon, azt egy Java környezetben futtatjuk.
A Java nyelven írt programokat java fordítóval fordítjuk le, és Java futtató környezettel futtatjuk. Ez utóbbi azt jelenti, hogy egy operációs rendszeren önállóan futni nem képes. A futtató környezet általánosan keretrendszernek is hívjuk, de az Oracle keretrendszerét Java Runtime Environment néven használjuk, röviden JRE. A fejlesztői környezet pedig a JDK, azaz a Java Development Kit. A fejlesztői környezet tartalmazza többek között a java fordítót, amely parancs a „javac”.
A Java nyelv szigorúan osztályok halmaza, kis és nagybetű érzékeny, minden utasítást pontosvesszővel zárunk.
A Java nyelven írt programokból bájtkódot szokás létrehozni.
Java forráskód | Java fordító | Java bájtkód | Java futtató | Gépi kód |
---|---|---|---|---|
Program.java | javac | Program.class | java | 1 és 0 sorozata |
Azonban vannak fordítók, amelyek gépi kód létrehozására is alkalmasak.
Java forráskód | Java fordító | Gépi kód |
---|---|---|
Program.java | javac | Program.exe |
A bájtkód futtatását a Java keretrendszer, vagy futtató környezet, angolosan Java Runtime Environment, röviden JRE biztosítja.
Java bájtkód |
---|
Java keretrendszer |
Operációs rendszer |
Hardver |
Készítse el a következő forráskódot a megadott néven, majd mentse, fordítsa és futtassa:
class Test { public static void main(String[] args) { System.out.println("Java működik a gépeden"); } }
Fordítás:
javac test.java
Futtatás:
java test
Előfordul, hogy a futtató keretrendszer nem találja a keretrendszer osztályait. Ekkor a következő kapcsoló megadása szükséges:
java -cp . test
A programban megfigyelhetjük, hogy az összetartozó részeket, továbbiakban blokkokat kapcsos zárójelek határolják:
{ ez a blokk }
{ egyik sor másik sor }
A példa alapján azt is észrevehetjük, hogy a blokkok egymásba ágyazhatók, és minden blokknak van egy fejrésze. A blokk fejrészében írjuk le mire is való az adott blokk. A Javaban mindig osztályokkal dolgozunk, angolul class. Osztályokba szervezzük a megvalósítandó programjainkat. Ennek valamilyen nevet kell adni. Fenti példánkban a név „test”. Ennek a névnek meg kell egyeznie az állomány nevével. Ez lesz a kiindulási osztályunk, a program végrehajtása ebben az osztályban kezdődik majd.
A Javaban az egyes tevékenységeket függvényekben valósítjuk meg és szokásos módon metódusnak nevezzük. Minden Java program kell tartalmazzon egy „main” nevű metódust. A programnak ez lesz kiindulási pontja, innen indul, amit úgy mondunk: a program „belépési pontja”. A main metódust a kiinduló osztályunkban hozzuk létre. A neve előtt és után egy pár dolgot meg kell adnunk. A main előtt módosítókat adunk meg. A main kötelező módosítói a public és static. A public biztosítja, hogy a program indításakor a main metódus elérhető legyen az operációs rendszerből. A static módosító biztosítja, hogy a main metódust a nélkül is elérhessük, hogy példányosítanánk a test osztályt (Később látni fogjuk, hogy az osztályokkal sokszor úgy dolgozunk, hogy létrehozunk belőle egy példányt). A void egy speciális típus, azt jelenti nincs típus. Esetünkben ezzel azt mondjuk, hogy a program visszatérési értékkel nem rendelkezik a futtató környezet felé.
A main név után zárójelekben adjuk meg a program bemenő paramétereinek leírását. Ez „String[] args” A bemenő paraméterek leírását akkor is meg kell adnunk ha nem használjuk őket. Fordításkor nem is de futtatáskor hibát kapunk, ha hiányzik. A példában azt látjuk, hogy egy String típusú tömbben amelynek neve „args” tároljuk el a bemenő paramétereket. A String típusról és a tömbökről később lesz szó.
A példában szereplő forrást a javac paranccsal fordítjuk. Alap esetben persze ez nem áll rendelkezésére. Telepítenünk kell a Java SDK valamely verzióját. A telepített SDK könyvtárában lesz egy „bin” nevű könyvtár, ezt útvonalba tesszük. Itt található a javac fordító is.
A java futtató parancs általában működni szokott, ha böngészőnk miatt már telepítettünk egy Java JRE csomagot.
A Java nyelvben osztályokkal dolgozunk. Mivel sok osztály létezik szükséges azok csoportosítása. Az összetartozó osztályokat csomagokban tároljuk. Egy csomag a háttértárolón egy könyvtárnak felel meg.
A System osztály a java.lang csomagból (wrapper) való. Ha egy osztályt a Java nyelvben használni szeretnénk, akkor importálni kell azt a csomagot, amely azt tartalmazza. A java.lang egy olyan alaposztály, amelyet a Javaban nem kötelező importálni, ez biztosítja a Java program alapszerkezetét.
class Prog01 { public static void main(String[]) { System.println("Valami"); } }
class Prog01 { public static void min(String[] args) { System.out.pritln("Valami"); } }
public Prog01 { public static void main(String[] arg) { System.out.println"Valami"); } }
class Prog01 { public static oid Main(String[] args) { System.out.println("Valami"); } }
class Prog01 { Public static void main(String[] args) System.out.println("Valami"); } }
A Java nyelvben egy és kétsoros megjegyzések használhatók.
Az egysoros megjegyzést a kettőd darab perjel valósítja meg:
// egy soros megjegyzés
Több soros megjegyzést a /* és */ karakterek közzé írhatunk:
/* ez
egy
több
soros
megjegyzés */
A kivitel alapesetben azt jelenti írok a képernyőre. Ezt megtehetjük a következő két metódussal a System osztályból:
A következőkben összehasonlítjuk a két metódust, megnézzük a különbségeket.
Írjunk programot, amely az „Első” és a „Második” szavakat írja a képernyőre. Használjunk println() metódust:
System.out.println("Első"); System.out.println("Második");
Most írassuk ki a két szót print() metódussal.
System.out.print("Első"); System.out.print("Második");
Nemcsak karaktersorozatokat írathatunk ki, lehet számok és más karakterek is:
System.out.println("ElsőMásodik");
System.out.println("1234");
System.out.println("@!+=");
Ha számokat szeretnénk kiíratni, akkor azokat nem kötelező idézőjelek közzé tenni:
System.out.println(1234);
Ha a számokat idézőjelek nélkül adjuk meg paraméterként, akkor számításokat is végezhetünk vele.
A következő példában beszorozzuk az 1234-es értéket 2-vel.
System.out.println(1234 * 2);
Esetleg összeadásokat végezhetünk vele:
System.out.println(3 + 2);
A kimenet:
5
Ügyeljünk arra, hogy ha az előbbi kifejezést idézőjelbe tesszük, akkor nem az összeadás eredménye íródik ki, hanem a kifejezés karakterről karakterre:
System.out.println("3 + 2");
Kimenet:
3 + 2
Statikus import:
import static java.lang.System.*; class Program01 { public static void main(String[] args) { out.println("Hi"); } }
A különleges karakterek másként escape szekvenciák.
Néhány karakternek speciális értelmezése is lehet. Ha így akarjuk használni, akkor ezt valahogy jelezni kell. Ilyen speciális értelmezés lehet, amikor egy sortörést akarunk kiíratni. Ezt az „n” karakterrel tehetjük meg, ha a speciális jelentését használjuk. A speciális jelentést egy visszaperjellel (\) jelezzük:
\n
Ilyen speciális kérés lehet egy tabulátorjel kiíratása. A tabulátorjelet a „t” karakter jelképezi. A használatához itt is a visszaperjelet tesszük elé:
\t
Az ilyen karaktereket Escape szekvenciának hívjuk.
Gyakorlásként írjuk a képernyőre a „Helló Világ” nevű programot a következő formában:
class Program { public static void main(String[] args) { System.out.println("Helló\nVilág"); } }
A példafeladatban a (\n) escape szekvenciát használjuk.
class Program { public static void main(String[] args) { System.out.println("Helló\tVilág"); } }
Vannak olyan karakterek is, amelyeknek a Java nyelven eleve speciális jelentésük van. Ilyen az idézőjel („), amely egy szöveg elejét és végét jelzi. Ha egy karaktersorozatban szeretnénk kiíratni, nehézségekbe ütközünk. Ehhez is tartozik persze escape szekvencia:
\"
class Program { public static void main(String[] args) { System.out.println("Helló\"Világ"); } }
Az escape szekvenciák tehát egy-egy betű, amelyet ha alkalmazunk visszaperjellel vezetjük be. Alkalmazhatjuk őket karakterek helyén is.
char sortores = '\n';
A Java nyelv Escape karakterei az alábbi táblázatban láthatók.
Escape szekvencia | Leírás |
---|---|
\uxxxx | Hexadecimális UNICODE karakter (xxxx) |
\' | Felső vessző |
\” | Idézőjel |
\\ | Visszaperjel |
\r | Kocsi vissza (A kiírás a sor elején folytatódik) |
\n | Új sor |
\f | Lapdobás |
\t | Tabulátor |
\b | Visszatörlés (Előtte lévő karaktert törli) |
Escape szekvenciával megadhatunk Unicode karakter is ha tudjuk annak kódját.
Az alábbi táblázatban a Copyright és negáció jelek unicode-ját látjuk.
Karakter | Kód |
---|---|
© | 00a9 |
¬ | 00ac |
A példa kedvéért így íratjuk kia copyright karaktert:
System.out.println("\u00a9");
Még több unicode karakter: http://www.unicode.org/charts/PDF/U0080.pdf
Karakter típusú változók létrehozása és értékadás így a következő módon néz ki:
char ch; char idezojel; ch = 'a'; idezojel = '\"';
W7 alatt fok:
\u0159
A memóriában adatokat tárolunk, amelyek lehetnek egész számok, valós számok, karakterek, esetleg karaktersorozatok. Az ilyen memóriahelyeket a programozás során mint változókat emlegetjük. A változókat használatuk előtt deklarálni kell. Ez azt jelenti, meg kell mondanunk milyen típusú adatot szeretnénk tárolni az adott memória helyen. Ez azért fontos, mert a rendszer így tudja mekkora helyet kell az adatnak lefoglalni. Az alábbiakban megnézzük hogyan foglalhatunk helyet egész, valós, karakteres, stb., típusok számára.
Példa egy változó deklarációra:
int szam;
A különböző primitív adattípusok számára a memóriában helyet foglalunk, használat előtt. Azonban nem mindegy mekkora helyet kell lefoglalni. Más méretet foglalunk le egy egész típusú számnak vagy más méretet egy valóst típusú számnak.
A memóriában lefoglalt helyre értéket helyezhetünk el a következő utasítással:
szam = 35;
A „szam” nevű memóriahelyre 35 értéket tettük. Akármekkora számot nem tehetünk a memóriahelyre. Ha deklaráláskor az „int” kulcsszót tettük a deklarációba, akkor a legnagyobb beírható szám: 2147483647. A legkisebb: -2147483648.
Az int helyett megadható még egy pár típus. A következő táblázatokban azt látjuk, melyik mekkora helyet foglalhat a memóriában és így mekkora számot tárolhatunk benne, maximum és minimum értékekkel.
byte | 1 byte | -128 – 127 |
short | 2 bytes | -32 768 – 32 767 |
int | 4 bytes | -2 147 483 648 – 2 147 483 647 |
long | 8 bytes | -9 223 372 036 854 775 808 – 9 223 372 036 854 775 807 |
Ha nagyobb értéket akarunk elhelyezni egy változóban, mint amire névlegesen megengedett:
short a = 32768;
Fordításkor a következő hibaüzenetet kapjuk:
javac -cp Program.java Program.java:6: possible loss of precision found : int required: short short a = 32768; ^ 1 error >Exit code: 1
Az int típus esetén:
integer number too large: 2147483648 int c = 2147483648; ^
Valós típusok tárolására a float és a double típusok használhatók. Tartományuk az alábbi táblázatban látható:
double | 8 bytes | 4.9e-324 – 1.7976931348623157e+308 |
float | 4 bytes | 1.4e-45 – 3.4028235e+38 |
A float egyszeres pontosságú számokat képres tárolni, míg a double dupla pontosságú számokat képes tárolni.
A valós típusok használata:
double a = 3.4d;
double a = 3.4f;
A double esetén elhagyható a szám végéről a „d” betűt:
double a = 3.4;
char | 2 byte |
A karaktereket a char segítségével definiálhatunk, amely egy darab karaktert szimbolizál, ami lehet egy betű, egy szám vagy valamilyen írásjel.
Például:
a
vagy
b
vagy
@
Az „a”, „b” és „et” jel karaktereket jelentik.
Ha meg akarok adni egy karaktert a Java nyelvben azt mindig aposztrófok között adjuk meg. Például:
'a'
vagy:
'b'
vagy:
'@'
Ezek után egy változót a következő módon tárolunk változóban:
char ch; ch = 'a';
Gyakorlásként írjunk egy programot, amely egy-egy változóban eltárolja a következő betűket: „a”, „l”, „m”, „a”. Majd írassuk a képernyőre egy sorba:
A logikai változóknak két értéke lehet true és false. Deklarálásra a következő szót használom: boolean
boolean | 1 byte |
Használata például:
boolean van; van = true;
A szelekciós vagy iterációs kifejezésekben hasznunkra lehetnek, lásd később a szelekciónál.
float a = 3.87;
Ebben a formában hibaüzenetet ad, mi szerint elveszítjük a pontosságot. Ezért egy „f” betűt kell a végére tenni.
float a = 3.87f;
A Java nyelvben nem minden objektum. Az adattípusok egy ilyen speciális csoportot alkotnak. Ezeket primitív típusoknak is szoktuk nevezni.
Primitív típus | Érték | Csomagoló osztály | Tartomány |
---|---|---|---|
boolean | true, false | Boolean | true vagy false |
char | 16 bit-es Unicode | Character | \u0000 – \uFFFF |
byte | 8 bit-es előjeles egész | Byte | -128 – 127 |
short | 16 bit-es előjeles egész | Short | -32768 – 32767 |
int | 32 bit-es előjeles egész | Integer | -2147483648 – 2147483647 |
long | 64 bit-es előjeles egész | Long | -9223372036854775808 – 9223372036854775807 |
float | 32 bit-es lebegőpontos | Float | 1.4E-45 – 3.4028235E+38 |
double | 64 bit-es lebegőpontos | Double | 439E-324 – 1.7976931348623157E+308 |
A Java nyelvben minden típus előjeles (signed), azaz nincs előjel nélküli (unsigned) típus.
A primitív típusok rendelkeznek egy nekik megfelelő csomagolóosztállyal (vagy burkoló osztály).
A következő program true értéket ír a képernyőre, mivel a két változó értéke egyenlő:
double a = 3.0; double b = 3.0; System.out.println(a == b);
Ha burkoló osztállyal hozom létre a változókat, az egyenlőség nem igaz:
Double a = 3.0; Double b = 3.0; System.out.println(a == b);
Az egyenlőség nem igaz, mert osztályok között az „==” operátor a két osztály hivatkozását hasonítja össze, nem az tartalmát.
Burkoló osztály esetén használjuk az osztály equals() metódusát:
Double a = 3.0; Double b = 3.0; System.out.println(a.equals(b));
Maximum értékek kiíratása:
System.out.println(Byte.MAX_VALUE); System.out.println(Short.MAX_VALUE); System.out.println(Integer.MAX_VALUE); System.out.println(Long.MAX_VALUE);
Minimum értékek kiíratása:
System.out.println(Byte.MIN_VALUE); System.out.println(Short.MIN_VALUE); System.out.println(Integer.MIN_VALUE); System.out.println(Long.MIN_VALUE);
Hány biten tároljuk az adott típust:
System.out.println(Byte.SIZE); System.out.println(Short.SIZE); System.out.println(Integer.SIZE); System.out.println(Long.SIZE);
A printf metódussal tizedestört formában is kiírhatók a lebegőpontos számok:
System.out.printf("%f\n\n", Double.MAX_VALUE);
Írjon programot, amelybe a fenti utasításokat helyettesíti be. Például:
class Program01 { public static void main(String[] argv) { System.out.println(Byte.MIN_VALUE); } }
A típusok konverziója szélesítéssel angolul: Automatic Type Promotion.
Ha van egy kisebb számokat tárolni képes változónk, annak értéke eltárolható egy nagyobb értékek tárolására képes változóban. Ezt nevezzük szélesítésnek.
Ha eltárolom például egy 35-öt egy byte típusú változóban:
byte a = 35;
Később átadhatom az értéket egy short, int, long, stb. típusú változónak:
byte a = 35; int b = a;
Ezt azért tehetem, mert „b” változóban nagyobb szám tárolható mint az „a” változóban. Ezt nevezzük szélesítésnek. Fordítva azonban már nem lehetséges.
Az alábbiakban az egyes típusokat látjuk milyen szélesítés alkalmazható rajtuk:
Lássuk újabb példával:
byte a = 3; short b = a;
A példában 3-s számot az „a” változóban tároljuk először, az után szélesítést alkalmazunk meg „a” értékét egy olyan változóban tároljuk el, amely már nagyobb számok tárolására is képes. Vagyis, egy byte típusú változót tartalmát egy short típusúban tárolhatom, ehhez semmiféle konverzióra nincs szükség.
A szűkítés már kényesebb dolog. Az értéket olyan változóban szeretném tárolni amely kisebb számok tárolására alkalmas mint az eredeti.
Példa:
short a = 3; byte b = (byte) a;
A példánkban a short nagyobb számok tárolására alkalmas, így nem írhatjuk le:
b = a;
Helyette típus kényszerítést használunk. A típuskényszerítés során zárójelbe tesszük annak a típusnak a nevét, amelybe szeretnénk átalakítani. Ha az egyenlőségjel baloldalán egy byte típus van, akkor zárójelbe azt írom „byte”. A típuskényszerítést „kasztolás” névvel is használjuk.
A kasztolás egyébként az angol casting szó magyarosan ejtése: casting [UK: ˈkɑːstɪŋ][US: ˈkæstɪŋ] esés, hajítás, horgászás, kimustrálás, öntés, öntvény, szereposztás, vetemedés, vetés. Eredeti formája: „type casting”. A C nyelvben terjedt el használata. Egy újabb példa a kasztingra:
double a = 3; int b = (int)a;
Az „a” változó értékét kasztoljuk int típussá.
A literális egy olyan állandó, aminek nincs neve. Literális például a „3”, az „a” betű, a „/” jel, bármi.
Amikor leírjuk, hogy
int a = 3;
a három az egy literális állandó. Állandó, mert a program további részében ezt az adatott nem tudom megváltoztatni, és literális mivel nincs neve. Nem egy névvel hivatkozok rá, hanem beírtam úgy ahogy van.
Literális a következő karakter, egyenlőség jel jobboldalán:
char ch = 'a';
Literális a következő is:
String s = "szilva";
Láthatjuk hogy a szám literálisokat csak úgy leírjuk, a karakterlitárálisokat felsővesszők közé tesszük, a karaktersorozat literálisokat pedig idézőjelek közé tesszük a Java nyelvben.
A Java-ban a legkisebb tárolási egység. A változókat használat előtt deklarálni kell.
double fizetes; double _fizetes; int fizetes; int $fizetes; long fizetes; boolean kesz;
Nem használható változónevek:
double 1salary; double %salary; int #holidays;
Egy változó nem kezdődhet számmal, nem kezdődhet százalékjellel, nem kezdődhet kettős-kereszttel.
A változók deklaráláskor értékét is definiálhatjuk:
double fizetes = 70000;
Eddig is használtunk állandókat, konkrétan literális állandókat. A következő állandók úgynevezett nevesített állandók. Azt vállaljuk, hogy a memóriaterületen elhelyezett értéket a program további részében nem fogjuk megváltoztatni. Ehhez a final kulcsszót fogjuk használni:
class Program01 { public static void main(String args[]) { final int a = 5; System.out.println(a); } }
A programunkban azt vállaljuk, hogy a program további részében az „a” nevű memóriahely tartalmát többet nem változtatjuk meg.
class Program01 { public static void main(String args[]) { final int ALAPFIZETES = 200000; System.out.println(ALAPFIZETES); } }
Az állandókat nagybetűvel szokás írni, hogy megkülönböztessük azokat a változóktól. Így a forráskódban azonnal felismerhető.
Értékadást egy darab (=) karater segítségével végzünk. A Java nyelvben előfordul két egyenlőségjel karakter is egymás után, annak azonban más jelentése van. Értékadáshoz csak egy darab karaktert használunk.
Az egyenlőségjel baloldalán álló változó felveszi a jobboldalon álló számállandó, változó vagy kifejezés értékét.
Float a = 3F;
vagy kisbetűvel:
Float a = 3f;
Primitív típus egész számmal:
float b = 3;
Valós számmal már szükséges az „f” vagy „F” jelző:
float b = 3.0f;
Double c = 3.;
double d = 3;
Használhatjuk a „d” vagy „D” jelzőt:
double d = 3.0d;
float a = b;
float a = (b + c) * 3;
A kifejezés operátorokat és operandusokat tartalmazó összeállítás. A példában a operandusok az egyenlőség jel jobb oldalán a „b”, a „c” és a „3”. Operátorok a záró és szorzójel.
Értékadás esetén kifejezés nem állhat az egyenlőségjel baloldalán. A következő utasítás teljesen hibás: (b + c) * 3 = a;
Nézzük meg a következő kifejezés hogyan lesz kiértékelve, mit ír a program a képernyőre:
double a = 1 / 2; System.out.println(a);
Az eredmény nulla, pedig 0.5 vártunk volna. Pedig egy double típusban tároljuk az eredményt. Mivel az értékadás jobboldalán csak egész számok szerepelnek az értékadás során a tört részek elvesznek.
Ha legalább egy számot valós típusúvá teszünk az eredmény 0.5 lesz.
double a = 1 / 2.0; System.out.println(a);
A 2-es értéket valóssá számmá változtattuk azzal, hogy után írtunk egy pontot (.) és egy nullát (0). A nulla a Java nyelvben elhagyható:
double a = 1 / 2.; System.out.println(a);
Használhatjuk a számok után a f vagy a d jelzőt:
double a = 1 / 2f; System.out.println(a); double b = 1 / 2d; System.out.println(b);
Formázott kivitel esetén, amikor számot vagy egyéb érték használok, az egyszerű képernyőre írás helyett, apróbb formai változtatásokat hajtok végre. Ilyen lehet, hogy a számot, mindenképpen 10 helyen ábrázolom. Az üres helyeken vezető nullákat írok ki. Vagy 3 tizedesjegy pontossággal ábrázolok egy számot. Esetleg mindig ábrázolom az előjelt.
Formázott kivitelt például a printf() metódussal lehetséges:
System.out.printf("formátumkód", változó_állandó_vagy_kifejezés);
Az első argumentum egy formátumszöveg (formátum-karaktersorozat) , amely tartalmaz egy formátumkódot. A második egy változó, egy állandó vagy egy kifejezés.
A formátumkód szintaxisa:
%[argumentum_index$][jelzők][szélesség][.pontosság]konverziós_karakter
A formátumkód mindig százalékjellel (%) kezdődik és egy formátumkarakterrel (konverziós karakter) végződik. A formátumkaraktereket lásd alább. A formátumkód előtt és után bármi állhat a karaktersorozatban.
Ha több argumentum is van, akkor megadhatjuk annak sorszámát, amelyet ki szeretnénk íratni. Az indexelés 1-gyel kezdődik.
Az alábbi példában nem használjuk az argumentumindexet:
System.out.printf("%d %d\n", 3, 4);
Így a képernyőre a következő íródik:
3 4
Az argumentumindext használva a megfordításhoz:
System.out.printf("%2$d %1$d\n", 3, 4);
A következő a kimenet:
4 3
Ehhez persze elég lett volna a két érték felcserélése, ezért a legkevésbé használt lehetőség.
A kiírás szélessége. Egy egész szám, például:
10
System.out.printf("%10d\n", 35);
A kiíratandó szám akárhány számjegyből áll, azt 10 helyen fogjuk ábrázolni, a a maradék hely szóközökkel lesz kitöltve. A tíz helyen a szám jobbra lesz igazítva.
A tizedes jegyek száma. Mindig egy ponttal (.) kezdődik. Például két tizedes jegy:
.2
Valós számok esetén megadhatjuk a tizedesjegyek számát:
System.out.printf("%.2f\n", 35.1234567);
Egyszerre megadható az szám ábrázolásának szélessége és a tizedesjegyek száma is:
System.out.printf("%10.2f\n", 35.1234567);
A könnyebb olvashatóság érdekében nagyobb számok esetén ezredenként elválasztót szoktunk használni a számoknál. Amerikai szokás szerint ez egy vessző (,), de nálunk a magyar nyelvben ezt szóközökkel oldjuk meg. A Java nyelvben egy vessző megadásával vehetjük rá a programunkat az ezredeselválasztó használatára:
System.out.printf("%,f\n", 32432344842.52334);
class Program { public static void main(String args[]) { int a = 45; int b = 27; System.out.printf("%d %d\n", a , b); } }
class Program { public static void main(String args[]) { int a = 5; int b = 4; int c = 3; System.out.printf("%d %d %d\n", a , b, c); } }
Az egymás után megadott „a”, „b”, stb. változók kiíratásának sorrendje megváltoztatható:
class Program { public static void main(String args[]) { int a = 45; int b = 27; System.out.printf("%d %d\n", a , b); System.out.printf("%2$d %1$d\n", a , b); } }
Egy dollár jel előtt megadjuk, melyik indexű változó kiíratására gondoltunk. Ezzel persze egy változó többször is kiíratható. A következő példában az „a” változó tartalmát kétszer is kiíratom.
class Program { public static void main(String args[]) { int a = 45; int b = 27; System.out.printf("%d %d\n", a , b); System.out.printf("%2$d %1$d %1$d\n", a , b); } }
A váltózók indexei 1-gyel kezdődnek.
+ | előjel |
- | balra igazítás (csak szélesség meghatározással, így van értelme) |
0 | vezető nullák megjelenítése |
, | ezredes tagolás |
# | alternatív formátum megjelenítése (csak o, x és X esetén) |
' ' | egy vezető szóköz pozitív számok számára (csak: 'd', 'o', 'x', és 'X' esetén) |
'(' | negatív számok zárójelbe kerülnek (csak: 'e', 'E', 'f', 'g', és 'G esetén) |
A jelzők sorrendje felcserélhetők. Az összes jelző alkalmazás lehetséges, de előfordul, hogy az egyik jelző használat értelmetlen a másik mellett.
Az ezredeselválasztó Linuxon gond nélkül működik, Windowson Unicode fontokat kell beállítani, másként nem működik.
A formátumkódot mindig egy konverziós karakter zárja . Az alábbi táblázatban láthatjuk a lehetséges formátumkódokat.
Konverziós karakter | Kategória | Leírás |
---|---|---|
'b', 'B' | elsődleges | Ha az argumentum null, akkor visszatérés „false”. Az argumentum boolden vagy Booldan, akkor a visszatérés String.valueOf(). Ellenkező esetben a vissztérés „false”. |
'h', 'H' | elsődleges | Ha az argumentum null, akkor a visszatérés is null. Egyébként a visszatérés Integer.toHexString(arg.hashCode(). |
's', 'S' | elsődleges | Ha az argumentum null, akkor a visszatérés is null. Ha az argumentum formázást valósít meg akkor a formázás érvényesül. Minden más esetben az argumentumon karaktersorozattá alakul toString() |
'c', 'C' | karakter | Visszatér egy Unicode karakterrel |
'd' | átalakító | Visszatér egy formázott decimális egésszel. |
'o' | átalakító | Visszatér egy formázott oktális egésszel. |
'x', 'X' | átalakító | Visszatér egy formázott hexadecimális egésszel. |
'e', 'E' | lebegőpontos | Visszatér egy formázott decimális számmal tudományos formában. |
'f' | lebegőpontos | Visszatér egy formázott decimális számmal. |
'g', 'G' | lebegőpontos | Visszatér egy formázott tudományos formával vagy decimális formával, a kerekítés utáni érték pontosságától függően. |
'a', 'A' | lebegőpontos | Visszatér egy formázott hexadecimális lebegőpontos számmal, alappal és a kitevővel. |
't', 'T' | idővel kapcsolatos | Dátum és konverziós karakterek előtagja. Lásd a dátum és idő konverziót. |
'%' | százalék | Visszaad egy '%' literálist '\u0025') |
'n' | sorelválasztó | Visszatér egy platformspecifikus sortöréssel. |
double a = 2,7183; System.out.printf("Szám: %+10.4f", a); // " Szám = +2,7183" System.out.format("Hatvany: %.2f\n", b);
Az óra, perc, másodperc kiíratása:
System.out.printf("%tT\n", java.util.Calendar.getInstance());
Az év kiíratása:
System.out.printf("%tY\n", java.util.Calendar.getInstance());
Az óra kiíratása:
System.out.printf("%tH\n", java.util.Calendar.getInstance());
import java.util.Calendar; class Program { public static void main(String args[]) { Calendar datum = Calendar.getInstance(); System.out.printf("%tH\n", datum); } }
Még több példa:
Calendar c = Calendar.getInstance(); // --> "May 29, 2006" System.out.format("%tB %te, %tY%n", c, c, c); // --> "2:34 am" System.out.format("%tl:%tM %tp%n", c, c, c); // --> "05/29/06" System.out.format("%tD%n", c);
Mint azt fentebb láttuk sortörést lehet kiíratni a println() metódussal, de az '\n' escapeszekvencia is használható erre a célra. Ugyanezt tehetjük meg a „%n” segítségével.
Az aktuális operációs rendszer sortörésének kiíratása:
System.out.format("%f%n%n", 455.3823);
import java.io.*; import java.util.*; class Forma { public static void main(String args[]) throws IOException { Formatter formazo = new Formatter(); formazo.format("%s %d %f", "Java", 10, 97.5); System.out.println(formazo); System.in.read(); } }
A Formatter osztály a java.util csomagban található.
import java.text.DecimalFormat; class Program { public static void main(String args[]) { DecimalFormat sajatForma = new DecimalFormat("###,###.###"); System.out.format(sajatForma.format(123456.789)); } }
import java.io.Console; class Program3 { public static void main(String args[]) { Console konzol = System.console(); konzol.printf("Helló Világ!\n"); } }
A Math osztály olyan metódusokat tartalmaz, amelyek megkönnyítik a matematikai feladataink megoldását. Ilyenek az abszolút érték számítása, gyökvonás, hatványozás, trigonometriai függvények számítása, stb.
A Math osztály importálás és példányosítás nélkül azonnal rendelkezésünkre áll. A következő példában -15 abszolút értékét számítjuk ki.
Egy szám abszolút értékét adja vissza.
Ha megnézzük a Java API dokumentációt ehhez hasonlókat láthatunk:
double abs(double a) float abs(float a) int abs(int a) long abs(long a)
Ebből tudhatjuk, hogy az abs metódusnak négy módon használhatjuk. Megadhatunk paraméterként double, float, int vagy long típust. Ha double adunk meg double típust ad vissza. Ezt az első sorból látjuk:
double abs(double a)
A „double a” mutatja, hogy milyen bemenő paraméter jöhet szóba, az elején a „double” pedig azt mutatja milyen értéket ad vissza a metódus.
double c = Math.sin(b * Math.PI / 180); double d = Math.sin(Math.toRadians(b)); System.out.printf("Szinusz : %.5f\n", c); System.out.printf("Szinusz : %.5f\n", d);
A trigonometriai függvények radiánban várják az értékeket. A bemenő paramétert ezért át kell konvertálni előbb radiánba.
Függvények |
---|
double sin(double a) |
double tan(double a) |
double cos(double a) |
double asin(double a) |
double acos(double a) |
double atan(double a) |
double atan2(double a) |
Az Euler-féle szám (jele: e) egy matematikai állandó, amit a természetes logaritmus alapja
System.out.println(Math.E);
Az E nem függvény! Tulajdonság!
A round a tizedes törtet kerekíti. .4-től lefele, .5-től felfele:
System.out.println(Math.round(1.5));
Eredménye: 2
System.out.println(Math.round(1.4));
Eredménye: 1
A ceil függvény a tizedes törtet felfelé kerekíti.
System.out.println(Math.ceil(1.0));
Eredménye: 1
System.out.println(Math.ceil(1.1));
Eredménye: 2
A floor függvény a tizedes törtet lefelé kerekíti.
double floor(double a)
Két példa:
System.out.println(Math.floor(1.1));
Eredménye: 1
System.out.println(Math.floor(1.9));
Eredménye: 1
Radiánfok átszámítása szögfokká.
Math.toDegrees(85);
Szögfok átszámítása radiánfokká.
Math.toRadians(85);
Az exponenciális függvény ex vagy exp(x), ahol e egy matematikai állandó, a természetes alapú logaritmus alapja, értéke körülbelül 2,718281828, és Euler-féle szám
double exp(double a)
A hatványozás egyik megfordított (inverz) művelete
double log(double a)
A log() a szám természetes logaritmusát adja. A matematikában ln(x) a jelölése.
double log10(double a)
A log10() a szám 10 alapú logaritmusát adja. A matematikában a lg(x) a jelölése.
double log1p(double x)
A log1p a szám és 1 összegének logaritmusát adja.
A véletlenszámok előállítására két osztály áll rendelkezésünkre. A Random és a Math.
Az eddig használt osztályok a java.lang csomagban voltak, amit nem kellett importálni. A Random osztály az eddigiektől eltérően importálni kell, a java.util csomagban található. Használni sem használhatjuk csak példányosítással. A példányosítás azt jelenti létrehozunk az osztályból egy példányt.
Az osztályok hasonlítanak például a „dolgozó” fogalomhoz. Ha azt mondom „dolgozó” az nem egy konkrét személy, konkrét ember, akár ki lehet. Ha azt mondom a Jóska nevű dolgozó akkor már konkretizáltam. A Jóska tulajdonképpen a dolgozó egy példánya. A Java nyelvben ehhez használjuk az osztályokat. Az osztály egy általános dolog. Ha példányosítom akkor, létrehoztam az adott osztály egy példányát. A létrehozott példányt objektumnak nevezzük. Az előbbi „dolgozó” analógiában az objektum a „Jóska példánynak” felel meg.
A Random osztályt példányosítani kell használat előtt, azt pedig a new utasítással tudjuk megtenni. Lássunk a példányosításra egy példát:
Random veletlen = new Random();
A példánkban kitaláltunk egy objektum nevet, ez a „veletlen”. A példányosítás utn a „veletlen” egy olyan objektum, amelyet a Random osztályból hoztunk létre a „new Random()” kifejezés segítségével.
A háttérben, tulajdonképpen a memóriában egy „veletlen” nevű objektumnak foglaltunk helyet a „new Random()” kifejezéssel.
A Random osztály importálása:
import java.util.Random;
A Random osztály példányosítása veletlen objektum létrehozásával:
Random veletlen = new Random();
A veletlen objektum használata:
int szam = veletlen.nextInt(3);
A Random osztály egyik metódusa a nextInt(). A nextInt() metódus egy véletlen számot generál, ha meghívjuk a veletlen objektumon. A példánkban a generált számot a „szam” nevű változóban tároljuk.
A nextInt() metódusnak paraméterként 3-at megadva 0 és 2 közötti értéket kaphatunk.
1 és 6 közötti szám előállítása ezek után:
Random veletlen = new Random(); int dobas = veletlen.nextInt(6) + 1;
A következő táblázatban a Random osztály további metódusait láthatjuk. A „veletlen” objektum helyett, azonban csak egy „r” nevű objektumot használunk a rövidség miatt.
Visszatérés típusa | Hívás | Leírás |
---|---|---|
int i = | r.nextInt(int n) | int >= 0 és < n közötti véletlen számot ad vissza |
int i = | r.nextInt() | a teljes int tartományból ad vissza véletlen számot |
long l = | r.nextLong() | a teljes long tartományból ad vissza véletlen számot |
float f = | r.nextFloat() | float >= 0.0 és < 1.0 közötti véletlen számot ad vissza |
double d = | r.nextDouble() | double >= 0.0 és < 1.0 közötti véletlen számot ad vissza |
boolean b = | r.nextBoolean() | true vagy false értékkel tér vissza véletlenszerűen |
double d = | r.nextGaussian() | 0.0 és szabályos eltéréssel 1.0 közötti véletlen eltéréssel tér vissza |
A Math.random() 0.0…0.999999 között állít elő egy számot.
double a = Math.random(); System.out.printf("%.20f\n", a);
A következő kimenetet adja:
0,509873801078128200000
Ha négyel szoroztam volna a számot:
double a = Math.random(); System.out.printf("%.20f\n", a * 4);
Kimenet például:
2,03949520431251270000
A szám egész része egy 0 és 3 közötti szám.
Ebből lehet egy egész véletlen számom.
Esetleg így is írhatjuk:
double a = 4 * Math.random(); System.out.println(a);
Ha mindig hozzáadunk 1-t, akkor 1 és 4 közötti számot kapunk:
double a = 4 * Math.random() + 1; System.out.println(a);
Példa 1 és 10 közötti egész szám előállítására:
szam = (int) (10 * Math.random()) + 1;
= | Egyszerű értékadás |
Az értékadást általánosan így írhatjuk le:
<változó> = <kifejezés>
Lássunk néhány konkrét példát a használatára:
int a, b; a = 2; // 2 értéket hozzárendeljük az a változóhoz b = 5; // 5 értéket hozzárendeljük a b változóhoz
Home home1 = new Home(); // új objektum készítése Home home2 = home1; // home1 referencia home2-be rendelése
+ | összeadás (karaktersorozatok összefűzésére is használjuk |
- | kivonás |
* | szorzás |
/ | osztás |
% | maradékképzés |
+ | Unary plusz operator; az értéket adja |
- | Unary mínusz operator; előjelet vált, vagyis az értéket negálja |
++ | inkrementáló operátor; az inkremens értéke: 1 |
-- | dekrementáló operátor; a dekremens értéke: 1 |
! | logikai ellentét; a logikai értéke ellentétes értékét adja |
A (+) egyoperandusú operátort a C nyelvben tették szabvánnyá először a (-) operátor ellentéteként csak a szimetria kedvéért. A (+) operátor használata így nem tesz semmit az értékkel, azt kapjuk ami van.
A (!) operátor az ellentétére fordít egy logikai értéket. A true értékből false értéket csinál és fordítva. Teszteljük a következő programmal:
System.out.println(true); System.out.println(!true); System.out.println(false); System.out.println(!false);
== | egyenlő |
!= | nem egyenlő |
> | nagyobb mint |
>= | nagyobb vagy egyenlő |
< | kisebb mint |
<= | kisebb vagy egyenlő |
Az egyenlő operátor visszaad egy true vagy false értéket, attól függően igaz-e amit állítunk.
int a = 4; System.out.println(a == 3);
A következő program ugyanígy true vagy false értéket ír ki, de most az ellentétére kérdezünk:
int a = 4; System.out.println(a != 3);
A többi logikai operátor is hasonlóan használható.
&& | feltételes ÉS |
|| | Feltételes VAGY |
?: | Hármas operátor (az if-then-else rövid változata) |
Az && operátor feltételes ÉS, amelyet két logikai állítás között szoktunk használni. A következő példában két állítást teszünk. Először azt állítjuk, hogy az „a” értéke 3, majd b értéke 4. Ha mindkettő igaz lenne, akkor kapnánk igaz értéket a teljes kifejezésben:
int a = 4; int b = 4; System.out.println(a == 3 && b == 4);
A példánkban false értéket kapunk, mert az a változóban nem 3-as érték szerepel.
instanceof | Egy objektumot egy megadott típushoz hasonlít |
~ | komplemensképzés bitenként (unary; egyoperandusú) |
<< | előjeles balra mozgatás (shift) |
>> | előjeles jobbra mozgatás (shift) |
>>> | előjel nélküli jobbra mozgatás (shift) |
& | bitenkénti ÉS |
| | bitenkénti VAGY |
^ | bitenkénti Kizáró VAGY |
Ha egy kifejezésben több operátor is van, akkor el kell dönteni, mi lesz az operátorok végrehajtásának sorrendje. Ezt nevezzük precedenciának. Az alábbiakban a Java nyelv precedencia táblázatát látjuk:
++ -- ! ~ instanceof | (pre- vagy poszt-) inkremens és dekremens, logikai és bitenkénti negálás, típus ellenőrzés |
* / % | szorzás, osztás, moduló |
+ - | összeadás, kivonás |
<< >> >>> | bitenkénti léptetések |
< > >= <= | összehasonlítások |
== != | egyenlő, nem egyenlő |
& | bitenkénti AND |
^ | bitenkénti XOR |
| | bitenkénti OR |
&& | logikai AND |
|| | logikai OR |
? : | feltételes kifejezés |
= += -= *= /= %= ^= &= |= <<= >>= >>>= | különböző értékadások |
A táblázatban legfelül látjuk azokat amelyek hamarabb végrehajtásra kerülnek. Mi történik akkor, ha azonos precedenciaszintű operátorokból van több? Ebben az esetben azok balról jobbra, sorba egymás után hajtódnak végre.
Lássunk egy példát:
int szam = 1 + 2 + 3; System.out.println(szam);
Az utasítások balról jobbra végrehajtódnak, de nekünk persze mindegy, mert az eredmény ugyanaz, ha először a második összeadás hajtódik végre.
A következő példában viszont nem mindegy melyik operátor hajtódik először végre:
int szam = 1 + 2 * 3; System.out.println(szam);
Ebben az esetben először a szorzás hajtódik végre, majd az összeadás.
A zárójelekkel azonban ezen változtathatunk:
int szam = (1 + 2) * 3; System.out.println(szam);
Először a zárójelen belüli összeadás kerül végrehajtásra, majd a szorzás.
Adott a következő Java programrészlet:
int a = 3; b = a++;
Jó kérdés lehet, hogy milyen érték kerül a b változóba. A kérdés úgy is feltehető, hogy az „++” operátor mikor növeli az „a” változó értékét? Mielőtt átadja az értékét „b” változónak, vagy csak utána. A helyes válasz csak utána. A b változóba tehát 3 kerül, utána növeli a ++ operátora az „a” változó tartalmát.
Ezzel ellentétes viselkedés is elérhető, ha az ++ operátort nem a változó utána, hanem az előtt szerepeltetjük:
int a = 3; b = ++a;
Ebben az esetben a „b” változó értéke 4 lesz, mivel az operátor előbb növelte „a” értékét, majd ez az érték került átadásra.
A „–” operátor használata megegyezik a „++” használatával, ebből a szempontból.
class Program02 { public static void main(String[] args) { int a = 3; int b = ~a; System.out.printf("%32s\n", Integer.toBinaryString(a)); System.out.printf("%32s\n", Integer.toBinaryString(b)); } }
//Előjeles balra mozgatás (baloldalon mindig az előjel bit jön be) class Program01 { public static void main(String[] args) { int a = 3; //Próbáljuk ki negatív értékkel int b = a << 2; System.out.printf("%4s\n", Integer.toBinaryString(a)); System.out.printf("%4s\n", Integer.toBinaryString(b)); } } //A baloldali első bit az előjel bit negatív számok esetén 1, pozitív esetén 0.
A feltételes operátor tulajdonképpen az if-then-else hasonlata. Van egy feltétel a kérdőjel előtt. Ha igaz, akkor az első értéket kapj az egyenlőség baloldalán álló „b” változó. Ne nem igaz, akkor a kettőspont utáni értéket kapja.
class Program { public static void main(String[] args) { int a = 8; String b = a > 5 ? "Nagyobb" : "Kisebb"; System.out.println(b); } }
class Program01 { public static void main(String[] args) { Integer a = 3; System.out.println(a instanceof Integer); } }
Primitív típussal nem működik a instanceof operátor!
A mellékletek részben találunk egy sokkal hasznosabb példát az operátor használatára. A jelen példának azért nincs sok értelme, mert az Integer helyett nem is tudunk mást írni.
Legyen egy „a” változó, amelynek értékét szeretnénk 2-vel növelni. Ekkor ezt írnánk:
int a = a + 2;
Ennek van egy rövidebb formája:
int a += 2;
A plusz jelet az egyenlőség jel elé tesszük, az „a” változóba pedig csak egyszer írom le.
Lehetséges kombinált értékadó operátorok:
+= -= *= /= %= &= ^= |= <<= >>=
Hármas operátor. Ennek az operátornak három operandusa van, ezért a neve.
Az operátor egy kérdőjelből és egy kettőspontból áll:
? :
Használatát lásd a szelekciónál.
System.out.println(Integer.parseInt("89"));
String s = "25"; int a = Integer.valueOf(s).intValue();
A valueOf() egyik prototípusa:
static Integer valueOf(String s)
Visszatér egy karaktersorozat számértékével egy Integer objektumban eltárolva.
Az intValue() metódussal primitív int típussá alakítjuk.
Az intValue()prototípusa:
int intValue()
String s = "87"; System.out.println(Integer.parseInt(s));
Szöveges formában tárolt valós számot alakítunk egésszé.
int a = Float.valueOf( "799.87" ).intValue();
System.out.println(Double.parseDouble("89.5"));
Double d = Double.valueOf(str).doubleValue();
Float f = Float.valueOf(str).floatValue();
int a = Integer.valueOf("B8DA3", 16).intValue();
int a = Integer.parseInt("B8DA3", 16);
A következő sor például a 11-et ír a képernyőre:
System.out.println(Integer.parseInt("B", 16));
char ch = 'A'; int b = ch; System.out.println(b); //Az eredmény: 97
vagy:
char ch = 'A'; int b = (int) ch; System.out.println(b); //Az eredmény: 97
int a = 97; char ch = (char)a; System.out.println(ch); //Az eredmény: a
String str = "ABCD"; for ( int i = 0; i < str.length(); ++i ) { char c = str.charAt(i); int j = (int) c; System.out.println(j); }
int a = 2; boolean b = (a != 0);
A nulla érték mindig hamis lesz. Az ettől eltérő pedig igaz.
boolean a = true; int b = a ? 1 : 0;
A true és a false a következő módon alakul át:
try { a = Integer.parseInt(str); } catch(NumberFormatException e) { }
String s = "some text here"; byte[] b = s.getBytes("UTF-8");
byte[] b = {(byte) 99, (byte)97, (byte)116}; String s = new String(b, "US-ASCII");
Az US-ASCII helyett lehet „UTF-8” is
Double a = 3.8; int b = Double.valueOf(a).intValue();
Float a = 3.8f; int b = Float.valueOf(a).intValue();
double a = 3.8; int b = (int) a;
import java.io.*; class Konvert { public static void main(String args[]) throws IOException { int i = 2; String bin = Integer.toBinaryString(i); System.out.println(bin); System.in.read(); } }
import java.io.*; class Konvert { public static void main(String args[]) throws IOException { int i = 11; String bin = Integer.toBinaryString(i); System.out.println(bin); String hexstr = Integer.toHexString(i); System.out.println(hexstr); System.in.read(); } }
A Java nyelven az olvasás a billentyűzetről nem egyszerű feladat. Van ugyan az in mezőnek egy read() metódusa, de az csak egyetlen bájtot olvas be. Ha ezzel kérnénk be egy számot, azt utána még át kellene konvertálnunk számmá. A System.in.read() metódust így legfeljebb arra használjuk, hogy várjunk egy „Enter” lenyomására.
Másik megoldás lehet a projekten jobb egér gomb „Run Maven” > Goals. Majd töltsük ki:
Megoldás lehet még, a java.io csomag osztályainak használata.
import java.util.Scanner; class Program01 { public static void main(String args[]) { Scanner bevitel = new Scanner(System.in); System.out.print("Egész szám: "); int a = bevitel.nextInt(); System.out.println(a); } }
import java.util.Scanner; class Program02 { public static void main(String args[]) { Scanner bevitel = new Scanner(System.in); System.out.print("Valós szám: "); double b = bevitel.nextDouble(); System.out.println(b); } }
import java.util.Scanner; class Program04 { public static void main(String args[]) { Scanner bevitel = new Scanner(System.in); System.out.print("Egész szám: "); int a = bevitel.nextInt(); System.out.print("Valós szám (vesszővel írjuk a tizedesvesszőt): "); double b = bevitel.nextDouble(); System.out.println(a + b); } }
import java.util.Scanner; class Program05 { public static void main(String args[]) { Scanner bevitel = new Scanner(System.in); System.out.print("Szöveg: "); String s1 = bevitel.nextLine(); System.out.print("Szöveg: "); String s2 = bevitel.nextLine(); System.out.println(s1 + " " + s2); } }
A Scanner osztállyal nem tudunk közvetlenül char vagy Character típust bekérni, bár megtehetjük, hogy egy beolvasott karaktersorozat első elemét vesszük:
import java.util.Scanner; class Program06 { public static void main(String args[]) { Scanner olvaso = new Scanner(System.in); char ch = olvaso.nextLine().charAt(0); System.out.println("Olvasott: " + ch); } }
A fenti példákban láttuk, hogy Scanner osztály remek lehetőség a bekérésekre. Ha viszont magyar ékezetes betűket írunk bekéréskor Windowson, azok hibásan jelennek meg, mivel a felület ahol a bekérés történik 852-s kódlappal dolgozik, és erről nem tud a Scanner osztály. Lehetőség van, azonban arra, hogy megadjuk mi beviteli környezet kódlapja. A kódlapok a következők lehetnek:
Ha parancsablakban fut a program, 852 bemenet beállítása:
Scanner sc = new Scanner(System.in, "852");
Ha Windows ablakban fut a program, cp1250 bemenet beállítása:
Scanner sc = new Scanner(System.in, "cp1250");
Ha szeretnénk operációs rendszertől függővé tenni a kódlap beállítást, akkor használhatjuk a System osztály getProperty() metódusát.
System.out.println(System.getProperty("os.name"));
Az OS megállapítása:
String os = System.getProperty("os.name").toLowerCase(); if(os.indexOf("win") >= 0) { System.out.println("Windows"); }else if(os.indexOf("nix") >=0 || os.indexOf("nux") >=0 || os.indexOf("aix") >0) { System.out.println("Unix"); }else if(os.indexOf("mac") >= 0) { System.out.println("Mac"); }
Az io csomagból a BufferedReader és az InputStreamReader osztályokat vesszük segítségül. Az io csomag osztályait nem használhatjuk kivételek feldolgozása nélkül. A metódust felkészíthetjük, hogy kezelje a kivételt, vagy rávesszük, hogy dobja el azt.
A példaprogramunkban kivételeket nem kezelünk, eldobjuk őket. Az eldobáshoz a metódus fejrészének a végére írjuk: „throws IOException.
import java.io.*; public class Program01 { public static void main(String[] args) throws IOException { InputStreamReader befolyam = new InputStreamReader(System.in); BufferedReader bemenet = new BufferedReader(befolyam); String s; int szam; System.out.print("Szám: "); s = bemenet.readLine(); szam = Integer.valueOf(s).intValue(); System.out.println("Ezt írtad: " + szam); } /* main vége */ } /* Fő osztály vége*/
Amit még felfedezhetünk, hogy a bekéréshez két osztály szükséges.
A következő kód megegyezik az előzővel, de az InputStreamReader deklarációt beágyaztuk a BufferedReader részbe.
import java.io.*; public class ap { public static void main(String[] args) throws IOException { BufferedReader bemenet = new BufferedReader(new InputStreamReader(System.in)); String s; int szam; System.out.print("Szám: "); s = bemenet.readLine(); szam = Integer.valueOf(s).intValue(); System.out.println("Ezt írtad: " + szam); } /* main vége */ } /* Fő osztály vége*/
Beolvasásra használható a System.console() metódus. Ez a metódus egy Console osztályt ad vissza, amelyen van egy readLine() metódusa, amely már alkalmas beolvasásra.
class Program01 { public static void main(String args[]) { System.out.print("Név: "); String nev = System.console().readLine(); System.out.println("Ezt írtad: " + nev); } }
A bekéréssel együtt írhatunk is a képernyőre a bekérés előtt:
class Program04 { public static void main(String[] args) { String szamStr = System.console().readLine("Kerek egy szamot: "); System.out.println("Ezt irtad: " + Integer.parseInt(szamStr)); } }
A readLine() valójában formázott bemenetre képes.
char ch; System.out.print("Karakter: "); ch = (char) System.in.read(); System.in.read(); System.out.println("A beírt karakter: " + ch); System.out.print("Karakter: "); ch = (char) System.in.read(); System.in.read(); System.out.println("A beírt karakter: " + ch); System.out.print("Karakter: "); ch = (char) System.in.read(); System.out.println("A beírt karakter: " + ch);
Ha több karaktert kérünk be az első karakter leütése után a leütött „Enter” a billentyűzet pufferben marad. Így következő billentyűzetről olvasás nem vár billentyűnyomásra, hanem tovább lép. Ezt az „Enter” billentyűt kiolvassuk a bekérés után tett System.in.read() utasítással.
Komplett példa:
import java.io.*; class Program { public static void main(String args[]) throws IOException { System.out.print("Karakter: "); char ch1 = (char) System.in.read(); System.in.read(); System.out.print("Karakter: "); char ch2 = (char) System.in.read(); System.in.read(); System.out.print("Karakter: "); char ch3 = (char) System.in.read(); System.in.read(); System.out.println("A beírt karakterek: " + ch1 + " " + ch2 + " " + ch3); } }
Karakterbekérés két másik módja:
ch = (char) System.console().reader().read(); //Java 6
A következő megoldás nem hagyja az Entert a billentyűzetpufferben.
ch = (char) new InputStreamReader(System.in).read();
import java.io.*; class Program { public static void main(String args[]) throws IOException { char ch; System.out.print("Karakter: "); ch = (char) System.console().reader().read(); System.console().reader().read(); System.out.println(ch); System.out.print("Karakter: "); ch = (char) System.console().reader().read(); System.console().reader().read(); System.out.println(ch); System.out.print("Karakter: "); ch = (char) new InputStreamReader(System.in).read(); System.out.println(ch); System.out.print("Karakter: "); ch = (char) new InputStreamReader(System.in).read(); System.out.println(ch); } }
Újabb példa:
import java.io.*; class Program { public static void main(String args[]) throws IOException { System.out.print("Karakter: "); char ch1 = (char) new InputStreamReader(System.in).read(); System.out.print("Karakter: "); char ch2 = (char) new InputStreamReader(System.in).read(); System.out.print("Karakter: "); char ch3 = (char) new InputStreamReader(System.in).read(); System.out.println("A beírt karakterek: " + ch1 + " " + ch2 + " " + ch3); } }
Alapesetben a program forráskódjában az utasítások egymás után sorban hajtódnak végre futtatáskor. Ezt nem mindig szeretnénk. Lesznek olyan utasítások, amelyek végrehajtását bizonyos feltételhez akarjuk majd kötni. Ha feltétel teljesül akkor végrehajtjuk az utasítást vagy utasításokat, ha nem akkor nem teszünk semmit, vagy éppen az utasítások egy másik csoportját akarom végrehajtani.
Vegyünk egy egyszerű iskolapéldát. Szeretném eldönteni egy változóról, hogy kisebb számot tartalmaz-e mint 100. Ha kisebbet, akkor szeretném kiírni, hogy kisebb. Ehhez tennem kell egy állítást. Például, legyen az „a” változó amit vizsgálok. Azt állíthatom például, hogy kisebb:
a < 100
Ez vagy igaz, vagy hamis állítás. Szükségünk van a Java nyelvben egy olyan utasításra, amellyel ezt képesek vagyunk megvizsgálni. Ez lesz az if.
Az if utasítással meg tudjuk vizsgálni, hogy egy állítás igaz, vagy hamis. Az állítást, mindig zárójelek közzé kell tennünk, az if után:
if (feltétel) utasítás;
A zárójel után jöhet az utasítás. Az utasítást persze tehetjük a következő sorba is, ha úgy átláthatóbb:
if (feltétel) utasítás;
Előfordul, hogy nem egy hanem több utasítást akarunk végrehajtani a feltétel teljesülése esetén. Az utasításokat ilyenkor blokk nyitó és blokk záró karakterek közzé teszem:
if (feltétel) { utasítás_1; utasítás_2; ... utasítás_n; }
A kapcsos zárójel jelzi, hogy a közzé zárt utasításokat együtt szeretném kezelni.
A következő lehetséges eset, hogy ha feltétel nem teljesül, akkor is szeretnék valamilyen utasításokat végrehajtani. Ekkor az utasítás után egy „else” kulcsszó után írom ezeket az utasításokat.
if (feltétel) utasítás_1; else utasítás_2;
Ha a feltétel teljesül, akkor az első utasítás hajtódik végre, ha nem, akkor a második, azaz az „else” utáni utasítás.
Ugyanez több utasítással:
if (feltétel) { utasítás_1; utasítás_2; ... utasítás_n; } else { utasítás_1; utasítás_2; ... utasítás_m; }
Eddig az szelekciónak csak a szintaxisát mutattuk be. Álljon itt egy konkrét példa a az if használatára:
Szelekció példa
import java.util.*; class szel { public static void main(String args[]) { Scanner bevitel = new Scanner(System.in); System.out.println("Szelekció"); System.out.print("Szám: "); int szam = bevitel.nextInt(); if(szam >0) System.out.println("Pozitív"); else System.out.println("0 vagy negatív"); } }
A program bekér egy számot, majd megvizsgálja, hogy pozitív szám, nulla vagy negatív számot írt be a felhasználó. Bekéréshez a Scanner osztályt használtam.
Többágú szelekció else if szerkezettel.
Ha több feltételnek is meg kell feleljünk, akkor egy első if utasítás után else if utasításokat használunk. Általánosan:
if (feltétel_1) utasítás_1; else if (feltétel_2) utasítás_2; else utasítás_3;
Egy konkrét példához nézzük egy problémát. A fentebb volt egy feladatunk ahol azt vizsgáltuk, hogy egy szám pozitív vagy más. A program arra már nem volt képes, hogy azt is megvizsgálja, hogy ha nem pozitív, akkor 0 vagy negatív!?! Az „else if” szerkezet lehetőséget ad erre, mert újabb feltételt tudunk beilleszteni.
import java.util.Scanner; class tobbagu { public static void main(String args[]) { Scanner olvaso = new Scanner(System.in); System.out.print("Szám: "); int szam = olvaso.nextInt(); if(szam > 0) System.out.println("Pozitív szám"); else if(szam == 0) System.out.println("Nulla"); else System.out.println("Negatív szám"); } }
Ugyanaz csak a bekérés más osztályokkal (Kezdőknek akik nem használtak Scanner osztályt.).
import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; class tobbagu2 { public static void main(String args[]) throws IOException { InputStreamReader folyam = new InputStreamReader(System.in); BufferedReader olvaso = new BufferedReader(folyam); System.out.print("Szám: "); int szam = Integer.parseInt(olvaso.readLine()); if(szam > 0) System.out.println("Pozitív szám"); else if(szam == 0) System.out.println("Nulla"); else System.out.println("Negatív szám"); } }
A switch utasítás szintén többágú szelekcióra lett kitalálva.
switch (kifejezés) { case érték1 : utasítások; break; case érték2 : utasítások; break; ... case értékn : utasítások; break; default : utasítások; }
Switch példa
class sw { public static void main(String args[]) { System.out.println("Hi"); int a = 7; switch(a) { case 1 : System.out.println("Egy"); break; case 2 : System.out.println("Kettő"); break; case 3 : System.out.println("Három"); break; case 4 : System.out.println("Négy"); break; default : System.out.println("Ismeretlen"); } } }
A fenti program megvizsgálja, hogy az „a” változóban milyen szám van. Ha 1 akkor kiírja az „Egy” karaktersorozatot a képernyőre. Ha 2 akkor a „Kettő” karaktersorozatot, stb. Ha egyik sem – mint a példában is – akkor az „Ismeretlen” karaktersorozatot írja ki.
A vizsgált változót a switch utáni zárójelek közzé írjuk. A case után írjuk szóközzel tagolva a feltételezett értékeket. A default után jönnek azok az utasítások, amelyek akkor hajtódnak végre, ha egyik feltétel sem teljesült.
Vegyük észre minden kiírató utasítás után a break utasítást. Mit csinál a break utasítást? A brak utasítás megszakítja az utasítások végrehajtását és újból a switch részhez ugrik. Hogy jobban megértsük változtassuk kissé meg a példánkat. Tegyük az „a” változóba a 2-es értéket. A case 2 : végén lévő break utasítást pedig töröljük:
class sw2 { public static void main(String args[]) { int a = 2; switch(a) { case 1 : System.out.println("Egy"); break; case 2 : System.out.println("Kettő"); case 3 : System.out.println("Három"); break; case 4 : System.out.println("Négy"); break; default : System.out.println("Ismeretlen"); } } }
Végrehajtás után az eredmény a következő:
Kettő Három
A következő, azaz a case 3 : utáni utasítás is végrehajtódott. Ez éppen a berak utasítás hiány miatt történt. A szerkezetet pont ilyen esetekre hozták létre. Ha az „a” változó értéke „2” és szeretnénk ebben az esetben „Kettő” és „Három” karaktersorozatot is a képernyőre írni.
A switch utasítás a következő primitív típusokkal működik:
Használható még a következő felsorolt típusokkal és a primitív típusok wrapper osztályaival Byte, Short, Char, Integer. A Java SE 7-es verziótól használható String osztállyal is.
Általánosan:
állítás ? érték_ha_igaz : érték_ha_hamis
A kifejezés visszaadja az első vagy második értéket, attól függően, hogy az állítás igaz, vagy hamis.
A kapott érték eltárolható egy változóban:
változó = állítás ? érték_ha_igaz : érték_ha_hamis
class Program01 { public static void main(String[] args) { int a = 3; String e = (a > 10) ? "Nagyobb" : "Kisebb"; System.out.println(e); } }
A program egyenértékű a következő if-es megoldással:
class Program01 { public static void main(String[] args) { int a = 35; String e = null; if (a > 10) e = "Nagyobb"; else e = "Kisebb"; System.out.println(e); } }
Az iteráció vagy ismétlés, amely ciklus néven ismert még.
Lesznek utasítások, amelyeket többször végre akarunk hajtani majd. Egyes esetekben tudni fogjuk hányszor, máskor pedig nem tudjuk hányszor, csak várunk valamilyen esemény bekövetkeztére. Az első eset a növekményes ciklus, a második pedig az „amíg” típusú ciklus.
A for utasítást jellemzően olyan ciklusoknál használjuk, ahol tudjuk meddig kell ismételni, azaz növekményes ciklusok esetén.
for ( kezdeti_érték ; feltétel ; növekmény) utasítás;
A for utasításnak három paramétere van. A három paramétert pontosvesszővel (;) választjuk el egymástól. A három paraméter a következő:
Ha már számolnunk kell hányszor hajtunk végre az utasításokat, akkor kell egy változó ahol ezt tárolni fogjuk. Gyakran erre a célra az „i” változót használjuk. Az „i” változónevet egy programban csak ciklusváltozóként szoktuk használni. A Java fordító erre nem kötelez, de jó szokás. Ha az „i” foglalt, akkor a következő „j”. Ha ez is foglalt, akkor „k”. Ennél több eset ritka, de van még betű az ábécében.
A következő példában az „i” változót használjuk ciklusváltozónak:
for ( i = 1; i <= 10 ; i++) System.out.println("Város");
Az i változót persze valahol deklarálni kell. A Java nyelv megengedi, hogy ezt a ciklus fejrészében (a ciklus zárójelben lévő része) tegyük:
for ( int i = 1; i <= 10 ; i++) System.out.println("Város");
Hasonlóan az if szerkezethez, itt is írhatunk több utasítást is a ciklus törzsébe (egy utasítás esetén, maga ez az egy utasítás a törzs, több utasítás esetén a blokk nyitótól a blokk záróig tart.
for ( int i = 1; i <= 10 ; i++) { System.out.println("Város"); System.out.println("Cím"); }
A fenti példákban a ciklustörzsben lévő utasítás, illetve utasítások 10-szer hajtódnak végre. Ezt a következő fejrésszel értük el:
for ( int i = 1; i <= 10 ; i++)
Ugyanez elérhető így is:
for ( int i = 0; i < 10 ; i++)
Vegyük észre a különbséget. A kezdő érték az utóbbi esetben 0, és addig megy a ciklus amíg kisebb mint 10, tehát 9-ig.
A while ciklus alapvetően „amíg” típusú ciklusok használatára találták ki.
A while ciklus általánosan így épül fel:
while (feltétel) utasítás;
Egy konkrét példa
i = 1; while (i <= 10) { System.out.println("Város"); i++; }
A példában szereplő while ciklus ugyanazt csinálja mint a fentebbi programok legtöbbje. Itt is tudjuk meddig megyünk. A while utasítást úgy használtuk mint a for-t. Csak a kezdőértéket a ciklus előtt adtam meg, a növekményt meg a ciklus törzsében.
Ez persze még nem az „amíg” típusú ciklus. Az „amíg” típusú ciklusnál nem tudjuk meddig megyünk. Várunk egy eseményre. A példa kedvéért a felhasználótól számokat kérünk be összeadás céljából. Nem tudjuk mennyit, majd a felhasználó eldönti. Ekkor valahogy biztosítanunk kell, hogy a bevitel végét jelezze. Ha 0 értéket nem vihet be a felhasználó, akkor használhatjuk ezt végjelnek.
Vagyis kérjük be sorra a számokat, amikor a felhasználó 0 számot üt be, akkor nem kérünk több számot. A következő példában a Scanner osztállyal kérünk be számokat 0 végjelig:
import java.*; import java.util.*; class vegjelig { public static void main(String[] argv) { Scanner bevitel = new Scanner(System.in); int szam=-1; while(szam != 0) { System.out.print("Kovetkezo szam: "); szam = bevitel.nextInt(); } } }
A példában persze a bekért számokkal még nem csinálunk semmit. Szeretnénk összeadni a bekért számokat:
import java.*; import java.util.*; class osszeg { public static void main(String[] argv) { Scanner bevitel = new Scanner(System.in); int szam=-1; int osszeg = 0; while(szam != 0) { System.out.print("Kovetkezo szam: "); szam = bevitel.nextInt(); osszeg = osszeg + szam; } System.out.printf("%d\n", osszeg); } }
Gyakorlásképpen összeadás helyett szorozza össze a bekért számokat. Bekérés közben ne írja ki a részeredményeket. Csak a ciklus végén írja ki a szorzatot.
Az eddigi ciklusok úgynevezett elől tesztelő ciklusok voltak. Ez annyit tesz, hogy előbb megvizsgálták a feltételt, majd ha az igaz volt, végrehajtották a ciklustörzs utasításait. A most következő ciklus hátul tesztelő ciklus. A ciklus törzsében lévő utasítások egyszer mindenképpen végrehajtódnak, a feltétel csak ez után kerül vizsgálatra. Ha a feltétel igaz, akkor az ciklus törzsében lévő utasítások megint végrehajtódnak.
do { utasítások; }while(feltétel);
Vegyük észre, hogy ezt ciklust végén le kell zárni pontosvesszővel.
Konkrét példa a hátul tesztelésre:
import java.util.*; class hatul { public static void main(String args[]) { Scanner bevitel = new Scanner(System.in); System.out.println("Hátul tesztelő ciklus"); int szam; do { System.out.print("Szám: "); szam = bevitel.nextInt(); }while(szam != 0); } }
A for utasításnak van egy kiterjesztett változata, amely tömbök és kollekciók iterálására lett kitalálva. Angolosan enhanced for néven ismert. A következőben ennek a használatát látjuk.
class Program01 { public static void main(String args[]) { String[] varos = {"Debrecen", "Nyíregyháza", "Zalaegreszeg", "Pécs", "Szeged"}; for(String str : varos) System.out.println(str); } }
A for() ciklus segítségével végtelen ciklust is előállíthatunk ha nem adunk meg paramétert:
for(;;){ //ciklustörzs }
A tömb azonos típusú értékeket tárolására alkalmas adatszerkezet. A tömböknek beszélünk a kiterjedéséről. Ha a kiterjedés csak egyirányú akkor vektorról beszélünk, ami hasonlít is a matematikában tanult vektorfogalomhoz. Ha a kiterjedés kétirányú akkor mátrixról beszélünk, szintén a matematikában használt mátrixhoz hasonlóan. A tömböknek lehet ennél több kiterjedése is, három, vagy akár több. De ezeket már ritkán szoktuk használni.
Egy tömb akkor vektor, ha egyirányú a kiterjedése. Például egész számokat szeretnénk eltárolni:
37 | 23 | 47 | 52 | 28 |
A példában öt darab egész számot szeretnénk tárolni.
A tömb egyes elemeivel szeretnénk valamit csinálni, így hivatkozni kell rájuk. Ezt úgy szoktuk megtenni, hogy minden értékhez egy indexet rendelünk. Az első érték indexe nulla, a következőé egy, aztán kettő, stb.
0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
37 | 23 | 47 | 52 | 28 |
<elemi típus>[] <változó név>;
vagy
<elemi típus> <változó név>[];
Konkrét példa:
int[] tomb;
vagy
int tomb[];
Kezdőérték adása
int[] tomb = {37, 23, 47, 52, 28};
De lehet így is:
int[] tomb = new int[] {37, 23, 47, 52, 28};
Más típussal:
long[] fizetesek = new long[] {10000, 20000, 30000, 40000};
int[] tomb = {3, 4, 7, 8};
A Java tömböknek deklaráláskor nincs hely lefoglalva a memóriában. Ez a new kulcsszóval kell megtennünk. Pl.:
class tomb { public static void main(String args[]) { int[] tomb; tomb = new int[5]; tomb[0]=37; System.out.println(tomb[0]); } }
class tomb2 { public static void main(String args[]) { int[] tomb = new int[5]; tomb[0]=37; System.out.println(tomb[0]); } }
Tömb mérete
import java.lang.reflect.*; ... System.out.println(Array.getLength(tomb));
System.out.println(tomb.length);
Tömb feltöltése:
import java.util.*; class Program { public static void main(String[] argv) { int[] tomb = new int[10]; Arrays.fill(tomb, 5); for(int i=0; i<tomb.length; i++) System.out.print(tomb[i] + " "); System.out.println(); } }
A példában 5-ös számokkal töltjük fel a tömböt.
1 | 3 | 3 |
2 | 4 | 6 |
3 | 4 | 7 |
5 | 6 | 7 |
Integer ars[][] = new Integer[4][3]; // Integer az int burkoló osztálya
int ars[][] = new int[][]{{1,3,3}, {2,4,6}, {3,4,7}, {5,6,7}};
Olyan mint egy 4 x 3 matrix
public class MultiDimensionalArrayExample { public static void main(String[] args) { int ars[][] = new int[][]{{1,2,3}, {2,4,6}, {3,4,7}, {5,6,7}}; for(int i = 0; i < 4; i++) for(int j = 0; j < 3; j++) System.out.println(ars[i][j]); } }
int tomb[][] = new int[8][4]; System.out.println(tomb.length); // 8-at ír ki System.out.println(tomb[0].length); // 4-et ír ki
A Java egyszerű tömbjeit nem arra találták ki, hogy később átméretezzük őket. Az átméretezés azért megoldható:
int ujHossz = 20; int eredetiHossz = tomb.length; Class componentType = tomb.getClass().getComponentType(); Object tomb2 = Array.newInstance(componentType, ujHossz); int vedettHossz = Math.min(eredetiHossz,ujHossz); if (vedettHossz > 0) System.arraycopy(tomb, 0, tomb2, 0, vedettHossz); tomb = (int[]) tomb2;
A komplett program működés közben:
class tombmeret { private static Object resizeArray (Object oldArray, int newSize) { int oldSize = java.lang.reflect.Array.getLength(oldArray); Class elementType = oldArray.getClass().getComponentType(); Object newArray = java.lang.reflect.Array.newInstance( elementType,newSize); int preserveLength = Math.min(oldSize,newSize); if (preserveLength > 0) System.arraycopy (oldArray,0,newArray,0,preserveLength); return newArray; } public static void main(String[] args) { int[] tomb = new int[10]; tomb[0] = 35; tomb[1] = 27; tomb[2] = 42; System.out.println(tomb.length); tomb = (int[]) resizeArray(tomb, 20); System.out.println(tomb.length); } }
Látjuk, hogy az ilyen egyszerű tömbök nem méretezhetők át könnyen. Ha méretezhető tömböt szeretnénk, akkor használjuk az ArrayList vagy a Vector osztályt, az util csomagból. Ezek átméretezése automatikus.
Az Arrays osztály arra való, hogy tömbökön végezzünk néhány műveletet. Ez lehet annak feltöltése.
int[] tomb = new int[10]; java.util.Arrays.fill(tomb, 0);
method(new Object[] { a, b, c});
Az java.util.ArrayList dinamikus tömböt valósít meg.
A tömblisták (ArrayList) automatikusan átméreteződnek, mérete mindig az elemek számától függ. Az egyes elemeket mindössze fel kell venni vagy törölni. Egy ilyen változó (objektum) deklarálásánál meg kell adnunk milyen típusú elemet szeretnénk tárolni kisebb-mint és nagyobb-mint jelek között. A következő példában például karaktersorozatot szeretnénk tárolni:
ArrayList<String> tomb = new ArrayList<String>();
Vagy egészek tárolása
ArrayList<Integer> tomb = new ArrayList<Integer>();
Lássuk az alábbi példában egy komplett programot:
import java.util.*; class Program { public static void main(String[] argv) { ArrayList<String> tomb = new ArrayList<String>(); tomb.add("eper"); tomb.add("málna"); tomb.add("barack"); System.out.println(tomb.get(2)); } }
Az ArrayList tartalmának kiíratása:
ArrayList<String> lista = new ArrayList<>(); lista.add('János'); lista.add('Mihály'); lista.add('Imre'); System.out.println(lista);
Az ArrayList-et egyszálas programokhoz tervezték. A Vectort többszálas programokhoz. A Vector nem ellenőrzi, ha a kollekciója megváltozik, ami hibákhoz vezethet.
megváltozhat az iteráció során, viszont a változás nem ellenőrzött.
A vektor az ArrayList-hez hasonlóan használható. Meg kell adnunk mit szeretnénk benne tárolni. A következőben lássunk egy komplett példát a használatára.
import java.util.*; class Program2 { public static void main(String[] argv) { Vector<String> tomb = new Vector<String>(); tomb.add("eper"); tomb.add("málna"); tomb.add("barack"); System.out.println(tomb.get(2)); } }
Elem törlése
tomb.remove(1);
Ha Object típust adok meg akkor különböző típusokat is eltehetek a verembe.
import java.util.*; class Program3 { public static void main(String[] argv) { Vector<Object> tomb = new Vector<Object>(); tomb.add("eper"); tomb.add(25); tomb.add("málna"); tomb.add("barack"); System.out.println(tomb.get(1)); } }
Egyéb metódusok használat közben:
import java.util.*; class Program4 { public static void main(String[] argv) { Vector<Object> tomb = new Vector<Object>(); tomb.add("eper"); tomb.add(25); tomb.add("malna"); tomb.add("barack"); tomb.addElement("korte"); System.out.println(tomb.get(1)); System.out.println(tomb.size()); System.out.println(tomb.remove(1)); System.out.println(tomb.size()); System.out.println(tomb.get(1)); System.out.println(tomb.elementAt(2)); System.out.println("Hol talalhato: " + tomb.indexOf("malna")); tomb.clear(); System.out.println(tomb.size()); tomb.addElement(new Integer(1)); tomb.addElement(new Integer(2)); System.out.println("Utolso: " + tomb.lastElement()); System.out.println("Elso: " + tomb.firstElement()); tomb.removeAllElements(); tomb.addElement("Valami"); tomb.addElement("Masik"); //Konverziók: Object[] tomb2 = tomb.toArray(); String[] tomb3 = new String[10]; tomb3 = (String []) tomb.toArray(tomb3); //Itt gond, ha a vektor nem string típusú elemet tartalmaz //Olyankor Object típusba lehet konvertálni. Enumeration e = tomb.elements(); } }
Ha Vector és hasonló listák esetén, ha számot akarunk tárolni akkor nem használhatjuk a primitív típust, helyette a burkolóosztályt kell használnunk. Ugyanakkor a for ciklusnak használhatjuk egy újabb változatát a lista kiíratására.
A következő példa ezt mutatja be:
import java.util.Scanner; import java.util.Vector; class Program { public static void main(String args[]) { Vector<Integer> szamok = new Vector<Integer>(); szamok.add(37); szamok.add(52); szamok.add(48); szamok.add(87); szamok.add(23); for(Integer szam : szamok) System.out.print(szam + " "); System.out.println(); } }
Vegyük észre az „Integer”-t az „int” helyett, a for ciklus fejrészében pedig „Integer szam : szamok”. Utóbbi azt jelenti, hogy veszem a szamok list minden elemét. Az elemeket a szam változóban kapom meg minden ciklusban, ameddig a lista elemei el nem fogynak.
A List egy Interfész, ezért példányt nem lehet belőle létrehozni. A konstruktorként az előző osztályok valamelyikét használhatjuk. A következő példában a Vector<> osztályt használjuk konstruktorként.
import java.util.*; class Program5 { public static void main(String[] argv) { List<String> tomb = new Vector<String>(); tomb.add("eper"); tomb.add("málna"); tomb.add("barack"); System.out.println(tomb.get(1)); } }
Használható <Object> típussal egyszerre több típus.
A Set egy interface, nem osztály. Ezért nincs is konstruktora. Helyette a TreeSet vagy HashSet osztályok konstruktorát használjuk. Egy halmazt határozhatunk meg vele, amelyen a szokásos halmazműveletek használhatók.
import java.util.*; class Program6 { public static void main(String[] argv) { //Set<String> halmaz = new TreeSet<String>(); Set<String> halmaz = new HashSet<String>(); halmaz.add("eper"); halmaz.add("málna"); halmaz.add("barack"); System.out.println(halmaz.size()); System.out.println(halmaz.contains("eper")); Iterator it = halmaz.iterator(); while(it.hasNext()) { Object elem = it.next(); } } }
import java.util.Iterator; import java.util.Vector; public class Program02 { public static void main(String args[]) { Vector<String> v = new Vector<String>(); v.add("alma"); v.add("körte"); v.add("barack"); v.add("szilva"); Iterator<String> i = v.iterator(); while (i.hasNext()) { System.out.println(i.next()); } } }
List<String> list = new ArrayList<String>(); list.addAll(list1); list.addAll(list2);
A C nyelvben ezt struct, míg Pascal nyelvben ez a record. A Java nyelvben ezek egyike sem használható, helyette osztályt használhatunk a már meglévő osztályon belül.
import java.io.*; class Program01 { public static void main(String args[]) throws IOException { class Dolgozo { int kor; double fizetes; } Dolgozo Joska = new Dolgozo(); Joska.kor = 23; Joska.fizetes = 370000; System.out.printf("%f\n", Joska.fizetes); System.out.println("Folytatáshoz nyomjon egy billentyűt"); System.in.read(); } }
vagy
import java.io.*; class Program01 { static class Dolgozo { int kor; double fizetes; } public static void main(String args[]) throws IOException { Dolgozo Joska = new Dolgozo(); Joska.kor = 23; Joska.fizetes = 370000; System.out.printf("%f\n", Joska.fizetes); System.out.println("Folytatáshoz nyomjon egy billentyűt"); System.in.read(); } }
Sokszor előfordulhat, hogy több különböző adatot szeretnénk tárolni de nem csak egy dologról vagy személyről hanem többről.
Például szeretnénk dolgozók adatait tárolni:
import java.io.*; class Osztalytomb { public static void main(String[] args) throws IOException { Dolgozo[] munkas = new Dolgozo[3]; munkas[0] = new Dolgozo("Nagy Béla", 350000); munkas[1] = new Dolgozo("Kis János", 750000); munkas[2] = new Dolgozo("Rózsa Sándor", 380000); for (int i = 0; i < 3; i++) munkas[i].print(); System.in.read(); } } class Dolgozo { private String nev; private double fizetes; public Dolgozo(String n, double s) { nev = n; fizetes = s; } public void print() { System.out.println(nev + "\t" + fizetes); } }
Újabb példa:
class Program01 { static class Dolgozo { String nev; int kor; double fizetes; } public static void main(String[] args) { Dolgozo[] munkas = new Dolgozo[3]; for(int i=0; i<3;i++) munkas[i] = new Dolgozo(); munkas[0].nev = "Nagy István"; munkas[0].kor = 25; munkas[0].fizu = 285600.0; munkas[1].nev = "Kis Béla"; munkas[1].kor = 32; munkas[1].fizu = "Kis Béla"; munkas[2].nev = "Be Kornél"; munkas[2].kor = 22; munkas[2].fizu = "Erős Lajos"; } }
Harmadik példa
/* Több tulajdonság tárolása listában */ import java.util.ArrayList; public class Program02 { public static void main(String[] a) { ArrayList<Dolgozok> dolgozok = new ArrayList<Dolgozok>(); dolgozok.add(new Dolgozok("Nagy", "József")); dolgozok.add(new Dolgozok("Rezeg", "István")); dolgozok.add(new Dolgozok("Kékedi", "János")); System.out.println(dolgozok); Dolgozok d = dolgozok.get(1); d.beallitVezNev("Erős"); System.out.println(dolgozok); Dolgozok d2 = dolgozok.get(1); System.out.println(d2.lekerVezNev()); } } class Cim { } class Dolgozok { private String vezNev; private String kerNev; private Double fizetes; public Cim cim; public Dolgozok(String vezNev, String kerNev) { this.vezNev = vezNev; this.kerNev = kerNev; this.cim = new Cim(); } public String lekerVezNev() { return this.vezNev; } public void beallitVezNev(String vezNev) { this.vezNev = vezNev; } public String lekerKerNev() { return this.kerNev; } public void beallitKerNev(String kerNev) { this.kerNev = kerNev; } public double lekerFizetes() { return this.fizetes; } public void beallitFizetes(double fizetes) { this.fizetes = fizetes; } }
Egy példa automatikus feltöltéssel:
class Szemely { private String nev; private int szuletesEve; Szemely(String nev, int szuletesEve) { this.nev = nev; this.szuletesEve = szuletesEve; } @Override public String toString() { return nev + ":" + szuletesEve; } } class Program01 { public static void main(String args[]) { Szemely[] szemelyek = new Szemely[5]; for(int i=0;i<5;i++) { szemelyek[i] = new Szemely("Névtelen" + i, 0); } System.out.println(szemelyek[1].toString()); } }
Ha HashSet osztályba szeretnénk például egy Dolgozo osztály példányait tárolni, néhány dolog nem fog működni alapértelmezetten. Ha például felveszem kétszer ugyanazt az adatot, mindkét adat tárolásra kerül, pedig halmazról lévén szó ennek nem lenne szabad bekövetkeznie. Ha egy HashSet objektumba, amely például Integer értékeket tartalmaz, a 22 értéket kétszer adom hozzá az add() metódussal, az csak egyszer fog tárolódni.
Visszatérve a Dolgozo osztályunkhoz, hasonló probléma lép fel, ha meg akarom vizsgálni, hogy egy adott dolgozó szerepel-e már a halmazban. Ezt a contains() metódussal szoktuk vizsgálni. Ha a HashSet halmazunkban a Dolgozo osztály példányai vannak a contains() metódus mindig hamis értéket fogunk kapni, vagyis nem tudjuk megvizsgálni vele, hogy egy adott dolgozó szerepel-e egy halmazban.
Természetesen a probléma megoldható, csak felül kell írnunk a hashCode() és a equals() metódust. A következő programban erre látunk példát:
import java.util.HashSet; class Dolgozo { String nev; int kor; double fiz; Dolgozo(String nev, int kor, double fiz) { this.nev = nev; this.kor = kor; this.fiz = fiz; } @Override public boolean equals(Object o) { if(this == o) return true; Dolgozo dolgozo = (Dolgozo) o; if(!dolgozo.nev.equals(this.nev)) return false; if(dolgozo.kor!=(this.kor)) return false; if(dolgozo.fiz!=(this.fiz)) return false; return true; } @Override public int hashCode() { int nevHash = this.nev.hashCode(); int korHash = this.kor; int fizHash = (new Double(this.fiz)).hashCode(); int res = nevHash + korHash + fizHash; return res; } } class Program01 { public static void main(String args[]) { HashSet<Dolgozo> h = new HashSet<Dolgozo>(); h.add(new Dolgozo("Nagy József", 35, 350000)); h.add(new Dolgozo("Nagy József", 35, 350000)); System.out.println(h.contains(new Dolgozo("Nagy József", 35, 350000))); System.out.println(h.size()); } }
Az enum típus egy speciális típus, amellyel a nevesített állandókhoz hasonló típusok jönnek létre. Egy ilyen típus több nevet tartalmaz. Értéket azonban nem adunk nekik, csak a nevükkel hivatkozunk rájuk. Használatával olvashatóbb kódot kapunk.
enum Egtaj { ESZAK, DEL, KELET, NYUGAT }
enum Os { LINUX, WINDOWS, MACOSX }
class Program { enum Nap { HETFO, KEDD, SZERDA, CSUTORTOK, PENTEK, SZOMBAT, VASARNAP } public static void main(String[] args) { Nap a = Nap.HETFO; System.out.println(a); } }
Legyen egy példa, ahol dolgozók adatait tároljuk, köztük a dolgozó státuszát. A státusz lehet aktív, próbaidős, szabadságos, beteg, megszüntetés alatt.
A státuszok nyilvántartására készítünk egy enum típust:
public enum Status { TRIAL, ACTIVE, HOLIDAY, SICK, TERMINATE }
A dolgozók tárolásánál ezt használjuk:
public class Employee { int id; String name; String city; double salry; Status status; }
Dolgozó státuszának beállítása:
public class App { public static void main(String[] args) throws Exception { handleEmp(); } public static void handleEmp() { Employee emp = new Employee(); emp.status = Status.ACTIVE; System.out.println(emp.status); } }
A lehetséges kimenet:
ACTIVE
A dolgozók státuszát tárolhattuk volna String típusban is, de amikor értéket kell adni neki:
emp.status = "active";
El kell gondolkodnunk, hogy most akkor mit kell pontosan írni? Acitve, active, aktív, ACTIVE, esetleg working vagy más?
Ha enum típust használunk a fordító vagy maga a fejlesztő eszköz szól, ha elírtuk.
További lehetséges enum típusok
Még több:
enum Day {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY } enum Nap {HETFO, KEDD, SZERDA, CSUTORTOK, PENTEK, SZOMBAT, VASARNAP} ; enum MovieType {ACTION, HORROR, COMEDY}; enum Gender {MALE, FEMALE}; enum WeekDay { MON, TUE, WED, THU, FRI, SAT, SUN }; enum Grade { A, B, C, D, F, INCOMPLETE }; //Ertekeles enum Tank { EMPTY, HALF, FULL }; //Penny =1 centes, Nickel=5 centes, Dime=10 centes, Quarter=25 centes ; Amerika enum Currency {PENNY, NICKLE, DIME, QUARTER}; enum Color {WHITE, BLACK, RED, YELLOW, BLUE }; enum Planet { MERCURY, VENUS, EARTH, ARS, JUPITER, SATURN, URANUS, NEPTUNE}; //sugár km, tömeg kg. enum Bolygo { MERKUR (2439.7, 3.302E+23), VENUSZ (6051.8, 4.8685E+24), FOLD (6378.137, 5.9736E+24), MARS (3402.5, 6.4185E+23), JUPITER (71492.0, 1.899E+27), SZATURNUSZ (60268, 5.6846e+26), URANUSZ (25559, 8.6832e+25), NEPTUNUSZ (24764, 1.0243e+26); private final double radius; private final double mass; Bolygo(double radius, double mass){ this.radius = radius; this.mass = mass; } private double getRadius() { return radius;} private double getMass() { return mass;} }
A char típus egy karakter tárolására való. Igaz a Java Unicode karaktereket tárol, de az angol ábécé betűi az UTF-8 megvalósítás esetén kompatibilisek az ASCII kódtáblával.
Ha tudjuk, hogy az ASCII kódtáblában a nagy „A” és a kis „a” közötti különbség 32, akkor egyszerűen alakíthatjuk a nagybetűs karaktereket kisbetűssé és fordítva:
class ascii { public static void main(String args[]) { char ch = 'A'; System.out.printf("%c\n", ch + 32); } }
A példában a nagy „A” karaktert kis „a” karakterré alakítjuk.
Rendelkezésre állnak a Character osztály metódusai is:
Kisbetűssé alakítása
char ch = Character.toLowerCase('A');
Szám, karakterként kezelése továbbiakban:
int a = 65; char ch = (char) a;
A Character osztály további metódusai:
boolean isDigit(char ch) |
boolean isLetter(char ch) |
boolean isLetterOrDigit(char ch) |
boolean isWhitespace(char ch) |
boolean isLowerCase(char ch) |
boolean isUpperCase(char ch) |
String toString() |
String toString(char c) |
char toUpperCase(char ch) |
A következő programban szeretnénk az „a” karakter ASCII kódját megkapni:
class Program01 { public static void main(String args[]) { char ch = 'a'; System.out.printf("%d\n", (int) ch); } }
Itt pedig van egy ASCII kódunk és szeretnénk kiíratni a hozzátartozó karaktert:
class Program01 { public static void main(String args[]) { int a = 65; System.out.printf("%c\n", a); } }
Az „a” karaktert tárolhatjuk eleve int típusban:
class Program01 { public static void main(String args[]) { int a = 'a'; System.out.printf("%d\n", a); } }
Kódpontok kiíratása:
Összehasonlításhoz használhatjuk a ”==„ az egyenlőségjeleket vagy ha burkolóosztályt használtunk, akkor equals() függvényt is.
A Scanner osztállyal közvetlenül nem kérhető be karakter. De bekérhetünk egy sztringet, aminek vesszük az első karakterét.
import java.util.*; class App { public static void main(String args[]) { Scanner sc = new Scanner(System.in); System.out.print("Karakter: "); String str = sc.next(); char ch = str.charAt(0); System.out.println(ch); sc.close(); } }
A next() metódus helyett használható a nextLine() metódus is.
import java.io.*; class Pel { public static void main(String args[]) throws IOException { InputStreamReader folyam = new InputStreamReader(System.in); BufferedReader olvaso = new BufferedReader(folyam); System.out.print("Karakter: "); String str = olvaso.readLine(); char ch = str.charAt(0); System.out.println(ch); } }
class Program01 { public static void main(String args[]) { if(Character.toString('a').equals("a")) System.out.println("Egyenlő"); else System.out.println("Nem egyenlő"); } }
Stringeket a String osztállyal hozhatunk létre. Nincs string primitív típus.
String s; s = "alma";
A Java nyelvben a sztringváltozónak értékadással is adhatunk értéket. A String osztály statikus, vagyis használható példányosítás nélkül.
A legnagyobb beírható string hossza: 65534
import java.io.*; class Szoveg { public static void main(String args[]) throws IOException { String s; s = "alma"; System.out.println(s.length()); System.in.read(); } }
Egyenlőség vizsgálat
String gyumolcs = "körte"; if (gyumolcs.equals("alma")) System.out.println("A gyümölcs alma");
A karaktersorozat hosszát adja vissza.
int hossz = s.length();
Karaktersorozatok összefűzésére való.
String s = "egyik"; s.concat(" másik");
Az s változót kiíratva ezek után ezt kapjuk:
egyik másik
Egy karaktersorozatban egy adott karaktersor cseréje egy másikra.
Általános szintaxis:
replace(mitCserél, mireCserél)
Egy konkrét példa:
String s = new String("Nagy kő esett le a szívemről tegnap"); System.out.print(s.replace("szívemről", "egy kocsiról"));
Egy karaktersorozatban a megtalált mintát minden helyen kicseréli.
str.replaceAll("\\s+", "\t"); //Szóközök tabulátorra cserélése
Kisbetűssé alakít minden karaktert.
toLowerCase()
String str = "SziLVa"; String kisbetus = str.toLowerCase();
Nagybetűssé alakít minden karaktert.
toUpperCase()
String str = "SziLVa"; String nagybetus = str.toUpperCase();
A trim() a szöveg elejéről és a végéről eltávolítja a whitespace karaktereket.
String s = " alma "; System.out.println(s.trim());
A karaktersorozatot feldarabolja a megadott szeparátor alapján.
str.split("\\s+"); //Egy vagy több szóköz
Szeparátorként megadható szabályos kifejezés. A split() függvény egy String[] típus ad vissza.
Megvizsgáljuk, hogy a karaktersorozat-változó üres-e.
Példa:
boolean ures = str.isEmpty();
class Str { public static void main(String args[]) { System.out.println("Szövegkezelés Java nyelven"); String szoveg = "alma"; System.out.println(szoveg.equals("almaa")); // true értéket ad, ha egyezik, vagy false System.out.println(szoveg.compareTo("alma")); // 0-át kapunk, ha egyezik System.out.println(szoveg.indexOf("alma")); // -1 ha nem található; // Ha szoveg változóban van ilyen annak a kezdő indexét kapjuk meg // Esetünkben 0 //Szöveg darabolása String sor ="alma:körte:barack:szilva"; String[] tomb = sor.split(":"); System.out.println(tomb[1]); String mondat = "Ha megint ezért üzen"; System.out.println(mondat.substring(4)); //Kezdő indextől szeretném a karaktereket System.out.println(mondat.substring(4, 6)); //Kezdő index és vég index közötti karakterek } }
A Sztring típusú objektum egy karakterére nem hivatkozhatunk a Java nyelven szögletes zárójelekkel, mint egy tömbnél. Sztring esetén a charAt() metódust használhatjuk.
Karakter tömb esetén a hivatkozás:
char[] tomb = {'a', 'b', 'c'}; System.out.println(tomb[1]);
Sztring esetén csak így:
String tomb = "abc"; System.out.println(tomb.charAt(1));
Esetleg, használjunk String() konstruktort:
char[] adat = {'a', 'b', 'c'}; String adat2 = new String(adat); System.out.println(adat2.charAt(1));
A string osztállyal létrehozott változó valójában nem változtatható meg. Ha ilyen műveletet végzünk a háttérben valójában egy új példány jön létre.
String str = "szilva"; str = "barack";
A fenti példa második sorában a egy új str objektum jön létre a memóriában.
Ugyanaz mint a StringBuffer, de a Stringek nincsenek szinkronizálva. Ezért használatát egy szálas programokhoz találták ki.
StringBuilder defString = new StringBuilder(); // 16 karakter méret beállítása StringBuilder nulString = new StringBuilder(6); // pontos méret megadása StringBuilder aString = new StringBuilder("kezdőérték"); // kezdőérték megadása
Hozzátartozó metódusok:
capacity(), length(), charAt(i), indexOf(g), lastIndexOf(g)
Módosító metódusok:
append(g), delete(i1, i2), insert(iPosn, g), getChars(i), setCharAt(iposn, c), substring(), replace(i1,i2,gvalue), reverse(), trimToSize(g ), toString(g)
Összehasonlítás String típussal:
if(strb.toString().equals("hasonlítószöveg")) //Mit tegyünk
StringBuffer s;
A StringBuffer osztállyal olyan sztringeket hozhatunk létre, amit meg is tudunk változtatni.
StringBuffer defString = new StringBuffer(); // 16 karakter méret beállítása StringBuffer nulString = new StringBuffer(6); // pontos méret megadása StringBuffer aString = new StringBuffer("kezdőérték"); // kezdőérték megadása
Hozzátartozó metódusok:
capacity(), charAt(i), length(), substring(iStart [,iEndIndex)])
Módosító metódusok:
append(g), delete(i1, i2), deleteCharAt(i), ensureCapacity(), getChars(srcBeg, srcEnd, target[], targetBeg), insert(iPosn, g), replace(i1,i2,gvalue), reverse(), setCharAt(iposn, c), setLength(),toString(g)
Az alábbi sorok a Calander típusú objektum tartalmát teszik olvashatóvá:
java.util.Calendar c = java.util.Calendar.getInstance(); String s = String.format("Születésnap: %1$tY-%1$tm-%1$te", c);
Valós szám kiíratása:
double a = 3.7; System.out.println(String.format("%.2f\n", a));
int hossz = s2.length();
int szam1 = 4; double szam2 = 3.5; String szamegy = String.valueOf(szam1); String szamketto = String.valueOf(szam2);
String s1 = "3.5"; String s2 = "34"; double szam1; int szam2; szam1 = Double.valueOf(s1).doubleValue(); szam2 = Integer.alueOf(s2).intValue();
String gyumolcs = "alma"; if (gyumolcs.equals("körte")) System.out.println("A gyümölcs: körte");
Lexikográfiai összehasonlítás. 0-át kapunk ha azonos, 0-nál kisebb értéket ha a második kisebb (lexikográfialilag), illetve 0-nál nagyobb értéket ha nagyobb.
String abc = "abc"; Stirng def = "xyz"; if (abc.compareTo(def) < 0) // 'a' kisebb mint 'x' if (abc.compareTo(abc) == 0) // ez is igaz
String s = "Finomabb"; int kezdet; kezdet = s.indexOf('b')
String s = "Finomabb"; int kezdet; kezdet = s.indexOf("nom")
String s = "Finomabb"; String resz; resz = s.substring(2,4);
Az első paraméter a kezdet, a második a vég.
String s = "barack"; char[] t = s.toCharArray(); System.out.println(t[0]);
Iterálással:
class Program01 { public static void main(String[] args) { String str = "almakörte"; char[] ca = str.toCharArray(); for(char ch : ca) { System.out.println(ch); } } }
String s = "barack:körte:alma"; String[] ts = s.split(":"); System.out.println(ts[1]);
A „|” szeparátorral nem működik. A Szeparátor lehet reguláris kifejezés is.
A kivételkezelést a program futtatása során fellépő abnormális állapotok kezelésére találták ki. Abnormális állapot esetén a programok kivételt dobnak. Például, egy nemlétező állományra hivatkozunk, vagy írni akarunk állományba, de nincs hozzá jogunk. Esetleg nullával próbáltunk meg osztani.
Ha egy program dobott egy kivétel, mi két dolgot tehetünk. Eldobjuk vagy kezeljük. Az eldobás a throws utasítással lehetséges. Az elkapás a try-catch utasítás párral.
import java.io.*; import java.util.*; class program { public static void main(String args[]) throws IOException { Scanner be =new Scanner(System.in); double c=0; int a = be.nextInt(); try { c = 50 / a; } catch (Exception e) { if (e instanceof ArithmeticException) System.out.println("Osztás nullával"); } System.out.printf("%f\n", c); System.out.println("Folytatáshoz nyomj egy billentyűt!"); System.in.read(); } }
try{ //utasítások }catch(IOException e) { System.err.println("Kivétel törént - Hogy miért? Lásd itt: "); e.printStackTrace(); System.exit(-1); }
A kivétel eldobása:
import java.io.IOException; class Program01 { public static void main(String[] args) throws IOException { System.out.println("Folytatáshoz nyomjon Entert"); System.in.read(); } }
Ha lebegőpontos számokkal dolgozunk és 0-val osztunk, akkor az nem hiba. Ez csak egész számok esetén hiba. Valós számok esetén az eredmény végtelen.
class Program01 { public static void main(String[] args) { double a = 1/0.; if(a == Double.POSITIVE_INFINITY) { System.out.println("Végtelen"); } else { System.out.println("Valami más"); } } }
Fájl létezésének ellenőrzése:
import java.io.*; public class ap { public static void main(String[] args) { File f = new File("adat.txt"); System.out.println(f.exists()); } }
További metódusok:
A fájl objektum könyvtárakat is jelölhet.
Ha egy File objektum könyvtárat jelöl akkor hívható a következő metódus:
import java.io.*; class Program2 { public static void main(String args[]) throws IOException { FileReader olvaso = new FileReader("adat.txt"); StringBuilder strb = new StringBuilder(); char ch; while(olvaso.ready()) { ch = (char)olvaso.read(); strb.append(ch); } olvaso.close(); System.out.println(strb); } }
import java.io.*; class readfile { public static void main(String[] argv) throws IOException { FileReader folyam = new FileReader("adat.txt"); BufferedReader fileolvaso = new BufferedReader(folyam); String sor; while ((sor = fileolvaso.readLine()) != null) { System.out.println(sor); } fileolvaso.close(); } }
import java.io.*; public class ap { public static void main(String[] args) throws IOException { File f = new File("adat.txt"); FileReader fr = new FileReader(f); BufferedReader bemenet = new BufferedReader(fr); boolean vege = false; String s; while(!vege) { s = bemenet.readLine(); if (s != null) System.out.println(s); else vege = true; } bemenet.close(); } }
import java.io.*; import java.util.*; class readfile2 { public static void main(String[] argv) throws IOException { Scanner olvaso = new Scanner(new FileReader("adat.txt")); while(olvaso.hasNextLine()) { System.out.println(olvaso.nextLine()); } } }
import java.io.*; class readfile { public static void main(String[] argv) throws IOException { FileReader folyam = new FileReader("adat.txt"); BufferedReader fileolvaso = new BufferedReader(folyam); String sor = null; do { sor = fileolvaso.readLine(); System.out.println(sor); }while (sor != null); fileolvaso.close(); } }
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; class Program01 { public static void main(String[] args) throws FileNotFoundException { File f = new File("adat.txt"); Scanner bef = new Scanner(f); while(bef.hasNextLine()) { System.out.println(Integer.parseInt(bef.nextLine())); } } }
A kivételek kezelését sokan a úgy oldják meg, hogy a fájlkezelő utasításokat egy try..catch szerkezetbe ágyazzák. Például így:
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; class Program01 { public static void main(String[] args) { File f = new File("adat.txt"); try { Scanner fin = new Scanner(f); while(fin.hasNextLine()) { System.out.println(Integer.parseInt(fin.nextLine())); } } catch (FileNotFoundException ex) { ex.printStackTrace(); } } }
A kivétel elkapásának persze akkor van értelme, ha magunk akarunk valamilyen szöveges üzenetet megjeleníteni. Ekkor a szöveges üzenet a catch() { } blokkba kerül.
A fenti kivételkezeléses példában a fájlkezelő utasításokat a try..catch szerkezetbe ágyaztuk. Ez nem valami elegáns, ráadásul átláthatatlanná teszik a szépen megírt fájlkezelő blokkunkat. A következő példában a kivételt eldobjuk a fájlkezelő részben, és mellette létrehozunk egy hasonló nevű függvényt, amelynek a feladata csak a kivétel kezelése.
import java.io.FileNotFoundException; import java.io.File; import java.util.Scanner; public class FileBeolvas { public static void beolvas() { try { tryBeolvas(); }catch(FileNotFoundException ex) { System.err.println("A fájl nem található"); } } public static void tryBeolvas() throws FileNotFoundException { File f = new File("adat.txt"); Scanner olvaso = new Scanner(f); while(olvaso.hasNextLine()) { System.out.println(olvaso.nextLine()); } } public static void main(String[] args) { beolvas(); } }
Vegyük észre a fájlkezelő metódus, amelynek a neve beolvas() volt fentebb, most át lett nevezve tryBeolvas()-ra. A hibakezelő metódus kapta a beolvas() nevet. A hibakezelő metódusból hívjuk meg a tryBeolvas() metódust.
import java.io.*; class Program { public static void main(String args[]) throws IOException { FileWriter iro = new FileWriter("adat.txt", true); iro.write("joska:titok:gazdasag:Szolnok\n"); iro.flush(); iro.close(); System.out.println("Kiírva"); } }
A konstruktorban a második paraméter true, azt jelenti hozzáfűzünk az állományhoz. Ez a paraméter nem kötelező. Ha nem adjuk meg alapértelmezetten felülírjuk az állományt.
import java.io.*; class Program3 { public static void main(String args[]) throws IOException { FileWriter firo = new FileWriter("adat2.txt", true); BufferedWriter iro = new BufferedWriter(firo); iro.write("Valai"); iro.close(); firo.close(); System.out.println("Kiírva"); } }
import java.io.*; class Program4 { public static void main(String args[]) throws IOException { FileWriter firo = new FileWriter("adat2.txt", true); PrintWriter iro = new PrintWriter(firo); iro.println("Valai"); firo.close(); System.out.println("Kiírva"); } }
import java.io.*; public class ap { public static void main(String[] args) throws IOException { File f = new File("adat.txt"); FileWriter kifolyam = new FileWriter(f); // Ha hozzáfűzni akarunk akkor FileWriter(f, true); PrintWriter kimenet = new PrintWriter(kifolyam); kimenet.println("alma"); kimenet.println("körte"); kimenet.println("szilva"); kimenet.println("barack"); kimenet.close(); } }
import java.io.*; import java.util.*; public class ap { public static void main(String[] args) throws IOException { File f = new File("adat.txt"); FileReader bemenet_folyam = new FileReader(f); BufferedReader bemenet = new BufferedReader(bemenet_folyam); boolean vege = false; String s, gyumolcs; int sorszam, suly; while(!vege) { s = bemenet.readLine(); if (s != null) { StringTokenizer Tokenek = new StringTokenizer(s); sorszam = Integer.valueOf(Tokenek.nextToken()).intValue(); suly = Integer.valueOf(Tokenek.nextToken()).intValue(); gyumolcs = Tokenek.nextToken(); System.out.println(sorszam + " " + suly + " " + gyumolcs); } else vege = true; } bemenet.close(); } }
InputStream in = new FileInputStream("adat.txt"); Reader r = new InputStreamReader(in, "US-ASCII"); int intch; while ((intch = r.read()) != -1) { char ch = (char) intch; //... }
import java.io.*; import java.util.*; class Program { private static String fajlOlvas(String path) { File file = new File(path); Scanner olvaso = null; StringBuilder strb = new StringBuilder((int)file.length()); try { olvaso = new Scanner(file); } catch(IOException e) { e.printStackTrace(); } String sorTores = System.getProperty("line.separator"); try { while(olvaso.hasNextLine()) strb.append(olvaso.nextLine() + sorTores); return strb.toString(); } finally { olvaso.close(); } } public static void main(String[] args) { String str = fajlOlvas("adat.txt"); System.out.println(str.replace("m", "g")); } }
Egy rövid példa:
import java.util.Scanner; import java.io.File; import java.io.IOException; class Program { public static void main(String[] args) throws IOException { File file = new File("adat.txt"); Scanner olvaso = new Scanner(file); System.out.println(olvaso.nextLine()); System.out.println(olvaso.nextLine()); } }
Vegyük észre, hogy itt nem olvasunk a fájl végéig.
A fájl végéig olvasáshoz:
while(olvaso.hasNextLine()) strb.append(olvaso.nextLine() + sorTores);
import java.io.*; import java.util.*; class Program { private static String readFileAsString(String filePath) throws IOException { byte[] buffer = new byte[(int) new File(filePath).length()]; FileInputStream f = new FileInputStream(filePath); f.read(buffer); return new String(buffer); } public static void main(String[] args) throws IOException { String str = readFileAsString("adat.txt"); System.out.println(str); } }
Néhány megadható kódolás:
További kódokat, a java.nio.charset.Charset osztály dokumentációja biztosít.
UTF-8 kódolással, Linuxon és Windowson is helyesen látszanak az ékezetek.
Scanner nFile = new Scanner(new File(fileName), "UTF-8");
vagy:
try { String fileName = "adat.txt"; Reader r = null; try { InputStream in = new FileInputStream(fileName); //US-ASCII r = new InputStreamReader(in, "UTF-8"); } catch(UnsupportedEncodingException e) {} Scanner nFile = new Scanner(r); while(nFile.hasNextLine()) { String str = nFile.nextLine(); System.out.println(str); } nFile.close(); } catch(FileNotFoundException e) { System.err.println("Hiba a fájlból olvasás során"); }
Stream osztállyokkal:
import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.BufferedReader; class Program01 { public static void main(String args[]) throws IOException { OutputStreamWriter fout = new OutputStreamWriter(new FileOutputStream("adat.txt"), "UTF-8"); fout.write("almaáűé"); fout.flush(); fout.close(); System.out.println("Kiírva"); InputStreamReader fin = new InputStreamReader(new FileInputStream("adat.txt"), "UTF-8"); BufferedReader in = new BufferedReader(fin); System.out.println(in.readLine()); } }
Karakterkódolás a Scanner osztállyal:
import java.util.Scanner; import java.io.FileNotFoundException; import java.io.File; class Program01 { public static void main(String[] args) { Scanner nFile = null; try { nFile = new Scanner(new File("adat.txt"), "UTF-8"); } catch(FileNotFoundException ex) { System.err.println("Nemlétező fájl"); } String str = nFile.nextLine(); System.out.println(str); nFile.close(); } }
import java.io.BufferedOutputStream; import java.io.BufferedInputStream; import java.io.DataOutputStream; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.FileInputStream; class Program01 { public static void main(String[] argv) throws Exception { FileOutputStream fileOut = new FileOutputStream("data.txt"); BufferedOutputStream bufferOut = new BufferedOutputStream(fileOut); DataOutputStream dataOut = new DataOutputStream(bufferOut); dataOut.writeUTF("árvíztűrő"); dataOut.writeLong(34L); dataOut.writeInt(44); dataOut.writeDouble(32.343); dataOut.writeBoolean(true); dataOut.close(); bufferOut.close(); fileOut.close(); FileInputStream fileIn = new FileInputStream("data.txt"); BufferedInputStream bufferIn = new BufferedInputStream(fileIn); DataInputStream dataIn = new DataInputStream(bufferIn); System.out.println(dataIn.readUTF()); System.out.println(dataIn.readLong()); System.out.println(dataIn.readInt()); System.out.println(dataIn.readDouble()); System.out.println(dataIn.readBoolean()); dataIn.close(); bufferIn.close(); fileIn.close(); } }
A sorrendet tartani kell.
import java.io.*; class Program01 { public static void main(String args[]) throws IOException{ System.out.println("Hi"); RandomAccessFile file = new RandomAccessFile("adat.txt", "rw"); file.seek(12); file.write("Hello World".getBytes()); file.close(); } }
A seek() metódussal a 12-es helyre állítom a fájlmutatót. Ha üres a 12 pozíció előtt a fájl, akkor NUL értékekkel tölti fel.
import java.io.*; class Program01 { public void kiir() throws IOException { System.out.println("Kiírás"); RandomAccessFile file = new RandomAccessFile("adat.txt", "rw"); file.seek(20); file.writeUTF("alma"); file.seek(40); file.writeUTF("körte"); file.seek(60); file.writeUTF("barack"); file.seek(80); file.writeUTF("szilva"); file.close(); } public void olvas() throws IOException { RandomAccessFile file = new RandomAccessFile("adat.txt", "r"); file.seek(40); System.out.println(file.readUTF()); file.seek(60); System.out.println(file.readUTF()); file.close(); } public static void main(String args[]) throws IOException{ new Program04().kiir(); new Program04().olvas(); } }
Ellenőrizi szeretnénk, hogy valóban szabályosan valós szám lett beírva:
try { double a = be.nextDouble(); } catch (Exception e) { System.out.println("Nem valós szám!"); }
Ha nem így történt, hibaüzenetet küldünk.
Ügyeljünk arra, hogy a forrásban ugyan tizedes pontot használunk, de a bekérésnél tizedes vesszőt vár a java.
Ugyanez egész számmal:
try { int a = be.nextInt(); } catch (Exception e) { System.out.println("Nem egész szám!"); }
Teljes példa a Scanner osztály használatára:
import java.io.*; import java.util.*; class Tip { public static void main(String args[]) throws IOException { System.out.println("Típusellenőrzés"); Scanner be = new Scanner(System.in); System.out.print("Szám: "); try { int a = be.nextInt(); } catch (Exception e) { System.out.println("Nem egész szám"); } System.in.read(); } }
Teljes példa BufferedReader osztály használata esetén
import java.io.*; class Tip { public static void main(String args[]) throws IOException { System.out.println("Típusellenőrzés"); InputStreamReader befolyam = new InputStreamReader(System.in); BufferedReader be = new BufferedReader(befolyam); String s; int szam; System.out.print("Szám: "); s = be.readLine(); try { szam = Integer.valueOf(s).intValue(); } catch(Exception e) { System.out.println("Gond van konverzióval"); } System.in.read(); } }
Konverziónál, használhatjuk a NumberFormatException kivételt is:
try { szam = Integer.valueOf(s).intValue(); } catch(NumberFormatException e) { System.out.println("Gond van konverzióval"); }
import java.io.*; class Tipusv { public static void main(String args[]) throws IOException { System.out.println("Hi"); InputStreamReader befolyam = new InputStreamReader(System.in); BufferedReader be = new BufferedReader(befolyam); String s = be.readLine(); if (isInteger(s)) System.out.println("Egész szám"); else System.out.println("Nem egész szám"); System.in.read(); } static public boolean isInteger(String bemenet) { try { Integer.parseInt(bemenet); return true; } catch(Exception e) { return false; } } /* isInteger */ }
import java.io.*; class Tipusv { public static void main(String args[]) throws IOException { System.out.println("Hi"); InputStreamReader befolyam = new InputStreamReader(System.in); BufferedReader be = new BufferedReader(befolyam); String s = be.readLine(); if(s.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")) System.out.println("Szám"); else System.out.println("Ez nem szám"); System.in.read(); } }
Ez a kódrész elfogad előjeleket és tizedespontot is.
import java.io.*; import java.text.*; class Tipusv { public static void main(String args[]) throws IOException { System.out.println("Hi"); InputStreamReader befolyam = new InputStreamReader(System.in); BufferedReader be = new BufferedReader(befolyam); String s = be.readLine(); DecimalFormat df = new DecimalFormat("#%"); Number a = 0; try { a = df.parse(s); System.out.println("Szám: " + a.doubleValue()); } catch(Exception e) { System.out.println("Nem megfelelő formátum" ); } System.in.read(); } }
Példaformátum leírás:
"#,##0.00%"
"#,##0.00"
A Number típusú objektum metódusai.
byte | byteValue() | Az adott szám bájt értékével tér vissza |
abstract double | doubleValue() | Az adott számot doulbe-ként adja vissza |
abstract float | floatValue() | Az adott számot float-ként adja vissza |
abstract int | intValue() | Az adott számot int-ként adja vissza |
abstract long | longValue() | Az adott számot long-ként adja vissza |
short | shortValue() | Az adott számot short-ként adja vissza |
import java.io.*; import java.text.*; class Tipusv { public static void main(String args[]) throws IOException { System.out.println("Hi"); InputStreamReader befolyam = new InputStreamReader(System.in); BufferedReader be = new BufferedReader(befolyam); String s = be.readLine(); NumberFormat df = NumberFormat.getInstance(); Number a = 0; try { a = df.parse(s); System.out.println("Szám: " + a.doubleValue()); } catch(Exception e) { System.out.println("Nem megfelelő formátum" ); } System.in.read(); } }
Ha már nagyon sok utasításunk van, azokat csoportosítani szoktuk, adunk neki egy nevet, majd a nevével hivatkozva hívjuk meg az összes utasítást. Például szeretnénk egy névjegykártyát kiíratni, amelyen szerepel a nevünk, címünk, telefonszámunk, e-mail címünk, weblapunk.
class Program { static void nevjegy() { System.out.println("Nagy József"); System.out.println("Budapest"); System.out.println("Tél u. 3."); System.out.println("+36 (30) 123-4567"); System.out.println("nagy@valaholdomain.hu"); System.out.println("http://valaholdomain.hu"); } public static void main(String[] args) { nevjegy(); } }
A fenti példában a metódus fej része így néz ki:
static void nevjegy()
Néha a metódusainknak szeretnénk bemenő paramétereket megadni. Például, szeretnénk egy szám négyzetét venni. Ekkor a metódusnak paraméterkén megadhatjuk mi legyen ez a szám.
class Program { static void negyzet(double szam) { System.out.println(szam * szam); } public static void main(String[] args) { negyzet(3.5); } }
Előfordulhat, hogy a kapott számot nem képernyőre szeretném íratni, hanem szeretném azt megkapni, továbbszámolás céljára. Ekkor a metódust úgy kell megírni, hogy adja vissza a kért értéket. Maradva a fenti négyzetszámító programnál, alakítsuk úgy át a programot, hogy adja vissza az adott szám értékét.
class Program { static double negyzet(double szam) { return szam * szam; } public static void main(String[] args) { System.out.println(negyzet(3.5)+2); } }
Vegyük észre, hogy a metódusainkat az osztályon belül hoztuk létre, static kulcsszóval láttuk el, ennek hatására az osztály példányosítása nélkül tudjuk azokat használni.
A metódusoknak egész sorozatát hozhatjuk létre:
class Program { static double dupla(double szam) { return 2 * szam; } static double negyzet(double szam) { return szam * szam; } static double felez(double szam) { return szam / 2; } public static void main(String[] args) { System.out.println(Program.negyzet(3.0)); System.out.println(Program.dupla(3.0)); System.out.println(Program.felez(3.0)); } }
Az alábbi példában a metódust a static kulcsszó nélkül hozzuk létre. A használata ebben az esetben csak példányosítással lehetséges.
class Program { double negyzet(double szam) { return szam * szam; } public static void main(String[] args) { Program program = new Program(); System.out.println(program.negyzet(3.5)+2); } }
Metódusok egész sorozata:
class Program { double dupla(double szam) { return 2 * szam; } double negyzet(double szam) { return szam * szam; } double felez(double szam) { return szam / 2; } public static void main(String[] args) { Program program = new Program(); System.out.println(program.negyzet(3.0)); System.out.println(program.dupla(3.0)); System.out.println(program.felez(3.0)); } }
class Szamitas { double dupla(double szam) { return 2 * szam; } double negyzet(double szam) { return szam * szam; } double felez(double szam) { return szam / 2; } } class Program { public static void main(String[] args) { Szamitas szamitas = new Szamitas(); System.out.println(szamitas.negyzet(3.0)); System.out.println(szamitas.dupla(3.0)); System.out.println(szamitas.felez(3.0)); } }
Ha készítek egy metódust, a bemenő paramétereket formális paraméternek is nevezzük. Ezzel szemben az aktuális paraméter, a metódus hívásának helyén behelyettesített változók.
A Java nyelvben a paraméterek érték szerint kerülnek átadásra. Másként szólva, ha egy metóduson belül megváltoztatom egy formális paraméter értéket, ez nem érinti az aktuális paraméter értékét.
Ha nem alaptípusokat használunk paraméterként az átadás már nem érték szerint történik.
A következő példában egyszerű típust adunk át paraméterként:
class Program01 { public static void szamol(Integer szam) { szam = szam * 2; System.out.println(szam); } public static void main(String[] args) { Integer szam = 4; szamol(szam); System.out.println(szam); } }
Eredmény:
8 4
A következő példában referencia típus adunk át:
class Dolog { int szam = 1; } class Program01 { public static void szamol(Dolog dolog) { dolog.szam = dolog.szam * 2; System.out.println(dolog.szam); } public static void main(String[] args) { Dolog dolog = new Dolog(); dolog.szam = 4; szamol(dolog); System.out.println(dolog.szam); } }
Eredmény:
8 8
Az utóbbival egyező eredményt kapunk tömbökkel, mivel azok is referenciák:
class Program01 { public static void szamol(int[] t) { t[0] = t[0] * 2; System.out.println(t[0]); } public static void main(String[] args) { int[] t = new int[2]; t[0] = 4; t[1] = 10; szamol(t); System.out.println(t[0]); } }
Eredmény:
8 8
Ha már sok osztályunk van érdemes azokat külön állományban tárolnunk.
A következő két fájl egyszerűen egy könyvtárban használom.
class Program01 { public static void main(String args[]) { Program02 prog = new Program02(); prog.kiir(); } }
class Program02 { public void kiir() { System.out.println("Másik osztály"); } }
Ha még több saját osztályunk van azokat külön állományokba rakjuk és becsomagoljuk.
Abban a fájlban ahol az osztályaink el vannak helyezve, az állomány elején egy package Csomagnév; utasítást kell elhelyeznünk.
Egy osztály importálása egy csomagból az import utasítás után megadott csomagnév.Osztály; formában történhet. Ilyen formában:
import csomagnév.Osztály;
Ha „*” karaktert használunk, akkor a csomag összes osztályát használatba vettük.
Minden csomag számára saját könyvtárat kell létrehozni. A csomag osztályainak .class állományait ide be kell másolni.
import sajat.*; class Program01 { public static void main(String args[]) { Program02 ketto = new Program02(); ketto.kikuld(); Program03 harom = new Program03(); harom.kikuld(); } }
package sajat; public class Program02 { public void kikuld() { System.out.println("Második"); } }
package sajat; public class Program03 { public void kikuld() { System.out.println("Harmadik"); } }