Fájlkezelés, IO Kivételkezelés Belső osztályok 6. gyakorlat Fájlkezelés, IO Kivételkezelés Belső osztályok
Fájlkezelés, IO
Java IO adatfolyam alapú megközelítés (stream-ek) InputStream/OutputStream: byte-orientált IO InputStream: adatforrás-folyam OutputStream: adatnyelő-folyam Reader/Writer osztályok: karakter-orientált IO unicode támogatással konvertáló osztályok (pl. InputStreamReader)
Standard IO standard input: System.in standard output: System.out standard error: System.err a System.out és a System.err közvetlenül használhatók (ahogyan eddig is használtuk őket)
Importálás IO-hoz importálnunk kell: import java.io.*; amiket általában használunk belőle (az API- ban utánuk lehet nézni bővebben): BufferedReader InputStreamReader FileReader FileWriter
Billentyűzetről beolvasás BufferedReader: szöveget olvas a karakter input-streamről InputStreamReader: byte-okat olvas, majd karakterekké alakítja őket BufferedReader be = new BufferedReader(new InputStreamReader(System.in)); be.read(); be.readLine();
Billentyűzetről beolvasás read(): egyetlen karaktert olvas be, és az ASCII kódjával tér vissza readLine(): egy sort olvas be, és a beolvasott sztringgel tér vissza
Beolvasás fájlból FileReader: karakteres fájlokat olvas konstruktorában egy File objektumot vár readLine(): egy sort olvas be a fájlból BufferedReader be = new BufferedReader(new FileReader(new File(”fajlnev.txt”))); be.readLine();
Kiíratás fájlba FileWriter: karakteres fájlokat ír szintén át kell adnunk neki egy File objektumot FileWriter ki = new FileWriter(new File(”uj.txt”)); ki.write(”szöveg”); az IO műveletek végén a stream-eket zárjuk le! be.close(); ki.close();
Példaprogram Fajlkezeles.zip (honlapomon)
Kivételkezelés
Kivételkezelés fogalmai nem derül ki minden hiba a fordítás során kivétel: egy probléma, mely meggátolja a futást egy adott metódusban/blokkban pl. null referencia kivétel dobása: az aktuális program végrehajtása megáll, kivétel „dobódik” a kivételkezelő mechanizmus keres egy megfelelő kivételkezelőt a kivételkezelő lekezeli a hibát, a program futása folytatódik
Kivételkezelés fogalmai kivétel elkapása: ha valahol kivétel dobódik, akkor feltételezzük, hogy az valahol el lesz kapva védett régió: a kód azon része, mely kivételeket hozhat létre hibakezelő kód követi try{ … } catch{ … }
Kivételkezelés try { … } catch (NullPointerException e) { } „veszélyes kód”: kivételt dobhat mi történjen, ha elkaptuk a kivételt?
Exception osztály a kivételek mind az Exception osztályból származnak néhány példa kivételekre: ClassNotFoundException DataFormatException IOException SQLException ArithmeticException (pl. nullával osztás) ArrayIndexOutOfBoundsException (tömbindexelési hibák) FileNotFoundException RuntimeException …
Try, catch, finally több catch blokk is lehet } catch (ArithmeticException e){ … } catch (IOException e){ … } catch (Exception e){ … } finally { … } sorba nézzük a catch ágakat, mindegyiknél az adott hibát tudjuk elkapni amit a finally-ba írok, az mindenképpen lefut (függetlenül attól, dobódik-e kivétel vagy nem)
Try, catch, finally catch (Exception e): általános kivételelkapó a finally ág nem kötelező, de hasznos lehet stream-ek vagy kapcsolatok lezárásához, mert így mindenképpen lezárjuk őket pl. ki.close();
Runtime Exception azon kivételek őse, amiket a virtuális gép dobhat a normál működése közben ezen osztályból származó kivételeket nem feltétlen kell elkapni, mert ha bekövetkeznek, akkor se tudunk sok mindent kezdeni velünk (a program úgyis meghal) ilyen pl. a NullPointerException, ArrayIndexOutOfBoundsException
Throwable osztály az Object osztályból származik ez is két leszármazottja van: Exception: erről volt szó eddig Error: fordítási időbeni- és rendszerhibák, ezekkel általában nem kell foglalkozni
Throws kulcsszó ezzel jelzem, hogy valami (általában metódus) dobhat kivételt, viszont a kivételt nem kapom el (vagy máshol kapom el) public void beolvas() throws IOException{ } sok esetben le sem lehet fordítani a programot a throws nélkül
Saját kivétel létrehozása származtatni kell valamilyen létező kivétel osztályból public class SajatKivetel extends Exception{ public SajatKivetel(String message){ super(message); }
Throw kulcsszó kivételt dobhatunk vele (manuálisan) Pl.: if (x<0) throw new SajatKivetel(„X negatív.”); ne keverjük a throws kulcsszóval, ami annak jelzésére szolgál, hogy egy metódus milyen kivételt dobhat! ha saját kivételt dobunk, azt jeleznünk kell a „throws” kulcsszóval, vagy try-catch segítségével kell lekezelni ha egyiket se tesszük, fordítási hibát fogunk kapni
throws vs. throw public static void main(String args[]) throws SajatKivetel{ int a=3; int b=0; if(b==0) throw new SajatKivetel(„Nulla az osztó”); else System.out.println((float)a/b); } jelezzük, hogy dobhat ilyen kivételt b=0 esetén ténylegesen dobjuk is a kivételt
Példaprogramok SajatKivetel.java (pub, 8. gyakorlat) Hiba.java (pub, 8. gyakorlat)
Belső osztályok
Belső osztályok osztályon vagy metóduson belüli osztályok cél: máshol nem használt algoritmus teljes elrejtése a belső osztályból elérhetők a „körülvevő” osztály elemei kivéve ha a belső osztály static egy (nem belső) osztály láthatósága csak public vagy package private lehet, a belső osztály viszont ezen felül lehet private, protected, sőt static is nem kell őket külön fordítani
Példa belső osztályra osztályon belüli belső osztály: public class Kulso{ … private class Belso{…} }
Példa belső osztályra metóduson belüli belső osztály: public void csinalValamit(){ … private class Belso(){…} }
Belső osztály példányosítása a tartalmazón belül ugyanúgy, mint eddig a tartalmazón kívülről: Kulso.Belso peldany = new Kulso.Belso(); csak nemstatikus belső osztály esetén: Kulso peldanyKulso = new Kulso(); Kulso.Belso púeldanyBelso = peldanyKulso.new Belso();
Példaprogramok Lista.java (pub, 8. gyakorlat) Lmain.java (pub, 8. gyakorlat)
Gyakorló feladatok pub: 8. gyakorlathoz tartozó feladatok.txt
Szorgalmi feladat szerda éjfélig küldhető el 3 pluszpontért nekem e-mailben Feladat: Írj három saját hiba osztályt: mindegyik származzon az Exception osztályból, legyen default és paraméteres konsturktoruk is, ezekben az Exception osztály default, valamint az 1 db String argumentumot váró konstruktorát hívd meg az egyik az InvalidYearException osztály: a default konstruktorban az "Érvénytelen évszám!„ szöveget add át az ős konstruktorának, a paraméteresben értelemszerűen a kapott String típusú paramétert Legyen ugyanilyen módon létrehozva az InvalidCitizenshipException és a TooLongNameException osztály is (itt a default konstruktor a "Nem magyar állampolgár„ és a „Túl hosszú a név!” szövegeket adja át az ős konstruktorának) Mindhárom osztály kerüljön a kivetelkezeles, azon belül a sajatkivetelek csomagba
Szorgalmi feladat Írj egy Állampolgár osztályt, legyen a kivetelkezeles csomagban: adattagjai az adószám (egész), a név, az évszám (egész szám) és az állampolgárság (String, pl. „magyar”, „német”…) Írj hozzá paraméteres konstruktort, mely 4 paramétert vár. A konstruktorban ellenőrizd: hogy az évszám pozitív-e, ha nem, akkor dobj InvalidYearExceptiont hogy a név hossza nagyobb-e 35-nél, ha igen, akkor dobj TooLongNameExceptiont a következő szöveggel: "A név túl hosszú: x karakter. Maximum 35 karakter lehet.„ (x nyilván az aktuálisan átadott paraméter hossza) hogy az állampolgárság értéke a „magyar”-e, amennyiben nem, dobj InvalidCitizenshipExceptiont a következő szöveggel: "Hiba: az adatbázis csak magyar állampolgárságú személyek adatait tartalmazhatja!„ Írj hozzá getter-setter metódusokat, a fentebb említett ellenőrzések a megfelelő setterekben is történjenek meg, valamint a hibadobás is
Szorgalmi feladat A hibadobást jelezd a throws kulcsszó segítségével a megfelelő metódusok deklarációjában, a hibát elkapni az osztályban sehol sem kell Írj egy KivételPélda osztályt, legyen ez is a kivetelkezeles csomagban: Próbálj létrehozni állampolgár objektumokat, valamint a setterek segítségével átállítani az adattagjaikat (ez veszélyes kód, kezeld ennek megfelelően) A keletkező hibákat kapd el, és az e.printStackTrace() hívásával írasd ki a konzolra a megfelelő információkat a hibáról Ne felejtsd el importálni a saját hiba osztályaidat!