Tartalmi kivonat
Home Page Forrás: http://www.doksihu Java 1.1 Fakultatív tantárgy 1999. Tantárgyi tematika. Félévi követelmények Alapok String osztály, StringBuffer osztály, Csomagoló osztályok Matemetikai osztályok, Kollekciók Osztályok Kivételkezelés Interfészek Input/Output User interfesz Cikkek az INFOPEN magazinból A Jáva programozási nyelv A Jáva programozási nyelv rejtelmei Adatbázis-kezelés Jávában Hálózatkezelés Jávában Elosztott rendszerek programozása Jávában A CORBA technológia file:///E|/docs/Untitled/default.html (1 of 2)20040118 3:00:46 Home Page Forrás: http://www.doksihu Biztonságos-e a Jáva A Java platform file:///E|/docs/Untitled/default.html (2 of 2)20040118 3:00:46 Változók Alapok Tartalom: Egyszerû példa Egyszerû applet Változók Mûveletek Konstansok Megjegyzések Osztályok, objektumok Objektum felszabadítása Metódusok és paraméterezésük Karakterkészlet Változó deklaráció Tömbök Osztályok adattagjainak
kezdõértéke Program vezérlõ szerkezetek Egyszerû példa public class HelloVilag{ public static void main(String[] args){ System.outprintln("Helló világ!"); } } A progam önálló alkalmazás. A HelloVilagjava forrás file-ban kell elhelyezni javac HelloVilag.java java HelloVilag Egyszerû applet import java.awt*; file:///E|/docs/Untitled/Alapok.html (1 of 9)20040118 3:00:56 fordítás futtatás Változók import java.appletApplet; public class Viszlat extends Applet { public void paint(Graphics g) { g.drawRect(25, 2, 90, 25); g.drawString("Viszlát!", 50, 20); } } Appletként használjuk. HTML lap <APPLET> címkéjében hivatkozunk rá A WWW szerverrõl töltõdik le Az apple tfile neve: Viszlat.java A HTML file neve: Viszlat.html <HEAD><TITLE>Viszlát applet</TITLE></HEAD> <BODY> <APPLET CODE="Viszlat.class" WIDTH=200 HEIGHT=50> Ha nem mûködik az APPLET a WWW böngészõben, akkor ez jelenik meg
helyette. </APPLET> </BODY></HTML> Az appletviewer programmal is indíthatjuk a HTML lapot: appletviewer Viszlat.html Változók Primitív típus Érték Csomagoló osztály boolean true, false Boolean char 16 bit-es Unicode Character byte 8 bit-es elõjeles egész Byte short 16 bit-es elõjeles egész Short int 32 bit-es elõjeles egész Integer long 64 bit-es elõjeles egész Long file:///E|/docs/Untitled/Alapok.html (2 of 9)20040118 3:00:56 Változók float 32 bit-es lebegõpontos Float double 64 bit-es lebegõpontos Double Minden primitív típusnak van egy csomagoló (wrapper) osztálya, amely a példány váltózójában tárolja az értéket, vannak metódusai. Konstruktorral hozhatók létre. Ott használható jól, ahol egyébként csak objektumot lehet használni, pl vector, stack, object I/O, szerializáció, stb Mûveletek A Jáva nyelv operátorai precedenciájuk csökkenõ sorrendjében: ++ -! ~ 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 &= |= <<= >>= >>>= Konstansok class matek { final static double PI = 3.1415926; // konstans file:///E|/docs/Untitled/Alapok.html (3 of 9)20040118 3:00:56 Változók } final módosító: nem módosítható az értéke static módosító: osztály szintû változó, példányosítás nélkül is létezik Megjegyzések // a sor hátralévõ része megjegyzés /* . megjegyzés . */ Osztályok, objektumok class Konyv { public String cím; public int oldalszam; public static int konyvszam = 0; }
String osztály (metódusai vannak) Módosítók: public más osztályokból is látható módosító nélküli (félnyilvános) csak a saját csomag osztályiból látható protected csak a leszármazott osztályokból látható private csak a saját osztályból látható file:///E|/docs/Untitled/Alapok.html (4 of 9)20040118 3:00:56 Változók Osztály ---> Objektum példányosítás new operátorral Konyv k = new Konyv(); // létrehozza az objektumot és az erre mutató referenciát // k-ban helyezi el. A k Konyv osztályba tartozó változó. Konyv k1; // csak változó deklaráció k1 = new Konyv(); // példányosít, és a referenciát k1-ben tárolja null : nem létezõ objektum-referencia Ha valamilyen osztály típusú változó értéke null, akkor nem hivatkozik objektumra. Hivatkozás objektum adattagjaira: k.cím = "Egri csillagok"; // szöveg literálból a fordító létrehoz egy String // objektumot, és az erre mutató referenciát
tárolja // a változóban k.oldalszam = 150; Az egyszerû változókat (primitív típusokat érték szerint tárolja a Java, nem kell példányosító operátort használni. public static int konyvszam; // staic módosító miatt ez osztály szintû változó, // példényosítás nélkül is létezik. Akkor jön létre, amikor // elõszõr hivatkozunk rá, vagy az elsõ példányt // létrehozzuk. Az objektumok számától függetlenül csak // egyetlen változó létezik. Hivatkozás osztály szintû változóra: Konyv. konyvszam vagy k1. konyvszam file:///E|/docs/Untitled/Alapok.html (5 of 9)20040118 3:00:56 Változók Objektum felszabadítása k1 = null; k1 = k2; k1 = new Konyv(); Mindhárom módszerrel a k1-ben eredetileg hivatkozott objektum referencia nélkül marad. A Jáva szemétgyûjtõ mechanizmusa (garbage collector) szabadítja fel a memóriát, de nem lehet tudni, hogy mikor (pl. ha kevés a memória) Metódusok és paraméterezésük class Konyv { . public
String toString() { return cim + Integer.toString(oldalszam); // vagy return cím + oldalszam } } Metódus hívása: Systam.outprintln(k1toString()); Static metódus - Osztály metódus static int HanyKonyvemVan() { return konyvszam; // static metódus csak a static adattagokhoz férhet hozzá } Karakterkészlet Unicode: uhhhh hhhh hexadecimális szám Minden char típus ill. String karakterei Unicode-ban vannak tárolva file:///E|/docs/Untitled/Alapok.html (6 of 9)20040118 3:00:56 Változók Literálok: null true, false 'k', ' ', '\', ''', '"', 'u', 'uhhhh' "String" Változó deklaráció int x,y; int x, y= 3; // csak az y kap értéket!!! Tömbök Valódi tömb. Az index 0-val kezdõdik! int [] a; // a tömb deklarációja, tetszõleges elemszámú int tömb a = new int [20]; // helyfoglalás 20 elemû tömbnek a[0] = 3; // értékadás a tömb elsõ elemének a.length // a tömb
hosszát adja vissza Több dimenziós tömbök int [] [] a = new int [3] []; // Háromszög for (int i = 0; i < a.length; i++) { a[i] = new int[i+1]; for (int j = 0; j < a[i].length; j++) a[i] [j] = 0; } file:///E|/docs/Untitled/Alapok.html (7 of 9)20040118 3:00:56 Változók Osztályok adattagjainak kezdõértéke Az osztályok adattagjai példányosításkor az alábbi kezdõérétket veszik fel: boolean false char 'u0000' bytr, short, int, long 0 float, double 0.0 objektum null A metódusokban deklarált változók nem kapnak kezdõértéket automatikusan! Program vezérlõ szerkezetek Blokk: { } A belül deklarált változók lokálisak a blokkra nézve Elágazás: if (logikai kifejezés) utasítás else utasítás vagy if () { } else { } Összetett elágazás switch (egész kifejezés) { case címke1: file:///E|/docs/Untitled/Alapok.html (8 of 9)20040118 3:00:56 Változók utasítások break case címke2: case címke3: utasítások break
default: utasítások { Ciklusok: Elõltesztelõ: Hátultesztelõ: while (logikai kifejezés) utasítás; do . utasítások . while (logikai kifejezés) for utasítás for (kezdet; logikai kifejezés; továbblépés) utasítás; = break: kilépés a ciklusból vagy switch-bõl continue: ciklusmag további részének kihagyása return [kifejezés]: metódus végrehajtásának befejezése file:///E|/docs/Untitled/Alapok.html (9 of 9)20040118 3:00:56 kezdet; while (logikai kifejezés) { utastások; továbblépés; } String osztály Forrás: http://www.doksihu String osztály String konstruktorok String létrehozása String konverzió String-ek összehasonlítása String vizsgálat Keresés String-ben String módosítás StringBuffer osztály StringBuffer konstruktorai StringBuffer értékének változtatása StringBuffer egyéb metódusai StringTokenizer osztály StringTokenizer konstuktorok StringTokenizer metódusai Csomagoló osztályok (wrapper) Konstruktorok
Konverziók Példák String - primitív típus - csomagoló osztály típusok közötti konverziókra Metódusok paraméter átadás szabályai Példa a HashTable használatára String osztály A String objektum az Object osztály leszármazottja A String objektum értéke nem változtatható meg! Ha olyan mûveletet adunk meg, amely a String értékét megváltoztatja, új objektum keletkezik az új értékkel, a String referencia az új objektumra fog mutatni, a régi objektum pedig referencia nélkül marad file:///E|/docs/Untitled/String osztaly.html (1 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu (szemétgyûjtés) Pl. String s = "görög"; s = s + "dinnye"; Örökli az Object osztály toString() metódusát. Ezt hívja a Java, ha egy String típusú változó sztring reprezentációjára van szükség: System.outprintln(s); String konstruktorok String() String(String) String(StringBuffer) String(char[]) String(char[], int tól, int
ig) String(byte[], int u) // a Unicode felsõ byte-ja String(byte[], int u, int tól, int ig) String létrehozása String s = "görög"; // automatikusan String objektum keletkezik String z = new String("dinnye"); String y = "görög" + " " + "dinnye"; String x = "görög".concat("dinnye"); // a háttérben automatikusan egy String objektum keletkezik char [] c = {'A', 'B', 'C'}; String d = new String(c); byte [] e = {65, 66, 67}; String f = new String(e, 0); // 0 = a Unicode felsõ byte-ja String konverzió static String valueOf(x) // az alábbi típusokból String típus állítható elõ x: byte, short, int, long, float, double, char, char [], char [] int tól, int hossz, Object, boolean tpusú file:///E|/docs/Untitled/String osztaly.html (2 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu Pl. float f = (float)3.4567; // a konstans double típusú s =
String.valueOf(f); System.outprintln(s); short h = (short)30567; // a konstans int típusú s = String.valueOf(h); System.outprintln(s); System.outprintln(StringvalueOf(a)); static X X.valueOf(String) // Stringbõl csomagoló osztály állítható elõ X: Byte, Short, Integer, Long, Float, Double, Boolean Pl. Boolean bo = BooleanvalueOf("false"); char charAt(int index) char [] toCharArray() char [] c = "görögdinnye".toCharArray(); void getBytes(int tól, int ig, byte[] hova, int hányadiktól) void getChars(int tól, int ig, char[] hova, int hányadiktól) static String copyValueOf(char[], int tól, int ig) static String copyValueOf(char[]) String-ek összehasonlítása boolean equals(Object o) String a,b; if (a.equals(b)) boolean equalsIgnoreCase(String) int compareTo(String) int r = a. compareTo(b); r == 0: a és b azonos sztringek r < 0: a kisebb mint b r > 0: a nagyobb mint b file:///E|/docs/Untitled/String osztaly.html (3 of
12)20040118 3:00:56 String osztály Forrás: http://www.doksihu String vizsgálat boolean endsWith(String) boolean startsWith(String) boolean startsWith(String mivel, int honnantól) boolean azonos regionMatches(int tól, String, másik, int másikTól, int hossz) boolean azonos regionMatches(boolean ignoreCase, int tól, String, másik, int másikTól, int hossz) Keresés String-ben int holTalálható indexOf(String mit, int honnantól) int holTalálható lastIndexOf(String mit, int honnantól) Ha a keresett String nem található, az eredmény -1 String módosítás String concat(String) String replace(char ról, char ra) String trim() String toUpperCase() String toLowerCase() String substring(int tól, int ig) StringBuffer osztály Változtatható méretû sztringek tárolására használhatók. Van egy kezdeti kapacitása. Ha a karakterek már nem férnek bele, megnövekszik StringBuffer sb = new StringBuffer("görög"); sb.append("dinnye");
StringBuffer konstruktorai StringBuffer() StringBuffer(int kezdõBufferMéret) file:///E|/docs/Untitled/String osztaly.html (4 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu StringBuffer(String) StringBuffer értékének változtatása StringBuffer append(x) x: String, byte, short, int, long, float, double, char, char [], char [] int tól, int hossz, Object, boolean tpusú StringBuffer insert(int hova, x mit) x: String, byte, short, int, long, float, double, char, char [], Object, boolean tpusú StringBuffer reverse() void setCharAt(int hol, char mit) StringBuffer egyéb metódusai int capacity(x); // megadja a tároló kapacitását void ensureCapacity(int kívántKapacitás); charAt(int); void getChars(int tól, int ig, char [] hova, int honnantól) int length(); // a sztring mérete void setLength(int újMéret); StringTokenizer osztály A java.util csomagban található Implementálja az Enumeration interfészt. Karaktersztringet
szétdarabol bizonyos elválasztó karakterek (delimiterek) mentén Több delimiter is megadható, és ezek kombinációi szintén delimiterek. Pl: String s StringTokenizer st = new StringTokenizer("alma körte szilva narancs"); while (st.hasMoreTokens()) { file:///E|/docs/Untitled/String osztaly.html (5 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu s = st.nextToken(); System.outprintln(s); } StringTokenizer konstuktorok StringTokenizer(String szöveg) default delimiterek: " " StringTokenizer(String szöveg, String delimiterek) StringTokenizer(String szöveg, String delimiterek, boolean DelimIsToken) StringTokenizer metódusai int countTokens(); //hány token van még a Stringben boolean hasMoreTokens() String nextToken Csomagoló osztályok (wrapper) Primitív típus Érték Csomagoló osztály boolean true, false Boolean char 16 bit-es Unicode Character byte 8 bit-es elõjeles egész Byte short 16 bit-es elõjeles egész
Short int 32 bit-es elõjeles egész Integer long 64 bit-es elõjeles egész Long file:///E|/docs/Untitled/String osztaly.html (6 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu float 32 bit-es lebegõpontos Float double 64 bit-es lebegõpontos Double Minden primitív típusnak van egy csomagoló (wrapper) osztálya, amely a példány váltózójában tárolja az értéket, vannak metódusai. Konstruktorral hozhatók létre. Nem mindig használjuk a csomagoló osztályokat a sebesség miatt. Konstruktorok Float f = new Float(3.14); Float f = new Float("3.14"); // NumberFormatException kivétel váltódhat ki Konverziók Sztringbõl primitiv típus Xxxx.parseXxxx(String) metódusok Pl. int k = IntegerparseInt("89"); Sztringbõl csomagolóosztály Xxxx.valueOf(String) metódusok Pl.Integer i = IntegervalueOf("89"); Csomagolóosztályból primitív típus xxxxValue(Xxxx) metódusok Pl. Integer i = new Integer(3); int ii =
i.intValue(); Példák String - primitív típus - csomagoló osztály típusok közötti konverziókra public class Szamproba { public static void main(String[] args) { Integer i = new Integer(3); // konstruktor paraméter szám System.outprintln("Integer= " + i); file:///E|/docs/Untitled/String osztaly.html (7 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu Integer j = new Integer("67"); // konstruktor paraméter String System.outprintln("Integer= " + j); Double d = new Double(3.123456789); System.outprintln("Double= " + d); Double dd = new Double("3.123456789"); System.outprintln("Double= " + dd); // Sztringbõl primitiv típus int k = Integer.parseInt("89"); System.outprintln("int= " + k); float f = Float.parseFloat("456"); System.outprintln("float= " + f); // Csomagoló osztalyból az érték kinyerése int ii = i.intValue(); System.outprintln("int=
" + ii); float ff = i.floatValue(); System.outprintln("int= " + ff); // primitív típusból String String s = i.toString(); System.outprintln("String= " + s); // Csomagoló osztalyból String String z = dd.toString(); System.outprintln("String= " + z); Short h = Short.valueOf("13"); System.outprintln("Short= " + h); // Csomagoló osztály objektuma értékének megváltoztatása i = new Integer(7); System.outprintln("Integer= " + i); } } file:///E|/docs/Untitled/String osztaly.html (8 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu Metódusok paraméter átadás szabályai import corejava.*; import java.util*; /* A paraméter átadás érték szerint történik, ezért csak akkor változtatható meg a paraméter értéke, ha az átadott érték eleve referencia, és az érték megváltoztatása nem jár a referencia megváltozásával. Pl. String, Integer, Boolean, stb értéke nem változik (csak
lokálisan) Stringbuffer értéke megváltoztatható. Több elemei megváltoztathatók. */ public class param atadas { public static void main(String [] args) { int x = 1; String s = "Haho"; Integer i = new Integer(5); StringBuffer sb = new StringBuffer("Haha"); Alkalmazott a = new Alkalmazott(); System.outprintln(x + ", " + s + ", " + sb + ", " + i + ", " + a); Uj ertek(x, s, sb, i, a); System.outprintln(x + ", " + s + ", " + sb + ", " + i + ", " + a); System.outprintln(new Date()); float f = (float)3.4567; s = String.valueOf(f); System.outprintln(s); short h = (short)30567; s = String.valueOf(h); System.outprintln(s); // a konstans double típusú // primitív típusból String // primitív típusból String System.outprintln(StringvalueOf(a)); // objektumból String Boolean bo = Boolean.valueOf("false"); csomagoló osztály System.outprintln(bo); // String-böl //
StringTokenizer StringTokenizer st = new StringTokenizer("alma,körte,szilva, file:///E|/docs/Untitled/String osztaly.html (9 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu narancs", ",", true); while (st.hasMoreTokens()) { s = st.nextToken(); System.outprintln(s); } } private static void Uj ertek(int a, String b, StringBuffer c, Integer d, Alkalmazott e) { a = 2; b = "Haliho"; c.setLength(2); c.append("Hihihi12345678901234567890"); c.ensureCapacity(2000); System.outprintln("Kapacitas: " + ccapacity()); d = new Integer(7); e.nev = "Valaki"; } } class Alkalmazott { String nev = "Senki"; int kor = 1; public String toString() { return nev + ", " + kor; } } Példa a HashTable használatára import java.util*; public class HashPelda { public static void main(String args[]) { Hashtable s = new Hashtable(); float i = 3, j = 5; Float ii = new Float(i); Double jj = new Double(j); Float kk =
null; file:///E|/docs/Untitled/String osztaly.html (10 of 12)20040118 3:00:56 String osztály Forrás: http://www.doksihu String st; s.put("Három", ii); // public Object put(Object key, Object value); s.put("Öt", jj); System.outprintln("HashTábla mérete: " + s size()); // get() használatakor NullPointerException kivétel kiváltódhat kk = (Float)s.get("Három"); System.outprintln("Három értéke: " + kk floatValue()); try { kk = (Float)s.get("Négy"); System.outprintln("Három értéke: " + kk.floatValue()); } catch (NullPointerException ni) {System.outprintln("Nincs ilyen elem!");} // Keresés kulcs szerint st = "Öt"; //s.remove(st); if (s.containsKey(st)) System.outprintln(st + " benne van a Hashtáblában!"); else System.outprintln(st + " nincs benne van a Hashtáblában!"); // Keresés érték szerint st = "Három"; //s.remove(st); if (s.contains(ii))
System.outprintln(ii + " benne van a Hashtáblában!"); else System.outprintln(ii + " nincs benne van a Hashtáblában!"); // Összes elem végignézése Enumeration en = s.elements(); Felsorolás Object o = null; while (en.hasMoreElements()) { file:///E|/docs/Untitled/String osztaly.html (11 of 12)20040118 3:00:56 // String osztály Forrás: http://www.doksihu o = en.nextElement(); System.outprintln("Osztály tipus: " + o.getClass() + " Adat: " + o); } // Összes kulcs végignézése Enumeration kulcs = s.keys(); // Felsorolás while (kulcs.hasMoreElements()) { o = kulcs.nextElement(); System.outprintln("Osztály tipus: " + o.getClass() + " Adat: " + o); } // Tábla sorainak törlése s.clear(); } } file:///E|/docs/Untitled/String osztaly.html (12 of 12)20040118 3:00:56 Matematikai osztályok Forrás: http://www.doksihu Matematikai osztályok Math osztály Random osztály Kollekciók Vector Vector konstruktorai
Vector elemkezelése Vector metódusai Vector elemeinek számbavétele Vector egyéb metódusai Hashtable A Hashtable használata Hashtable konstruktorai Hashtable elemkezelése Hashtable elemeinek lekérdezése Hashtable metódusai Példa a vektorok használatára Példa a Hashtable használatára Matematikai osztályok Számokat képviselõ csomagoló osztályok Byte, Short, Integer, Long, Float, Double java.langMath java.utilRandom file:///E|/docs/Untitled/Mat.html (1 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu ArithmeticException egész számok esetén a 0-val osztás váltja ki valós számok esetén nem fordul elõ Float és Double osztályok konstansai: POSITIVE INFINITY 1.0/00 NEGATIVE INFINITY -1.0/00 NaN 0.0/00 A NaN == NaN false!, ezért a Float.isNaN() vagy a DoubleisNaN() metódusokat kell hsználni. Math osztály Minden metódusa static - utility osztály double d = Math.sqrt(20); Math objektumot nem lehet készíteni
Konstansok: E, PI Metódusok: abs(), acos(), asin(), atan(), atan2(), ceil(), cos(), exp(), floor(), log(), max(), min(), pow(), random, rint(), round(), sin(), sqrt(), tan() double random() a Random osztály nextDouble() metódusát használja Random osztály A java.util csomagban található A Math.random() is a Random osztályt használja Konstruktorok: file:///E|/docs/Untitled/Mat.html (2 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu Random() - a pillanatnyi idõt használja Random(long mag) - ha megismételhetõ véletlenszám sorozatot szeretnénk kapni Számgenerálás int nextInt() Integer.Min VALUE - MAX VALUE long nextLong() Long.Min VALUE - MAX VALUE float nextFloat 0.0f - 10f double nextDouble 0.0d - 10d Kollekciók Objektumokat tároló, dinamikusan bõvíthetõ, különféle visszakeresési módszert alkalmazó objektumok java.utilVector Olyan dinamikus tömb (lista), amely a kollekció objektumait rendezetten tárolja, és
rendezetten is adja vissza. Egy-egy objektum többször is elõfordulhat a vektorban java.utilHashtable Olyan szótár (dictionary) amely a kollekció objektumait kulcsértékkel tárolja, és a kulcsérték megadásával keresi ki. Egy-egy kulcs csak egyszer szerepelhet a táblában Vector A kollekció elemei Object objektumok, amelyeket elõvételkor típus kényszerítéssel (cast) kell átalakítani a konkrét típusra. Eközben ClassCastException kivétel váltódhat ki. Az elemeket Object [] tömbben tárolja. A vektorban tárolt tényleges objektumok típusa tetszõleges lehet. Pl. String s = "Erzsébet"; file:///E|/docs/Untitled/Mat.html (3 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu GregorianCalendar d = new GregorianCalendar(1978,11,17); Vector v = new Vector(); v.addElement(s); v.insertElementAt(d,0); Vector konstruktorai Vector() Vector(int kezdõKapacitás) Vector(int kezdõKapacitás, int növekmény) Vector
elemkezelése final void addElement(Object o) final void insertElementAt(Object o, int index) final void setElementAt(Object o, int index) final void removeElementAt(int index) final void removeAllElement() final boolean removeObject(Object o) // ha az objektum nem eleme a vektornak, false a visszaadott érték Vector metódusai Elemek közvetlen lekérdezése: final boolean contains(Object o) final Object elementAt(int index) // ArrayIndexOutOfBoundException kivételt válthat ki; Elemek indexe: 0 - size()-1 final Object firstElementAt() final int indexOf(Object o) // Ha az objektum többször is szerepel a vektorban, az elsõ indexét adja vissza final int lastIndexOf(Object o) // -1, ha nincs final Object lastElement() // Ha a vektor üres, null-t ad vissza final int size() // A vektor elemeinek száma Vector elemeinek számbavétele Egyszerû módszer for (int i = 0; i < v.size(); i++) { Xxxx o = (Xxxx)v.elementAt(i); file:///E|/docs/Untitled/Mat.html (4
of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu } final Enumeration elements() Enumeration e = v.elements(); while (e.hasMoreElements()) { Xxxx o = (Xxxx)e.nextElement(); } Az Enumeration a java.util interfésze Vector egyéb metódusai final int capacity() Object clone() // Valójában Vector-t ad vissza. Másolatot készít a vektorról, de az elemekrõl nem. final void copyInto(Object [] o) final void ensureCapacity(int minimumkapacitás) final boolean isEmpty() final void setSize(int újMéret) // az új méreten felüli elemeket törli final void trimToSize() // Újraméretezi a tömböt final String toString()// Az elemek sztring értékének konkatenációja Hashtable A kollekció elemei és a kulcsok Object objektumok. Az elemeket a HashtableEntry [] tömbben tárolja. Kulcsonként csak egy érték tárolható. Ha a put mûvelet során már létezõ kulcsú elemet adunk meg, az új érték a régi helyére kerül. A Hashtable
használata Hashtable bd = new Hashtable(); bd.put("Erzsébet", new GregorianCalendar(1978,11,17)); bd.put("Mónika", new GregorianCalendar(1965,1,12)); String ss = "Mónika születési éve: " + file:///E|/docs/Untitled/Mat.html (5 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu ((GregorianCalendar)bd.get("Mónika"))get (Calendar.YEAR); System.outprintln(ss); Az Object int hashCode() metódusát használja a kulcsok készítéséhez Hash kódok A String osztály feluldefiniálja a hashCode() metódust és a sztring alapján képez hash kódot, ezért az azonos sztringek azonos hash kódot eredményeznek. A hashCode()-ot implementáló osztályok: a primitív típusok csomagoló osztályai, String, Color, File, URL Hashtable konstruktorai Hashtable() Hashtable (int kezdõKapacitás) Hashtable (int kezdõKapacitás, float újra hash-elési küszöb)// újra hash-elési küszöb = 0.0f - 10f Hashtable
elemkezelése void clear() Object elõzõElem put(Object kulcs, Object elem) Object kulcs remove(Object kulcs) // null, ha nincs ilyen kulcs Object clone() // Hash objektumot ad vissza Hashtable elemeinek lekérdezése boolean contains(Object elem) boolean containsKey(Object kulcs) Object get(Object kulcs) boolean isEmpty() int size() String toString() Hashtable metódusai Elemek és kulcsok számbavétele: Enumeration elements() file:///E|/docs/Untitled/Mat.html (6 of 11)20040118 3:00:57 // null, ha nincs ilyen kulcs Matematikai osztályok Forrás: http://www.doksihu for (Enumeration e = bd.elements(); ehasMoreElements(); ) { GregorianCalendar d = (GregorianCalendar)e.nextElement(); } Enumeration keys() for (Enumeration e = bd.keys(); ehasMoreElements(); ) { String s = (String)e.nextElement(); } Példa a vektorok használatára import java.util*; public class Vektor pelda { public static void main(String[] args) { Alkalmazott a = new Alkalmazott("Kis
Kutya", 50000); Alkalmazott b = new Alkalmazott("Nagy Kutya", 100000); Alkalmazott c = new Alkalmazott("Kis Macska", 10000); Alkalmazott d = new Alkalmazott("Nagy Macska", 20000); Vector v = new Vector(); v.addElement(a); v.addElement(b); v.addElement(c); v.insertElementAt(d, 0); Vektor Kiir(v); v.removeElementAt(1); Vektor Kiir(v); Vector v1 = (Vector)v.clone(); Vektor Kiir(v1); v = null; Vektor Kiir(v1); file:///E|/docs/Untitled/Mat.html (7 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu a = null; b = null; Vektor Kiir(v1); System.outprintln( (v1contains(c)) ? "'c' benne van" : "'c' nincs benne" ); // Átmásoljuk az elemeket Hashtable-be Object o; Alkalmazott z; String s; Hashtable h = new Hashtable(); for (Enumeration e = v1.elements(); ehasMoreElements(); ) { z = (Alkalmazott)e.nextElement(); s = z.getnev(); o = h.put(s, z); } // Adott nevu alkalmazott adatainak kiírása a
Hashtable-ból z = (Alkalmazott)h.get("Kis Macska"); System.outprintln(z); } // Vector tartalmának kiírása public static void Vektor Kiir (Vector v) { Enumeration e = v.elements(); System.outprintln("A vektor elemeinek száma: " + vsize() + " "); System.outprintln("A vektor elemei:"); while (e.hasMoreElements()) { Alkalmazott o = (Alkalmazott)e.nextElement(); System.outprintln(o); } } } // -----------------------------------------------class Alkalmazott { private String nev; private int fizetes; public Alkalmazott (String nev, int fizetes) { this.nev = nev; this.fizetes = fizetes; file:///E|/docs/Untitled/Mat.html (8 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu } public String getnev() { return nev; } public String toString () { return "Név: " + nev + " Fizetés: " + fizetes; } } Példa a Hashtable használatára import java.util*; public class HashPelda { public static void main(String
args[]) { Hashtable s = new Hashtable(); float i = 3, j = 5; Float ii = new Float(i); Double jj = new Double(j); Float kk = null; String st; s.put("Három", ii); // public Object put(Object key, Object value); s.put("Öt", jj); System.outprintln("HashTábla mérete: " + ssize()); // get() használatakor NullPointerException kivétel kiváltódhat kk = (Float)s.get("Három"); System.outprintln("Három értéke: " + kkfloatValue()); try { kk = (Float)s.get("Négy"); System.outprintln("Három értéke: " + kkfloatValue()); } catch (NullPointerException ni) {System.outprintln("Nincs ilyen elem!");} // Keresés kulcs szerint st = "Öt"; //s.remove(st); file:///E|/docs/Untitled/Mat.html (9 of 11)20040118 3:00:57 Matematikai osztályok Forrás: http://www.doksihu if (s.containsKey(st)) System.outprintln(st + " benne van a Hashtáblában!"); else System.outprintln(st + " nincs benne van
a Hashtáblában!"); // Keresés érték szerint st = "Három"; //s.remove(st); if (s.contains(ii)) System.outprintln(ii + " benne van a Hashtáblában!"); else System.outprintln(ii + " nincs benne van a Hashtáblában!"); // Összes elem végignézése Enumeration en = s.elements(); // Felsorolás Object o = null; while (en.hasMoreElements()) { o = en.nextElement(); System.outprintln("Osztály tipus: " + ogetClass() + " Adat: " + o); } // Összes kulcs végignézése Enumeration kulcs = s.keys(); // Felsorolás while (kulcs.hasMoreElements()) { o = kulcs.nextElement(); System.outprintln("Osztály tipus: " + ogetClass() + " Adat: " + o); } // Tábla sorainak törlése s.clear(); // Hashtable bd = new Hashtable(); bd.put("Erzsébet", new GregorianCalendar(1978,11,17)); bd.put("Mónika", new GregorianCalendar(1965,1,12)); String ss = "Mónika születési éve: " +
((GregorianCalendar)bd.get("Mónika"))get(CalendarYEAR); System.outprintln(ss); } } file:///E|/docs/Untitled/Mat.html (10 of 11)20040118 3:00:57 Java http://www.doksihu programozás Forrás: Osztályok Tartalom Egyszerû példa Példányváltozók Metódusok Fordítás közbeni adatfolyam ellenõrzés Objektumok használata Hozzáférési kategóriák Statikus tagok Fõprogram Konstruktorok Inicializáló blokkok Destruktor jellegû metódusok Öröklõdés Polimorfizmus Osztálymetódusok elfedése Az osztályhierarchia Absztrakt osztályok és metódusok Végleges osztályok és metódusok Példányváltozók és metódusok leírása. Az osztály példányosításával keletkezik az objektum, egyed vagy példány. Az adatokat és az õket kezelo mûveleteket egységbe zárjuk. Az adatokat elrejthetjük más osztályok mûveletei elõl (adatelrejtés). Egyszerû példa //-----------------------------------------------public class Alkalmazott {
file:///E|/docs/Untitled/Osztalyok.html (1 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: // Az osztály tagjai: adattagok és metódusok // A class elott módosítók szerepelhetnek String nev; int fizetes; void fizetesDuplaz() { fizetes *=2; } void fizetesEmel(int nov) { fizetes += nov; } } Alkalmazott alk; alk = new Alkalmazott(); konstruktor meghívásával alk.nev = "Harapós Kutya"; példányváltozókra alk.fizetes = 30000; // Deklaráció // Példányosítás a // Hivatkozás a alk.fizetesDuplaz(); // Metódus meghívása // ------------------------------------------------------------------ Példányváltozók Változók deklarációja int fizetes= 30000, potlekok, levonasok = fizetes/5; // inicializálni lehet a példányváltozókat final double ADOKULCS = 20; // A final módosítóval konstanst hozunk létre. Változók használata Az osztály metódusaiban az adattagokra a nevükkel hivatkozunk
file:///E|/docs/Untitled/Osztalyok.html (2 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: Más objektum adattagjára minõsített névvel hivatkothatunk: masik.fizetes Pl. Az alkalmazott osztályban definiált tobbetKeresMint metódus: boolean tobbetKeresMint(Alkalmazott masik) { return fizetes > masik.fizetes; } Metódusok Metódusok definíciója Fej + törzs Fej: visszatérés típusa( ha nincs akkor void), név, formális paraméterek. Metódus szignatúrája: név és a formális paraméterek listája típusokkal és sorrendhelyesen Metódus név elõtt módosítók lehetnek: public , protected, private, abstract. Pl. boolean kozepesJovedelmu (int minimum, int maximum) { return fizetes >= minimum && fizetes < maximum; } Formális paraméterek: lokális változók (érték paraméterek) (final módosító használható) Minden paraméternek külön kell megadni a típusát. Paraméterlista lehet üres is, () akkor is kell. Ha nincs
visszatérési típus, a void szót kell a metódus név elé tenni. Metódusok meghívása Mindig konkrét példányra hívjuk meg. alk.fizetesDuplaz(); A metóduson belül minõsítés nélkül hívhatjuk meg az osztály metódusait: void automatikusFizetesEmel() { if (kozepesJovedelmu(30000, 60000)) file:///E|/docs/Untitled/Osztalyok.html (3 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: fizetesEme;(5000); } A this pszeudováltozó Metódustörzsben az aktuális objektumra a this pszeudováltozóval hivatkozhatunk. Metódusnevek túlterhelése Több azonos nevû metódus is írhatunk az osztály definíción belül, de ezeknek szignatúrájukban különbözniük kell. Ezt a metódus nevek túlterhelésének nevezzük class Alkalmazott { . . void fezetesEmel(int nov) { fizetes += nov; } void fezetesEmel() { fizetes += 5000; } void fezetesEmel(Alkalmazott masik) { if (kevesebbetKeresMint(masik)) fizetes = masik.fizetes; } } Alkalmazott a = new
Alkalmazott(), b = new Alkalmazott(); a.fezetesEmel(5000); a.fezetesEmel(); a.fezetesEmel(b); file:///E|/docs/Untitled/Osztalyok.html (4 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: Fordítás közbeni adatfolyam ellenõrzés A példányváltozók mindig kapnak kezdõértéket, de a metódusok lokális változóiv nem feltétlenül, ezért a fordító program ellenõrzi, hogy adtunk-e kezdoértéket. A nem void típusú metódusokban értékkel bíró return utasítást kell elhelyezni. Ha a fordító számára nem egyértelmû a kezdõértékek megadása, hibát jelez, ekkor explicite meg kell adni. Objektumok használata Az objektum a példányosítással születik meg. Alkalmazott a = new Alkalmazott(); konstruktor // new után Az 'a' referencia az objektumra (referencia típusú változó). Több változó is mutathat ugyanarra az objektumra: Alkalmazott a, b; a = new Alkalmazot(); b = a; a.fizetes = 50000; System.outprintln(bfizetes); ki!
// 50000 -t ír Objektumok paraméterként való átadásakor az objektumra 2 referencia van. A formális paraméter referenciája az eljárásból kilépéskor megszûnik. Ha egy változó nem mutat objektumra, a referenciája: null. Ha az objektumra nincs szükségünk, null-ra állítjuk, vagy más értéket adunk neki. Magát az objektumot a szemétgyûjtõ mechanizmus (garbage collector) szabadítja fel. Hozzáférési kategóriák Az adattagok és metódusok elérhetõsége szabályozható. Félnyilvános tagok file:///E|/docs/Untitled/Osztalyok.html (5 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: A jelöletlen tagokat (adat és metódus) félnyilvános tagoknak nevezzük. Ezekre csak az azonos csomagban lévõ osztályokból hivatkozhatunk. Nyilvános tagok (public) A public módosítóval ellátott tagokra bármely osztályból hivatkozhatunk. Ha egy adattagot csak olvasni engedünk meg a csomagon kívûlrõl, az adattagot privatenak jelöljük,
és egy public metóduson keresztül tesszük az adatot hozzáférhetõvé a csomagon kívûlrõl. Privát tagok (private) A private adattagok csak a példánymetódusokból érhetok el. A private metódusok is csak az osztályból érhetõk el. Leszármazottban hozzáférhetõ tagok (protected) Lásd az öröklõdésnél. Statikus tagok Az osztály egészére vonatkozó változókat osztályváltozóknak, a metódusokat pedig osztálymetódusoknak nevezzük. Ezeket a static módosító jelöli. Osztályváltozók Egyetlen példányhoz sem kötõdnek. Csak 1 létezik belõlük public class Alkalmazott { . static int nyugdijKorhatar = 62; // Osztályváltozó int eletkor; . int hatraVan() { return nyugdijKorhatar - eletkor; } } Alkalmazott a = new Alkalmazott(); a.nyugdijKorhatar = 65; Alkalmazott.nyugdijKorhatar = 65 file:///E|/docs/Untitled/Osztalyok.html (6 of 15)20040118 3:00:58 // helyes // ez is helyes Java http://www.doksihu programozás Forrás: Osztálymetódusok
Osztálymetódus csak az osztályváltozókhoz férhet hozzá, a példányváltozókhoz nem! static void nyugdijKorhatarEmel() { nyugdijKorhatar++; } Hívása: a.nyugdijKorhatarEmel(); Alkalmazott.nyugdijKorhatarEmel(); Foprogram public class paramKiir { public static void main(String [] args) { if (args.length > 0) { System.outprintln("Program paraméterek:"); for (int i= 1; i<args.length; i++) System.outprintln(args[i]); } else { System.outprintln("Nincsenek program paraméterek!"); } } } Konstruktorok Példányosításkor fut le. Ha nem készítünk konstruktort, akkor is van ún implicit konstruktor. Konstruktorok definíciója: Majdnem olyan, mint egy metódus definíció. Az azonosító kötött, nincs visszatérési típus (void sincs). Csak hozzáférési file:///E|/docs/Untitled/Osztalyok.html (7 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: módosító használható. Pl. public class Alkalmazott { . public Alkalmazott
(String nev, int fizetes) { this.nev = nev; this.fizetes = fizetes; } public Alkalmazott (String nev) { this.nev = nev; this.fizetes = 20000; } } Az aktuális paraméterek típusa határozza meg, hogy melyik konstruktort kell hívni. Pl. konstruktorból hívható egy másik konstruktor: public Alkalmazott (String nev) { this(nev, 20000); } Példányosítás paraméterekkel Csak olyan paraméter listát adhatunk át a konstruktornak, amelynek megfelelõ konstruktort készítettünk. Ha nem írtunk konstruktort, csak paraméter nélkülit használhatunk. Ha nem írtunk paraméter nélküli konstruktort, csak paraméterezettet hívhatunk. Alkalmazott a = new Alkalmazott("Kis Kutya", 50000); Alkalmazott b = new Alkalmazott("Nagy Kutya"); file:///E|/docs/Untitled/Osztalyok.html (8 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: Inicializáló blokkok A változódeklaráció és a metódusdefiníció közé tehetõ. Lehetnek
osztályinicializátorok és példányinicializátorok. Az osztályinicializátor az osztály szintû konstruktort pótolja (mivel ilyen nincs). Példa az osztályinicializátorra: public class Alkalmazott { . static int[] evesSzabadsag = new int [60]; static { for (int i= 0; i<30; i++) evesSzabadsag[i] = 15; for (int i= 30; i<40; i++) evesSzabadsag[i] = evesSzabadsag[i-1] + 1; for (int i= 40; i<50; i++) evesSzabadsag[i] = evesSzabadsag[i-1] + 2 ; for (int i= 50; i<60; i++) evesSzabadsag[i] = evesSzabadsag[i-1] + 1; } . public int evesSzabadsag() { if (eletkor < 60) return evesSzabadsag[eletkor]; else return evesSzabadsag[59]; } } Destruktor jellegû metódusok Az objektumok megszûnésekor a szemétgyûjtõ felszabadítja a lefoglalt helyet, de lehet, hogy bizonyos feladatokat el kell végezni elotte. Erre való a finalize metódus Ez az õsosztály (object) metódusa. Az adott osztályban csak felûldefiniáljuk: protected void finalize() throws Throwable (
file:///E|/docs/Untitled/Osztalyok.html (9 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: . } A tárterület felszabadítása elott hívódik meg, de nem lehet tudni, hogy mikor! A finalize metódus osztály színtû megfelelõje a classFinalize: static void classFinalize() throws Throwable ( . } Öröklõdés Objektumorientáció lényege : egységbe zárás (adatabsztrakció), öröklõdés, polimorfizmus. Osztály kiegészítése új tagokkal. Egy létezõ osztály kiterjesztése: új változók, új metódusok bevezetése. Pl. a Fonok osztály bevezetése az Alkalmazott osztály kiterjesztésével A Fonok osztály rendelkezik mindazon adatokkal és mûveletekkel, amellyel az Alkalmazott osztály, csak kiegészül új adatokkal és mûveletekkel. public class Fonok extends Alkalmazott { final int MAXBEOSZT = 20; Alkalmazott [] beosztottak = new Alkalmazott[MAXBEOSZT]; int beosztottakSzama = 0; public void ujBeosztott(Alkalmazott b) (
beosztottak[beosztottakSzama++] = b; ) } Szülõ ossztály: Alkalmazott (Os) Gyermek ossztály: Fonok (Leszármazott) A gyermek rendelkezik a szülõ adattagjaival is, azonban ha azok private típusúak, akkor a gyermek csak az örökölt metódusok segítségével érheti el õket, ha azok nem private-ok. A metódusok öröklése révén kódmegosztás jön létre a szülõ és a gyermek között. file:///E|/docs/Untitled/Osztalyok.html (10 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: A konstruktotrok és az öröklõdés A konstruktorokat a gyermek nem örökli. Ha nem írunk a gyermekhez új konstruktort, a szülõé hajtódik végre. Ha írunk, és nem hívjuk meg explicite a szülõ valamelyik konstruktorát, a szülõ argumentum nélküli konstruktora meghívódik. public class Fonok extends Alkalmazott { . public Fonok(String nev, int fizetes) { super(nev, fizetes); // a szülo kiválasztott konstruktorának végrehajtása } public Fonok(String nev) {
this(nev, 50000); konstruktorának végrehajtása } } // a Fonok másik A szülõ konstruktorának meghívása megelõzi a gyermek példány változóinak inicializálását, és az inicializáló blokk végrehajtását. Polimorfizmus A gyermek õseinek minden változójával és metódusával rendelkezik. Ezért minden olyan környezetben használható, ahol az õsei használhatók. Egy Alkalmazott típusú változónak értékül adható egy Fonok típusú objektum. Azt a lehetõséget, hogy egy adott típusú változó nemcsak szigorúan a típusának megfelelõ, hanem a leszármazott objektumokra is hivatkozhat, polimorfizmusnak (sokalakúság) nevezzük. A változóknak így van statikus és dinamikus típusa. A statikus típus a deklarált típus, a dinamikus, pedig a változó által hivatkozott objektum tényleges típusa. A változó dinamikus típusa a program során változhat A polimorfizmus igazi erejét a metódusok felüldefiniálásának lehetõsége adja.
file:///E|/docs/Untitled/Osztalyok.html (11 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: Példánymetódusok felüldefiniálása: A leszármazottakban szükség lehet bizonyos metódusok átírására, mivel lehet, hogy valamit máshogyan kell csinálni, mint az õs példányban. Pl. Az Alkalmazott osztályban és a leszármazottaiban van egy potlek metódus, amely a fizetés kiegészítéseket határozza meg: public class Alkalmazott { . int nyelvekSzama; . public int potlek() { return nyelvekSzama*5000; } public int fizetesPotlekokkal () { return fizetes() + potlek(); } } public class Fonok extends Alkalmazott { . public int potlek() { return super.potlek() + beosztottakSzama +1000; } } A Fonok osztály felüldefiniál egy példánymetódust. Oszálymetódusokat nem lehet felüldefiniálni, csak átfedni. A gyermek a super minosítõvel hivatkozhat a szülõ eredeti metódusaira. A super.potlek() az Alkalmazott osztály potlek metódusát hívja A
polimorfizmus tulajdonsága, hogy mindig a dinamikus típus szerinti metódus lesz meghívva. Alkalmazott a = new Fonok("Kovács János"); int p, fp; . p = a.potlek(); file:///E|/docs/Untitled/Osztalyok.html (12 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: fp = a.fizetesPotlekokkal(); // az örökölt fizetesPotlekokkal() metódust hívja, ez azonban a // Fonok potlek() metódusát hívja. Adinamikus kötés lehetõvé teszi, hogy a statikus típustól függetlenül, mindig a megfelelõ metódus fusson le. Osztálymetódusok elfedése Osztálymetódust nem lehet felüldefiniálni, csak elfedni. Osztálymetódus elfedi az õsökben deklarált, vele megegyezõ szignatúrájú metódusokat. Az osztálymetódusok hívása nem dinamikus, hanem statikus kötés szerint történik. Változók elfedése Az osztály kiterjesztésekor az õsökben deklarált példány- vagy osztályváltózókat elfedhetjük, azonos nevû változókkal. A gyermek csak
minõsítéssel férhet hozzá az elfedett változókhoz. A protected hozzáférési kategória Az õsök public tagjaihoz a leszármazott ugyanúgy hozzáférhet, mint minden más osztály. Az örökölt félnyilvános tagokhoz a gyermek csak akkor férhet hozzá, ha az ossel azonos csomagba tartozik. A private tagok el vannka zárva a leszármazottak elõl. A protected tagokhoz hozzáférhetnek az azonos csomagban definiált osztályok. Más csomagból csak a leszármazott osztályok férhetnek hozzá a protected tagokhoz. Az osztályhierarchia Az osztályok rokonsági viszonyainak összességét osztályhierarchiának nevezzük. A java.langObject osztály implicit módon minden más osztálynak szülõje, amely nem más osztályból származik, vagyis amelynek definíciójában nem adtuk meg az extends tagot. Közvetve minden osztály az Object leszármazottja Az Object osztály azokat a metódusokat tartalmazza, amelynekkel minden osztálynak rendelkeznie kell.
file:///E|/docs/Untitled/Osztalyok.html (13 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: Absztrakt osztályok és metódusok Az osztályhierarchia tetejét alkotó osztályoknak inkább az a szerepük, hogy definiáljanak egy metódus készletet, amelyek a leszármazottakat egysége keretbe foglalják. Ezek többnyire csak specifikálják a metódusokat, de nem implementálják azokat. Az ilyen osztályokat absztrakt osztályoknak nevezzük. Ezek tartalmaznak implementáció nélküli metódusokat. Az absztakt osztályok nem példányosíthatók Az absztakt osztályok absztrakt metódusai kiterjesztéskor juthatnak implementációhoz. Az absztakt osztályok annak ellenére, hogy nem példányosíthatók, lehetséges absztrakt típusú változókat deklarálni. Az ilyen változók mutathatnak a leszármazottak objektumaira. public abstract class Sikidom { public abstract double kerulet(); public abstract double terulet(); } public class Kor extends Sikidom {
public double r; public double kerulet() { return 2*Math.PI*r; } public double terulet() { return r*rMath.PI; } } public class Teglalap extends Sikidom { public double a, b; public double kerulet() { return 2*ab; } file:///E|/docs/Untitled/Osztalyok.html (14 of 15)20040118 3:00:58 Java http://www.doksihu programozás Forrás: public double terulet() { return a*b; } } Végleges osztályok és metódusok Ha nem akarjuk, hogy egy osztály kiterjeszthetõ, vagy egy metódus felüldefiniálható legyen, a final módosítót használjuk. file:///E|/docs/Untitled/Osztalyok.html (15 of 15)20040118 3:00:58 A Java kivételkezelése A Java kivételkezelése A Java hibakezelése a kivétekezelésen alapszik (Exception) A kivétel kezelése A kivétel keletkezésének módjai Megfelelõ kivételkezelõ keresése Hibakezelés A try { } blokk végrehajtásának esetei A kivételkezelés alkalmazási köre A kivételek specifikálása Kivételosztályok 1. Példa 2. Példa 3. Példa 4.
Példa 5. Példa 6. Példa A Java kivételkezelése A program futása közben fellépõ hibákat kezelni kell: a programot olyan állapotba kell hozni, hogy folytatható legyen, vagy a kilépés elõtt a tisztessséges befejezés érdekében néhány dolgot el kell végezni A Java hibakezelése a kivétekezelésen alapszik (Exception) A kivétel olyan esemény, amely megszakítja a program normális futását, és kivételes módon fut tovább. A kivételt okozhat pl.: indexhatárt túllépjük, háttértároló megtelik, illegális konverziót hajtunk végre, verem megtelik, stb A kivételek kezelése is az osztályokon alapul. Ez a hiba típusától függõ feldolgozást tesz lehetõvé, de a nyelvi elemek szempontjából a kivétel tartalma közömbös. A kivétel kezelése file:///E|/docs/Untitled/Kivetelkezeles.html (1 of 12)20040118 3:00:58 A Java kivételkezelése Hiba keletkezésekor egy kivétel objektum jön létre, amely információt tartalmaz a kivétel
fajtájáról és a program állapotáról. Ezután ez az objektum a Java futtató környezet felügyelete alá kerül, vagyis az a metódus, amelyben a hiba keletkezett, kiváltja a kivételt: throwing exception (kivétel kiváltása) A kivétel keletkezésének módjai 1. Futás közben rendellenes dolog történik (osztás 0-val) 2. A program egy throw utasítása váltja ki a kivételt (lehet a könyvtári csomagban vagy a saját osztályainkban) 3. Aszinkron kivétel lép fel Ha a program több szálon fut, és egy szál mûködése megszakad Az 1. bárhol, 2 és 3 a programnak csak meghatározott helyén léphet fel Ha egy metódus kiváltja az eseményt, a futása megszakad, és a vezérlés nem tér vissza a hiba keletkezésének helyére. Megfelelõ kivételkezelõ keresése A kivétel kiváltása után a JVM olyan helyet keres a programban, ahol a kivétel kezelése megtörténhet. A kivételt az a kivételkezelõ kódblokk fogja lekezelni, amelynek a hatókörében
keletkezett, és amely megfelelõ típusú. A kivételkezelõ megfelelõ típusú, ha az általa kezelt kivétel típusa azonos a kiváltott kivétel típusával vagy õse annak. A kivételkezelõ hatókörét a programozó határozza meg. file:///E|/docs/Untitled/Kivetelkezeles.html (2 of 12)20040118 3:00:58 A Java kivételkezelése file:///E|/docs/Untitled/Kivetelkezeles.html (3 of 12)20040118 3:00:58 A Java kivételkezelése Hibakezelés 1. A kivételkezelõ hatókörében hiba lép fel, és keletkezik egy, a hibának megfelelõ típusú kivételobjektum (Ez a kivétel kiváltása) 2. A Java virtuális gép (JVM) megkeresi a megfelelõ kivételkezelõt: elõször megnézi, hogy a kiváltott kivétel típusa azonos-e vagy leszármazottja a kivétel típus1-nek. Ha igen, akkor az ehhez tartozó kivételkezelõ blokk kapja meg a vezérlést. ha nem, akkor a kivétel típus2-vel majd kivétel típus3-mal próbálkozik. 3. A kivételkezelõ blokk végrehajtása után
végrehajtja a finally blokk utasításait (ha van ilyen) 4. A program a catch, finally blokkok utáni utasítással folytatódik A try { } blokk végrehajtásának esetei 1. Nem lép fel hiba A finally blokk ekkor is végrehajtódik (ha van) 2. Hiba lép fel, és valamelyik catch ág lekezeli a hibát Ezután a finally blokk végrehajtódik (ha van) 3. Hiba lép fel, de nincs alkalmas kivételkezelõ A finally blokk végrehajtódik, majd a hívó metódus kivételkezelõjánek adódik át a vezérlés file:///E|/docs/Untitled/Kivetelkezeles.html (4 of 12)20040118 3:00:58 A Java kivételkezelése file:///E|/docs/Untitled/Kivetelkezeles.html (5 of 12)20040118 3:00:58 A Java kivételkezelése A kivételkezelés alkalmazási köre 1. A Java nyelvnek sok kivételtípusa van: pl ArrayIndexOutOfBoundException, NumberFormatException 2. A programozó saját típusokat hozhat létre A kivételek alapvetõen 2 csoportba oszthatók: 1. Ellenõrzött kivételek 2. Nem ellenõrzött
kivételek Az ellenõrzött kivételeket: 1. Elkapni, vagy 2. Specifikálni kell, máskülönben fordítási hiba lép fel. Azért vannak nem ellenõrzött kivételek is, mert vannak olyan hibák, amelyek szinte bárhol felléphetnek, kezelésük a Java nyelven belül lehetetlen. Ez csak gondot okozna a programozóknak. A kivételek specifikálása Az olyan ellenõrzött kivételeket, amelyeket a metódusban nem kapunk el, specifikálni kell: a metódus fejében ezeket felsoroljuk, jelezve, hogy a metódus hívásakor fel kell készülni ezek elkapására. Pl. metódus () throws kivétel1, kivétel 2, { metódus törzs } Kivételek hiba keletkezésekor váltódnak ki, vagy throw utasítással is kiválthatók! Kivételosztályok java.lang Throwable a kiváltható osztályok hierarchiájának csúcsa. Ez, és ennek a leszármazottjai a throw utasítással kiválthatók. file:///E|/docs/Untitled/Kivetelkezeles.html (6 of 12)20040118 3:00:58 A Java kivételkezelése
java.langError komoly hiba esetén lép fel. Pl OutOfMemoryError (elfogyott a mermória). Ritkán fordulnak elõ. Több leszármazottja van. Az Error leszármazottjai nem ellenõrzött kivételek. java.langException Ez, és ezek leszármazottai ellenõrzött kivételek (a RunTimeException kivételével). A program teljes hibakezelését lényegében az Exception és leszármazottai segítségével oldjuk meg. A saját kivétel osztályinkat is az Exception-ból célszerû származtatni. 1. Példa public class Kivetel1 { public static void main(String [] args) { int i=0, db=0, j=0; byte max= 5; String [] tk = {"12", "34", "a56", "78", "90", "123"}; Integer [] egesz = new Integer[max]; db = max; for (j=0; j<db; j++) { System.outprintln(tk[j]); } //---------------------------------// A string tomb adatait integer tipusu tömbbe teszi // Nem ellenorzött kivéteelek: NumberFormatException, NullPointerException //
elkapásuk, vagy specifikálásuk nem kötelezo! for (j=0; j<db; j++) { try { file:///E|/docs/Untitled/Kivetelkezeles.html (7 of 12)20040118 3:00:58 A Java kivételkezelése egesz[j] = new Integer(tk[j]); } catch (NumberFormatException nf) {System.outprintln(j+1 + " adat hibas: " + tk[j]);} } // Kiirjuk az egesz tomb tartalmat for (j=0; j<db; j++) { try { System.outprintln(egesz[j]floatValue()); } catch (NullPointerException np) {System.outprintln(j+1 + " elem nem létezik!");} } } } 2. Példa public class Kivetel2 { public static void main(String [] args) { int i=0, db=0, j=0; byte max= 5; String [] tk = {"12", "34", "a56", "78", "90", "123"}; Integer [] egesz = new Integer[max]; db = max; for (j=0; j<db; j++) { System.outprintln(tk[j]); } //---------------------------------// A string tomb adatait integer tipusu tombbe teszi // Kiirjuk az egesz tömb tartalmat // Nem ellenorzött kivétel:
NumberFormatException // elkapásuk, vagy specifikálásuk nem kötelezo! try { for (j=0; j<db+2; j++) { try { egesz[j] = new Integer(tk[j]); System.outprintln(egesz[j]floatValue()); // System.outprintln(new Integer(tk[j])floatValue()); } catch (NumberFormatException nf) {System.outprintln(j+1 + " adat hibas: " + tk[j]);} } file:///E|/docs/Untitled/Kivetelkezeles.html (8 of 12)20040118 3:00:58 A Java kivételkezelése } catch (ArrayIndexOutOfBoundsException tulcsordul) {System.outprintln(" Tomb megtelt"); } } } 3. Példa import java.io*; public class Kivetel3 { public static void main(String [] args) { int i=0, db=0, j=0; byte max= 5; String [] tk = {"12", "34", "a56", "78", "90", "123"}; Integer [] egesz = new Integer[max]; db = max; for (j=0; j<db; j++) { System.outprintln(tk[j]); } FileWriter f = null; PrintWriter g = null; // Beolvasott adatokat file-ba menti try { f = new
FileWriter("adat.txt"); // IOException-t el kell kapni, vagy specifikálni g = new PrintWriter(f, true); for (j=0; j<db; j++) { g.println(tk[j]); // throw new IOException(); } } catch (IOException io) {System.outprintln(io+" hiba"); } finally {g.close();} } } 4. Példa import java.io*; file:///E|/docs/Untitled/Kivetelkezeles.html (9 of 12)20040118 3:00:58 A Java kivételkezelése public class Kivetel4 { public static void main(String [] args) { int i=0, db=0, j=0; byte max= 5; String [] tk = {"12", "34", "a56", "78", "90", "123"}; db = max; for (j=0; j<db; j++) { System.outprintln(tk[j]); } FileWriter f = null; PrintWriter g = null; // Beolvasott adatokat file-ba menti try { f = new FileWriter("adat.txt"); // IOException-t el kell kapni, vagy specifikálni g = new PrintWriter(f, true); kiir(db, g, tk); } catch (IOException io) {System.outprintln(io+" hiba"); } finally
{g.close();} } // ---------------------------------------static void kiir (int db, PrintWriter g, String [] tk) throws IOException { for (int j=0; j<db; j++) { g.println(tk[j]); throw new IOException(); } } } 5. Példa class MyException extends Exception { public MyException(String s) { super(s); } } //-----------------------------------------class Kivetel5 { file:///E|/docs/Untitled/Kivetelkezeles.html (10 of 12)20040118 3:00:58 A Java kivételkezelése static int dobo(String s) throws MyException { try { if (s.equals("osztas")) { int i = 0; return i/i; } if (s.equals("null")) { s = null; return s.length(); } if (s.equals("teszt")) { throw new MyException("Teszt üzenet"); } return 0; } finally { System.outprintln("[dobo("" + s +"") vége]"); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { try { dobo(args[i]); System.outprintln("Teszt "" +
args[i]+"" nem váltott ki kivételt"); } catch (Exception e) { System.outprintln("Teszt "" + args[i] + "" kiváltott egy kivételt: " + egetClass()+" " + egetMessage() + " üzenettel"); } } } } 6. Példa class VeremMegteltException extends Exception { public int egesz; public VeremMegteltException(int egesz) { this.egesz = egesz; } } // -------------------------------------------class verem { final static int MERET = 3; file:///E|/docs/Untitled/Kivetelkezeles.html (11 of 12)20040118 3:00:58 A Java kivételkezelése int mutato = 0; // mutato a következo szabad helyre mutat int [] verem = new int [MERET]; void betesz(int egesz) throws VeremMegteltException { if (mutato < MERET) { verem[mutato++] = egesz; } else { throw new VeremMegteltException(egesz); } } } // -------------------------------------------public class Kivetel6 { public static void main(String [] args) { // egészeket fogunk a verembe tenni verem v
= new verem(); try { v.betesz(1); v.betesz(2); v.betesz(3); v.betesz(4); } catch (VeremMegteltException vm) {System.outprintln(vmegesz + " nem fér a verembe!");} for (int i=0; i<v.mutato; i++) System.outprintln(vverem[i]); } } file:///E|/docs/Untitled/Kivetelkezeles.html (12 of 12)20040118 3:00:58 A Java kivételkezelése Forrás: http://www.doksihu Interfészek (Interface) Az interfészek közötti öröklõdés int elemek rendezése float elemek rendezése Interfészek implementálása Interfész használata deklarációban Interfész deklarációja Interfész módosítók Interfész törzs Absztrakt metódusok Példa az interfészek kiterjesztésére Példák int elemek rendezése float elemek rendezése Rendezés típus ellenõrzéssel 1. Rendez + összead Rendezés típus ellenõrzéssel 2. Interfészek (Interface) A Java nyelv egy fontos eleme, amely nem része az osztályoknak az interfész (interface). Interfész = új referencia típus, amely absztrakt
metódusok és konstansok deklarációjának összessége. Különbség az osztályokhoz képest, hogy hiányoznak a valódi, változtatható adattagok és a metódusok implementációi. Az interfész tehát egy felületet definiál. Ez egy új absztakciós szint bevezetését jelenti A feladat megoldásának bizonyos szintjén el lehet vonatkoztatni a konkrét implementációtól. Ez növeli a megbízhatóságot, könnyíti a tervezést, könnyebb újrafelhesználható programokat (osztályokat) készíteni. Az interfészt implementációján keresztül használjuk. file:///E|/docs/Untitled/Interfeszek.html (1 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu Egy osztály implementál egy interfészt, ha annak az összes metódusát implementálja. Minden olyan helyen, ahol interfész szerepel típusként, az interfészt implementáló bármilyen osztály példánya felhesználható. Az interfészek közötti öröklõdés Az interfészek között is
létrehozható szülõ-gyermek kapcsolat, ezt kiterjesztésnek nevezzük. Interfészek között többszörös öröklõdés (kiterjesztés) is lehetséges (ellentétben az osztályokkal). Az interfészeknek nincs közös õsinterfésze, mint az osztályoknak az object. Két példa: int elemek rendezése float elemek rendezése Nézzük meg, mit kell átalakítani? Interfészek implementálása class osztálynév [extends õsosztály] implements interfész1, interfész2,* { adattagok konstruktorok metódusok interfész metódusainak implementációja (a metódus feje megegyezik az interfészben deklarálttal) } * a többszörös "öröklést" valósítja meg file:///E|/docs/Untitled/Interfeszek.html (2 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu Az összes absztrakt metódust implementálni kell! Interfész használata deklarációban Az interfésznév szerepelhet deklarációban, formális paraméterként. A változónév olyan
referenciát jelent, amely az interfészt implementáló osztály valamelyik példányára mutat. Interfész deklarációja [interfész módosítók] interface interfésznév [kiterjesztett interfészek] { konstansok deklarációi absztrakt metódusok (csak a metódus fejfe!) } Az interfész neve lehetõleg -ható, -hetõ -re végzõdjön, jelezve, hogy az interfész képes megvalósítani a nevében jelzett mûveletet. Az -able végzõdésû nevek interfészt jelölnek. Interfész módosítók abstract (alapértelmezett, nem kell használni) public ( az interfész más csomagból is elérhetõ) Interfész törzs konstans definíciók metódus deklarációk // implicit publikus // implicit publikus file:///E|/docs/Untitled/Interfeszek.html (3 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu Konstansok: [módosítók] típus azonosító inicialzáló módosítók: alapértelmezés = public, static, final típus: létezõ típus. Pl char [] c =
{'a', 'b', 'c', 'd'} Absztrakt metódusok Olyan, mint az osztály metódusainak deklarációja törzs nélkül: [módosítók] visszatérési típus metódusnév() [kiváltható kivételek] metódus módosítók: public, abstract // nem kell megadni Példa az interfészek kiterjesztésére interface Gyumolcs { void egyedMeg(int i); } interface Alma extends Gyumolcs{ int színe(); void színÁllít(int i); } interface Korte { int mérete(); void méretÁllít(int i); } class Jonatan implements Alma { int szín; public void színÁllít(int i) { szín=i; } public int színe() { return szín; } public void egyedMeg(int i) { System.outprintln("Finom volt"); file:///E|/docs/Untitled/Interfeszek.html (4 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu } } class VilmosKorte implements Korte { int méret; public void méretÁllít(int i) { méret=i; } public int mérete() { return méret; } } public class Teszt {
public static void main(String args[]){ Alma b; b=new Jonatan(); b.színÁllít(5); System.outprintln(bszíne()); b.egyedMeg(3); } } int elemek rendezése // Egészek rendezése //-----------------------------------// File: Rendezheto2.java public interface Rendezheto2 { boolean kisebbMint(Rendezheto2 s); } //-----------------------------------// File: Rendez2.java // Rendez2 osztály újrafelhasználható public class Rendez2 { public static void rend(Rendezheto2 [] tomb) { int n = tomb.length; int i, j; Rendezheto2 temp; for (i=0; i<n; i++) { file:///E|/docs/Untitled/Interfeszek.html (5 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu for (j=i+1; j<n; j++) { if (tomb[j].kisebbMint(tomb[i])) { temp = tomb[i]; tomb[i] = tomb[j]; tomb[j] = temp; } } } } } //-----------------------------------// File: RendezTeszt2.java class RendezTeszt2 { public static void main(String [] args) { EgeszRendez [] in = new EgeszRendez[6]; in[0] = new EgeszRendez(7);
in[1] = new EgeszRendez(9); in[2] = new EgeszRendez(4); in[3] = new EgeszRendez(8); in[4] = new EgeszRendez(1); in[5] = new EgeszRendez(5); Rendez2.rend(in); // Rendezés meghívása for (int i=0; i<in.length; i++) System.outprintln(in[i]); } } // Interfész implementálása class EgeszRendez implements Rendezheto2 { int tetel; public EgeszRendez(int elem) { tetel = elem; } public boolean kisebbMint(Rendezheto2 elem){ // Interfész metódusának implementálása return tetel < ((EgeszRendez)elem).tetel; } public String toString() { return "" + tetel; file:///E|/docs/Untitled/Interfeszek.html (6 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu } } //------------------------------------ float elemek rendezése // Valós számok rendezése //-----------------------------------// File: Rendezheto2.java public interface Rendezheto2 { boolean kisebbMint(Rendezheto2 s); } //-----------------------------------// File: Rendez2.java // Rendez2
osztály újrafelhasználható public class Rendez2 { public static void rend(Rendezheto2 [] tomb) { int n = tomb.length; int i, j; Rendezheto2 temp; for (i=0; i<n; i++) { for (j=i+1; j<n; j++) { if (tomb[j].kisebbMint(tomb[i])) { temp = tomb[i]; tomb[i] = tomb[j]; tomb[j] = temp; } } } } } //-----------------------------------// File: RendezTeszt3.java class RendezTeszt3 { public static void main(String [] args) { file:///E|/docs/Untitled/Interfeszek.html (7 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu FloatRendez [] in = new FloatRendez[6]; in[0] = new FloatRendez(7); in[1] = new FloatRendez(9); in[2] = new FloatRendez(4); in[3] = new FloatRendez(8); in[4] = new FloatRendez(1); in[5] = new FloatRendez(5); Rendez2.rend(in); // Rendezés meghívása for (int i=0; i<in.length; i++) System.outprintln(in[i]); } } // Interfész implementálása class FloatRendez implements Rendezheto2 { float tetel; public FloatRendez(float elem) { tetel = elem; }
public boolean kisebbMint(Rendezheto2 elem){ // Interfész metódusának implementálása return tetel < ((FloatRendez)elem).tetel; } public String toString() { return "" + tetel; } } //------------------------------------ Rendezés típus ellenõrzéssel 1. //-----------------------------------// File: ErvenytelenTipusException.java public class ErvenytelenTipusException extends Exception{ public ErvenytelenTipusException(String s) { super(s); } } file:///E|/docs/Untitled/Interfeszek.html (8 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu //-----------------------------------// File: Rendezheto.java public interface Rendezheto { boolean kisebbMint(Rendezheto s) throws ErvenytelenTipusException; } //-----------------------------------// File: Rendez.java public class Rendez { public static void rend(Rendezheto [] tomb) throws ErvenytelenTipusException { int n = tomb.length; int i, j; Rendezheto temp; for (i=0; i<n; i++) { for (j=i+1;
j<n; j++) { if (tomb[j].kisebbMint(tomb[i])) { temp = tomb[i]; tomb[i] = tomb[j]; tomb[j] = temp; } } } } } //-----------------------------------// File: RendezTeszt1.java class RendezTeszt1 { public static void main(String [] args) { EgeszRendez [] in = new EgeszRendez[6]; in[0] = new EgeszRendez(7); in[1] = new EgeszRendez(9); in[2] = new EgeszRendez(4); in[3] = new EgeszRendez(8); in[4] = new EgeszRendez(1); in[5] = new EgeszRendez(5); try { Rendez.rend(in); } catch (ErvenytelenTipusException et) {System.outprintln("Hibás típus: " + et); } for (int i=0; i<in.length; i++) System.outprintln(in[i]); file:///E|/docs/Untitled/Interfeszek.html (9 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu } } class EgeszRendez implements Rendezheto { int tetel; public EgeszRendez(int elem) { tetel = elem; } public boolean kisebbMint(Rendezheto elem) throws ErvenytelenTipusException { if (elem instanceof EgeszRendez) return tetel <
((EgeszRendez)elem).tetel; else throw new ErvenytelenTipusException(elem.toString()); } public String toString() { return "" + tetel; } } //------------------------------------ Rendez + összead // Az interfészben van egy 'átalakít' metódus, amely az összegzéshez // double típusúvá alakítja az elem típusát // File: Rendezheto4.java public interface Rendezheto4 { boolean kisebbMint(Rendezheto4 s); double atalakit(); } //-----------------------------------// File: Rendez4.java public class Rendez4 { public static void rend(Rendezheto4 [] tomb) { int n = tomb.length; int i, j; Rendezheto4 temp; file:///E|/docs/Untitled/Interfeszek.html (10 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu for (i=0; i<n; i++) { for (j=i+1; j<n; j++) { if (tomb[j].kisebbMint(tomb[i])) { temp = tomb[i]; tomb[i] = tomb[j]; tomb[j] = temp; } } } } } //-----------------------------------// File: Osszead4.java public class Osszead4 { public
static double Osszead(Rendezheto4 [] tomb) { int n = tomb.length; int i; double temp = 0.0; for (i=0; i<n; i++) temp += tomb[i].atalakit(); return temp; } } //-----------------------------------// File: RendezTeszt4.java class RendezTeszt4 { public static void main(String [] args) { FloatRendez [] in = new FloatRendez[6]; in[0] = new FloatRendez(7); in[1] = new FloatRendez(9); in[2] = new FloatRendez(4); in[3] = new FloatRendez(8); in[4] = new FloatRendez(1); in[5] = new FloatRendez(5); Rendez4.rend(in); for (int i=0; i<in.length; i++) System.outprintln(in[i]); double sum = 0; sum = Osszead4.Osszead(in); System.outprintln("Összeg: " + sum); file:///E|/docs/Untitled/Interfeszek.html (11 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu } } //----------------------------------------class FloatRendez implements Rendezheto4 { float tetel; public FloatRendez(float elem) { tetel = elem; } public boolean kisebbMint(Rendezheto4 elem){ return tetel
< ((FloatRendez)elem).tetel; } public double atalakit(){ return (double)tetel; } public String toString() { return "" + tetel; } } //------------------------------------ Rendezés típus ellenõrzéssel 2. // Az implementáló osztály egyben kiterjeszt egy másik osztályt //-----------------------------------// File: ErvenytelenTipusException.java public class ErvenytelenTipusException extends Exception{ public ErvenytelenTipusException(String s) { super(s); } } //-----------------------------------// File: Rendezheto.java public interface Rendezheto { boolean kisebbMint(Rendezheto s) throws ErvenytelenTipusException; file:///E|/docs/Untitled/Interfeszek.html (12 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu } //-----------------------------------// File: Rendez.java public class Rendez { public static void rend(Rendezheto [] tomb) throws ErvenytelenTipusException { int n = tomb.length; int i, j; Rendezheto temp; for (i=0; i<n; i++) {
for (j=i+1; j<n; j++) { if (tomb[j].kisebbMint(tomb[i])) { temp = tomb[i]; tomb[i] = tomb[j]; tomb[j] = temp; } } } } } //-----------------------------------// File: RendezTeszt.java class RendezTeszt { public static void main(String [] args) { EgeszRendez [] in = new EgeszRendez[6]; in[0] = new EgeszRendez(7); in[1] = new EgeszRendez(9); in[2] = new EgeszRendez(4); in[3] = new EgeszRendez(8); in[4] = new EgeszRendez(1); in[5] = new EgeszRendez(5); try { Rendez.rend(in); } catch (ErvenytelenTipusException et) {System.outprintln("Hibás típus: " + et); } for (int i=0; i<in.length; i++) System.outprintln(in[i]); } } class Egesz { public int tetel; public Egesz(int e) { file:///E|/docs/Untitled/Interfeszek.html (13 of 14)20040118 3:00:59 A Java kivételkezelése Forrás: http://www.doksihu tetel = e; } } class EgeszRendez extends Egesz implements Rendezheto { public EgeszRendez(int elem) { super(elem); } public boolean kisebbMint(Rendezheto elem) throws
ErvenytelenTipusException { if (elem instanceof EgeszRendez) return tetel < ((EgeszRendez)elem).tetel; else throw new ErvenytelenTipusException(elem.toString()); } public String toString() { return "" + tetel; } } //------------------------------------ file:///E|/docs/Untitled/Interfeszek.html (14 of 14)20040118 3:00:59 Java Input/Output Forrás: http://www.doksihu Java Input/Output Csatornák Karakter szervezésû Byte szervezésû Csatorna megnyitása és lezárása Kiíró mûveletek Olvasó mûveletek Leképzés fizikai adatszerkezetre File-ok Csövek Byte- és karaktertömbök, sztringek Szûrõk Adattípus értéke beolvasása és kiírása Véletlen elérésû file-ok (RandomAccessFile) Kapcsolat a file rendszerrel (File osztály) Példák Példa1 N egész szám kiirása Random file-ba A Java.io csomag Java Input/Output A Bemenet/Kimenet a Stream (csatorna) fogalmához kapcsolódik. A csatorna olyan adatsorozat, amelyet feldolgozhatunk olvasó
mûveletekkel, vagy elõállít–hatunk író mûveletekkel. Lényegében szekvenciális Input/Output. A csatorna egy absztrakciós szint. amely a bemenet/kimenet kezelését függetleníti az operációs rendszertõl, az eszközöktõl, amelyen az adatokat tároljuk (bill., képernyõ, file-ok, párhuzamos szálak közti csõcsatorna) Témák: file:///E|/docs/Untitled/Input Output.html (1 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu Csatornák Leképzés fizikai adatszerkezetre Szûrõk Véletlen elérésû file-ok Kapcsolat a file rendszerrel Kivétel kezelése Csatornák 1. Byte szervezésûek (legkisebb egység a byte) Az osztályok az InputStream és az OutputStream absztrakt osztályok leszármazottai. Pl.: OutputStream: public void write(byte b []) throws IOException 2. Karakter szervezésûek (karakterek, sztringek) (legkisebb egység a Unicode char) Az osztályok az Reader és a Writer absztrakt osztályok leszármazottai. Pl.: Writer: public
void write(char c []) throws IOException Csatorna megnyitása és lezárása Megnyitás: csatorna objektum létrehozása konstruktorral. Írás/Olvasás: a csatorna objektumon kell végrehajtani. Lezárás: a csatorna objektum close() metódusával. Pl.: import java.io*; FileWriter fout = new FileWriter("adat.txt"); // megnyitás // Kiírás fout.close(); // lezárás Kiíró mûveletek Karakter csatornára (OutputStreamWriter) write(int c) throws IOException write(char c [], int off, int len) throws IOException write(String s, int off, int len) throws IOException write(char c []) throws IOException rite(String s) throws IOException Byte csatornára (Output Stream) absztrakt file:///E|/docs/Untitled/Input Output.html (2 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu write(int b) throws IOException (absztrakt) write(byte b[]) throws IOException write(byte b[], int off, int len) throws IOException Kivételek: IOException NullPointerException
ArrayIndexOutOfBoundException Olvasó mûveletek Karakter csatornára (Reader) ■ int read() throws IOException // 1 karakter beolvasása, blokkolódik,ha nincs //karakter a csatornán; -1, ha csatorna vége int read (char c []) throws IOException int read (char c [], int off, int len) throws IOException Byte csatornára (InputStream) int read() throws IOException // 1 byte beolvasása (absztrakt) int read (byte b []) throws IOException int read (byte c [], int off, int len) throws IOException Üres csatorna: Nem tartalmaz adatot. Ha beolvasás közben a csatorna kiürül, a read blokkolódik, amíg adat érkezik Végetért csatorna A csatorna vége jelet tartalmazza. Pl.: public static void masol (InputStream in, OutputStream out) throws IOException { int b; while (b = in.read() != -1) outwrite(b); out.flush(); } Leképzés fizikai adatszerkezetre file:///E|/docs/Untitled/Input Output.html (3 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu File-ok (pl.:
FileInputStream) Csövek (pl.:, PipedInputStream, PipedOutputStream) Byte- és karaktertömbök, sztringek (pl.: CharArrayWriter) File-ok Karaktercsatorna: FileReader, FileWriter Byte csatorna: FileInputStream, FileOutputStream Konstuktor pl. FileReader(String file név) throws FileNotFoundException FileReader(File file) throws FileNotFoundException FileReader(FileDescriptor fd) Csövek Szálak közti kommunikáció megszervezésére való. PipedInputStream - PipedOutputStream vagy PipedReader - PipedWriter összekapcsolásával jön létre A csõcsatorna összekapcsolását a bemenet és a kimenet is kezdeményezheti! Pl.: PipedInputStream in = new PipedInputStream(out); // a bemeneti csatorna rákapcsolódik a kimeneti catornára // a kimeneti csatornát elõbb létre kell hozni Byte- és karaktertömbök, sztringek byte[] és char[] típusú objektumok adják a csatorna fizikai reprezentációját. Byte csatorna felett létrehozott karakter csatornák Az InputStreamReader és az
osztélyok OutputStreamWriter byte csatorna felett vannak definiálva. Olvasáskor, íráskor a byte-ok automatikusan Unicode-dá (és viszont) konvertálódnak. A konstruktor paramétere dönti el, hogy milyen szabvány szerint kell a konverziót elvégezni. Pl.: Billentyûzetrõl olvasunk WindowsEE/ISO Latin-2 karaktereket: InputStreamReader in = new InputStreamReader(System.in, "Cp1250"); A File Reader és a FileWriter a fenti osztályok leszármazottai ugyanúgy byte csatorna felett vannak definiálva, de a konstruktoruknak nem adható meg, hogy milyen kódolást használjanak. Az op rendszer alapértelmezett kódolását használja. file:///E|/docs/Untitled/Input Output.html (4 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu Szûrõk Az osztályai nem azt írják le, hogy honnan olvasunk, vagy hová írunk, hanem azt, hogy ezt hogyan csináljuk. Ezekkel egy már meglévõ csatornát ruházunk fel különleges tulajdonságokkal. Például a
DataOutputStream-mel int-eket írhatun ki (bináris alakban): FileOutputStream fout = new FileOutputStream("adat.txt"); DataOutputStream dout = new DataOutputStream(fout); dout.writeInt(51); // dout-on keresztül az fout-ra írunk dout.close(); // rekurzíven mindkét csatornát lezárja A szûrõk egymásba ágyazhatók, mivel ezek maguk is csatornák. A szûrõknek ezt a mûködési elvét delegációnak nevezzük. A szûrõkre meghívott mûveleteket úgy hajtják végre, hogy igénybe veszik a szûrendõ csatrona szolgáltatásait. Adattípus értéke beolvasása és kiírása A DataInputStream és a DataOutputStream szûrõkkel a Java adattípusait tudjuk beolvasni/kiírni. (Szabványos, gépfüggetlen reprezentáció) DataInputStream file:///E|/docs/Untitled/Input Output.html (5 of 13)20040118 3:01:00 DataOutputStream Java Input/Output Forrás: http://www.doksihu int read(byte b[]) throws IOException flush() throws IOException int read(byte b[], int off, int
len) int size() // eddig kiírt byte-ok readFully(byte b[]) write(int b) readFully(byte b[], int off, int len) int write(byte b[], int off, int len) int skipBytes(int n) boolean readBoolean() writeBoolean(boolean b) byte readByte(byte v) writeByte(byte v) int readUnsignedByte() short readShort() writeShort(int v) int readUnsignedShort() char readChar() writeChar(int v) int readInt() writeInt(int v) long readLong() writeLong(long v) float readFloat() writeFloat(float v) double readDouble() writeDouble(double v) String readLine() // deprecated writeBytes(String s) // alsó byte-ok writeChars(String s) // 2 byte String readUTF() writeUTF(String s) Sor beolvasása: a BufferedReader osztály readLine() metódusával javasolt! Szöveg kiírása: PrintStream, PrintWriter osztályok (más-más csatornára írnak) Valamennyi adattípust kiírhatják szöveges formában: print vagy println write (String s) (int i) (double d) (int c) (char b[]) (char b[], int off,
int len) (String s) file:///E|/docs/Untitled/Input Output.html (6 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu Véletlen elérésû file-ok (RandomAccessFile) Felfogható, mint egy file rendszerben tárolt byte-vektor. Bármelyik pozicióján lévõ byte olvasható/írható. File-mutató: ettõl kezdõdõen olvasunk/írunk (automatikusan továbblép!) Lekérdezése: getFilePointer() Beállítása: seek() Tetszõleges adattípus olvasható/írható. Ugyanúgy használható, mint a DataInputStream és a DataOutputStream Kivételek: EOFException IOException A RandomAccessFile konstruktorának a 2. paramétere: "r": csak olvasás "rw": írás/olvasás Kapcsolat a file rendszerrel (File osztály) Információt tartalmaz egy file-ról vagy könyvtárról, és file- és könyvtár kezelési mûveleteket lehet végrehajtani a segítségével. Az file tartalmát nem ezzel dolgozzuk fel! Létrehozása konstruktorral: File f = new
File("munka/adat.txt"); File f = new File("adat.txt"); Nem létezõ állományhoz is létrehozható File objektum! Konstruktorok: File(String út); File(String út, String név); File(File út, String név); Metódusok: boolean canRead(); boolean canWrite(); boolean delete(); boolean exists(); String getAbsolutePath(); String getName(); String getParent(); String getPath(); boolean isAbsolute(); file:///E|/docs/Untitled/Input Output.html (7 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu boolean Directory(); boolean isFile(); long lastModified(); long length(); String [] list(); // a könyvtár állományai boolean mkdir(); boolean mkdirs(); boolean renameTo(); Példák Példa1 import java.io*; import java.util*; public class IOtest1 { public static void main(String [] args) { byte [] t = new byte[80]; String s = ""; int n=0, i=0, db=0, j=0; byte max= 10; boolean eof=false; String [] tk = new String[max]; Integer [] egesz = new
Integer[max]; FileWriter f = null; PrintWriter g = null; try { /* // DataInputStream readln() metódusa deprecated DataInputStream in = new DataInputStream(System.in); */ InputStreamReader in = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(in); System.outprintln("Kérem az adatokat, egy-egy sorban többet is lehet (max 10, de ures sor zár):"); while (!eof) { s = br.readLine(); if (s.length() == 0) eof = true; StringTokenizer st = new StringTokenizer(s); while (st.hasMoreTokens()) { tk[n++] = st.nextToken(); db++; } } } catch (IOException io) {System.outprintln(io+" hiba"); } catch (ArrayIndexOutOfBoundsException tulcsordul) {System.outprintln(" Tomb megtelt"); } file:///E|/docs/Untitled/Input Output.html (8 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu for (j=0; j<db; j++) { System.outprintln(tk[j]); } // Beolvasott adatokat file-ba menti try { f = new FileWriter("adat.txt"); g = new
PrintWriter(f, true); for (j=0; j<db; j++) { g.println(tk[j]); } } catch (IOException io) {System.outprintln(io+" hiba"); } finally {g.close();} //---------------------------------// A string tomb adatait integer tipusu tombbe teszi for (j=0; j<db; j++) egesz[j] = new Integer(0); for (j=0; j<db; j++) { try { egesz[j] = new Integer(tk[j]); } catch (NumberFormatException nf) {System.outprintln(j+1 + " adat hibas: " + tk[j]);} } // Kiirjuk az egesz tomb tartalmat for (j=0; j<db; j++) { System.outprintln(egesz[j]floatValue()); } } } N egész szám kiirása Random file-ba import java.io*; import java.util*; import corejava.*; // public class IOtest2 { public static void main(String [] args) throws IOException { int i, n=100, k= 0; StringBuffer s; RandomAccessFile f = null; String st; System.outprint("Kérem a file nevét: "); /* byte [] nev = new byte[20]; file:///E|/docs/Untitled/Input Output.html (9 of 13)20040118 3:01:00 Java Input/Output
Forrás: http://www.doksihu System.inread(nev); st = new String(nev); System.outprint("File név hossza: "+ stlength()); File fn = new File(st.trim()); // Le kell vágni a fölösleges karaktereket */ InputStreamReader in = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(in); st = br.readLine(); //br.close(); //in.close(); System.outprint("File név hossza: "+ stlength()); File fn = new File(st); /* st = Console.readString(""); System.outprint("File név hossza: "+ stlength()); File fn = new File(st); */ fn.delete(); try { f = new RandomAccessFile(fn, "rw"); for (i=1; i<=n; i++) f.writeInt(i); } catch (IOException io) {System.outprintln(io+" hiba"); Systemexit(1); } try { int x; f.seek(0); for (i=1; i<=n; i++) { if (i/10*10+1 == i) System.outprintln(); x = f.readInt(); s = new StringBuffer(""+x); s.insert(0, new char[8-slength()]); System.outprint(s); } System.outprintln();
System.outprintln("egeszdat file mérete: " + flength()); // i = 3; // az i. adatot olvassuk be // f.seek((i-1) * 4); // x = f.readInt(); // System.outprintln(x); } catch (IOException io) {System.outprintln(io+" hiba"); } finally {f.close();} } } file:///E|/docs/Untitled/Input Output.html (10 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu A Java.io csomag file:///E|/docs/Untitled/Input Output.html (11 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu file:///E|/docs/Untitled/Input Output.html (12 of 13)20040118 3:01:00 Java Input/Output Forrás: http://www.doksihu file:///E|/docs/Untitled/Input Output.html (13 of 13)20040118 3:01:00 User interfész Forrás: http://www.doksihu Grafikus kezeloi felület készítése A grafikus felület Konténer osztályok Layout menedzserek FlowLayout BorderLayout CardLayout GridLayout GridBagLayout AWT komponens hierarchia Eseménykezelés AWT eseményosztályok Eventlistener
interfészek Példák Checkbox alkalmazás Checkbox alkalmazás eseménykezeléssel Program paraméterek kiírása Lista használata Grafikus kezelõi felület készítése (User interfész) Grafikus kezelõi felület létrehozása. A Java Abstract Window Toolkit (AWT) osztály könyvtár támogatja a grafikus kezelõi felület létrehozását. Az AWT platform független, de nem olyan kifinomult, mint más fejlesztõ rendszerek GUI interfészei. Témák Stand alone alkalmazások ( grafikus kezelõi felületek létrehozása) Appletek (böngészõ Java alkalmazásai) ( grafikus kezelõi felületek létrehozása) Konténerek file:///E|/docs/Untitled/User interfesz.html (1 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu Komponensek grafikus kezelõi felület felépítése Pakolási stratégia Eseménykezelés (egér és billentyû események) A grafikus felület A grafikus felület komponensekbõl áll (a komponens osztályok példányai). A
komponens osztályok a Component osztály leszármazottai. A komponenseket a konténer osztályok foglalják egységbe. Tehát a komponesek a konténerek egy csoportját kezelik és vezérlik. A konténerek a felhasználói eseményeket a komponenseikhez továbbítják. A konténer osztályok a Container osztály leszármazottai. A Container a Component leszármazottja, ezért egy konténer további konténereket tartalmazhat. A konténerek a rendelkezésükre álló helyet a képernyõn az ún. pakolási stratégia alapján osztják fel, vagyis, hol helyezkedjen el a komponens, és hogyan változzon a mérete, ha a konténer mérete változik. Egy pakolási stratégia a LayoutManeger interfész megvalósítása. Több ilyen pakolási stratégia létezik: FlowLayout, BorderLayout, stb. A konténerekbe a komponenst a konténer add() metódusával lehet felvenni, és a remove() metódusával lehet eltávolítani. Ha egy konténer komponens listája változik, a validate() metódus
hívásával a megjelenítést aktualizálni kell. Konténer osztályok Panel/Applet A java.appletApplet a Panel-bõl származik file:///E|/docs/Untitled/User interfesz.html (2 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu Window/Frame A Window keret nélküli, a Frame kerettel rendelkezõ különálló ablak ScrollPane Egyetlen komponenst tartalmazhat, görgetõ sávokkal rendelkezik Dialog/FileDialog Kommunikáció a felhasználóval dialógus ablakok segítségével: adatbekérés, hiba kijelzés. Mindig egy másik ablakhoz tartoznak Lehetnek modálisak is Layout menedzserek FlowLayout: addig pakolja a komponenseket egymás mellé, amíg elférnek, majd a következõ sorban folytatja. (Ez az applet alapértelmezett Layout menedzsere.) BorderLayout: az égtájak szerint és középre helyezhetjük az egyes komponenseket. North West Center East South panel.add(komponens, "East"); // A panel egy konténer CardLayout: nem tárgyaljuk
GridLayout: a komponensek négyzetrácsba kerülnek, amelyeknek a mérete azonos. panel.setLayout(new gridLayout(5, 4)); panel.add(new Button ("1")); panel.add(new Button ("2")); GridBagLayout: egy milliméter papírhoz hasonló rácson minden komponensek egy vagy több cellát foglalhat el. A komponensek kezdõ poziciója megadható. file:///E|/docs/Untitled/User interfesz.html (3 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu A kezelése bonyolult. A Layout menedzsert le is lehet tiltani, a komponensek abszolút poziciója is megadható. AWT komponens hierarchia file:///E|/docs/Untitled/User interfesz.html (4 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu Eseménykezelés Az eseményeket egy osztályhierarchia kezeli, amelynek gyökere a java.utilEventObject Egy bizonyos típusú eseményhez a gyökérosztály egy neki megfelelõ eseménye tartozik. Az AWT-beli események a java.awtAWTEvent osztályba tartoznak Az
események egy forrás objektumból származnak, és egy vagy több fogadó objektumnak adódnak át a fogadó file:///E|/docs/Untitled/User interfesz.html (5 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu objektum megfelelõ metódusának meghívásán keresztül. Az eseménykezelés osztályai a java.awtevent csomagban vannak (importálni kell!) Az eseményfajták fogadására interfészeket készítettek. Ha egy osztály megvalósít egy ilyen interfészt, akkor a példányai fogadó objektumok lesznek, vagyis feldolgozzák az ennek megfelelõ eseményeket. Ahhoz, hogy a fogadó objektumok megkapják az eseményeket, regisztrálniuk kell magukat az esemény forrásánál. Pl.: Az ablak a Frame osztály leszármazottja. Implementálja az ActionListener interfészt Ez az esemény fogadója Az interfész összes metódusát implementálni kell. Ez esetben csak az ActionPerformed metódust A Bezár nyomógomb az esemény forrása. Ennél kell regisztrálni az
ablakot, hogy adja át neki az ActionEvent típusú objektumot: ■ bezarButton.addActionListener(this) Pl.: file:///E|/docs/Untitled/User interfesz.html (6 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu FocusListener interfész metódusai: focusGained(FocusEvent e) focusLost(FocusEvent e) FocusEvent eseményosztály konstruktora: public FocusEvent(Component source, int id, boolean temporary) ❍ source: a java.utilEventObjectgetSource() metódusával kérdezhetõ le, hogy kitõl származik az esemény ( source.getSource() ) ActionListener interfész metódusai: actionPerformed(ActionEvent e) ActionEvent eseményosztály konstruktora: public ActionEvent(Object source, int id, String command, int modifiers) ■ source: esemény forrása id: esemény azonosítása command: parancs sztring modifiers: billentyûk kombinációja, amelyeket lenyomva tartottunk az esemény keletkezésekor ActionEvent metódusai: String getActionCommand() int
getModifiers() AWT eseményosztályok file:///E|/docs/Untitled/User interfesz.html (7 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu Eventlistener interfészek (java.utilEventListener) ActionListener AdjustListener ComponentListener ContainerListener file:///E|/docs/Untitled/User interfesz.html (8 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu FocusListener ItemListener KeyListener MouseListener MouseMotionListener TextListener WindowListener Példák Checkbox alkalmazás import java.awt*; public class CheckboxTestF extends Frame { Checkbox c1; Checkbox c2 = new Checkbox("2. box", true); Checkbox c3 = new Checkbox("3. box", false); CheckboxGroup cbg = new CheckboxGroup(); // Csoportos checkboxok létrehozása public CheckboxTestF() { // konstruktor super("Checkbox alkalmazás"); setLayout(new FlowLayout()); c1 = new Checkbox("1. box", true); add(c1); // Különálló checkbox-ok létrehozása
add(c2); add(c3); add(new Checkbox("1. radio ", cbg, true)); add(new Checkbox("2. radio ", cbg, false)); add(new Checkbox("3. radio ", cbg, true)); setSize(250, 200); validate(); } public static void main(String args[]) { CheckboxTestF fr = new CheckboxTestF(); fr.show(); } } file:///E|/docs/Untitled/User interfesz.html (9 of 12)20040118 3:01:01 User interfész Forrás: http://www.doksihu Checkbox alkalmazás eseménykezeléssel import java.awt*; public class CheckboxTestF extends Frame { Checkbox c1; Checkbox c2 = new Checkbox("2. box", true); Checkbox c3 = new Checkbox("3. box", false); CheckboxGroup cbg = new CheckboxGroup(); // Csoportos checkboxok létrehozása public CheckboxTestF() { // konstruktor super("Checkbox alkalmazás"); setLayout(new FlowLayout()); c1 = new Checkbox("1. box", true); add(c1); // Különálló checkbox-ok létrehozása add(c2); add(c3); add(new Checkbox("1. radio ", cbg,
true)); add(new Checkbox("2. radio ", cbg, false)); add(new Checkbox("3. radio ", cbg, true)); setSize(250, 200); validate(); } public static void main(String args[]) { CheckboxTestF fr = new CheckboxTestF(); fr.show(); } } Program paraméterek kiírása import java.awt*; import java.awtevent*; import java.utilProperties; //grafikus komponensek miatt kell //eseménykezelés miatt kell //rendszerparaméterlistázáshoz kell public class Params extends Frame implements ActionListener { TextArea textArea=new TextArea(); Button bezarButton=new Button("Bezár"); public Params() { super("Params alkalmazás"); bezarButton.addActionListener(this); add("South", bezarButton); add("Center", textArea); setSize(300, 200); validate(); } public static void main(String args[]) { file:///E|/docs/Untitled/User interfesz.html (10 of 12)20040118 3:01:01 //Frame-tol öröklés //szövegmezo //nyomógomb //konstruktor //Frame konstruktorát
meghívjuk //figyeli a gombot //a gomb lent lesz //a többi helyen szövegmezô lesz //kezdeti méret beállítása //grafikus felület aktualizálása //indítás User interfész Forrás: http://www.doksihu Params frame=new Params(); //példányosítás frame.textAreaappend("Paraméterszám: "+argslength+" "); for (int számláló=0;számláló<args.length;számláló++) //paraméterek listázása frame.textAreaappend(számláló+1+" paraméter: "+args[számláló]+" "); frame.show(); //felület megjelenítése } public void actionPerformed(ActionEvent e) { System.getProperties()list(Systemout); System.exit(0); } //eseménykezelo //listázás //kilépés a programból } Lista használata import java.awt*; import java.awtevent*; public class ListTestF extends Frame implements ActionListener, ItemListener, FocusListener { List l1=new List(8, false); // egyszeres választású lista List l2=new List(3, true); // többszörös választású
lista TextArea t = new TextArea("Kezdetben üres volt"); // szövegterület TextField tf = new TextField(10); // szövegmezö public ListTestF() { l1.addItem("1/1"); l1.addItem("1/2"); l1.addItem("1/3"); l1.addItem("1/4"); l1.addItem("1/5"); l1.select(0); l1.select(1); // konstruktor // elsõ lista felépítése // csak ez lesz kiválasztva, mert egyszeres választású a lista l2.addItem("2/elso"); // második lista felépítése l2.addItem("2/második"); l2.select(0); // mindketto ki lesz választva l2.select(1); add("West",l1); add("East",l2); add("Center", tf); add("South",t); // alapértelmezett pakolási startégia: BorderLayout l1.addActionListener(this); l2.addItemListener(this); tf.addFocusListener(this); t.setEditable(false); setSize(400, 300); validate(); } file:///E|/docs/Untitled/User interfesz.html (11 of 12)20040118 3:01:01 User interfész
Forrás: http://www.doksihu public void actionPerformed(ActionEvent evt) { t.insert("Következö: " + l1getSelectedItem() + ' ', 0); validate(); } public void itemStateChanged(ItemEvent e) { int index = Integer.parseInt(egetItem()toString()); String s = ""; if (l2.isIndexSelected(index)) s = index + ". Kiválasztva: " + l2getItem(index); else s = index + ". Nincs kiválasztva: " + l2getItem(index); t.insert("Következö: " + s + ' ', 0); validate(); } public void focusGained(FocusEvent foc) { } public void focusLost(FocusEvent foc) { TextField o = (TextField)foc.getSource(); try { int x = Integer.parseInt(ogetText()); } catch (NumberFormatException n) {o.setText("Hibás adat!"); /* Dialog d = new Dialog((Frame)o.getParent(), "Hibás adat!", true); d.show(); // Nem lehet becsukni a dialógus ablakot! */ } } public static void main(String args[]) { //indítás ListTestF frame=new ListTestF();
//példányosítás frame.show(); //felület megjelenítése } } file:///E|/docs/Untitled/User interfesz.html (12 of 12)20040118 3:01:01 A Jáva programozási nyelv Forrás: http://www.doksihu A Jáva programozási nyelv Tartalomjegyzék Röviden az elõzményekrõl A nyelv legfontosabb tulajdonságai Egyszerû Objektumorientált Architektúrafüggetlen és hordozható Java Interpretált és dinamikus Robusztus és biztonságos Többszálú Elosztott Összefoglalás Végezetül néhány kérdés, kétely Fontosabb WWW címek Duke A Sun-nál már megint kitaláltak valamit 1: új programozási nyelvtõl hangos az Internet, itt van a Jáva 2 - angolosan Java! Manapság mindenki errõl beszél: kisebb és nagyobb cégek lelkesen üdvözlik az új nyelvet, technológiát; csatlakozó, támogató nyilatkozataikkal telve a szaksajtó. Az esetleges tõkeerõs - ellenzõk egyelõre bölcsen hallgatnak vagy - rosszmájú vélemények szerint - ravasz módon, beépülve, belülrõl
próbálják kisajátítani, a saját ízlésüknek, piaci érdekeiknek megfelelõre formálni az alakuló technológiát. Programozók, felhasználók lelkes és szkeptikus hada vitázik egymással, a nyelvvel foglalkozó hírcsoport, a comp.langjava meghaladja a nagy "vetélytárs" nyelvhez tartozó comp.langc++ forgalmát 1996 elsõ félévében a Jáva nyelvrõl másfél tucat könyv megjelenése várható. Izzanak az Internet vonalak a Sun és a Netscape FTP szerverei környékén, ahonnan letölthetõk az elsõ ismerkedéshez szükséges programok. Végezetül egy ún Jávát értõ böngészõvel (Java-aware browser) rendelkezõ szerencsések egyre gyakrabban bukkannak a WWW világában meghökkentõ oldalakra, olyanra, ahol például a fenti vörös orrú, fekete sapkás, figura - Dukenak hívják - vidáman lengeti felénk a bal kezét! Pont ez az integetés az, ami megindokolja, hogy miért kell nekünk egy új programozási nyelv, amikor olyan jól megvoltunk mi az
X-szel (itt mindenki behelyettesítheti a kedvencét). Ugyan a Jáva nyelv tulajdonságainak felsorolásánál megtalálhatunk számos olyan divatos kifejezést - pl. objektumorientált, párhuzamos, elosztott, stb. -, amik nélkül manapság egyetlen a valamire való programozót sem lehetne elcsábítani a kedvenc, ódivatú nyelvének pontosvesszõi és zárójelei mellõl, de ez még kevés lenne a file:///E|/docs/Untitled/article.html (1 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu sikerhez, elvégre világmegváltó nyelvek napról napra születnek. Szerintem a várható sikernek ezen felül két jelentõs indoka van: elõször is sok befolyásos számítástechnikai cég elhitte, hogy van benne fantázia és most - remélhetõleg - dõl a pénz a fejlesztésre. A felhasználók szempontjából sokkal fontosabb a másik érv: a Jáva nyelv összeházasodott HotJava napjaink legdivatosabb számítástechnikai játékszerével, az Internet
hálózattal. A házasságból egyelõre két gyermek született, a Sun HotJava- illetve a Netscape WWW böngészõ programjának új, 2.0 verziója. Bár mindkét gyermek fejletlenke még, csak béta korúak, de már ki-kimutatják oroszlánkörmeiket, sõt újabb gyerekek érkezése is várható. Mellesleg a HotJava teljes egészében Jáva nyelven íródott, azt bizonyítandó, hogy a nyelv eléggé izmos ilyen méretû feladatok megoldására. Egy ilyen Jávát értõ böngészõvel az egér egyetlen óvatlan kattintására nem csak adatokat, de teljes, futni képes programokat is letölthetünk a kiszolgálóról, amely aztán el is indul a mi számítógépünkön. Akinek errõl a vírusok, férgek és egyéb rosszindulatú programok jut az eszébe, nyugodjon meg, késõbb még lesz errõl is szó! Mire jó egy ilyen program? Hát természetesen bármire - a Jáva általános célú programozási nyelv -, a program nálunk fut, nem terheli az eredeti kiszolgálót, jópofa
dolgokat rajzol, menükkel, párbeszédablakokkal tarkítja a képernyõnkre, hangokat ad, egyszóval életet lehel a letöltött dokumentumba. Persze ennél többet is tehet, például felveheti a kapcsolatot azzal a kiszolgálóval, ahonnan hozzánk került és a két gép tisztességes elosztott rendszerként buzgón kommunikálni kezd, abból pedig bármi kisülhet. A hagyományos böngészõk képesek arra, hogy az általuk ismert, elõre beprogramozott protokollokat HTTP, FTP, Gopher, News, . - használva felvegyék a kapcsolatot egy-egy kiszolgálóval és onnan adatokat töltsenek le, amelyeket, amennyiben a formátumát korábban ismerték - HTML, GIF, JPEG, . -, akkor megjelenítsék. Viszont ha az URL-ben (a kiszolgáló gépet és az ott tárolt információt megadó címben) ismeretlen protokollt adtunk meg, akkor szegény böngészõ kétségbeesetten széttárja a karját. Ha csak az adat formátuma ismeretlen, a helyzet egy fokkal jobb: a böngészõ letölti a teljes
adathalmazt, majd - ha szerencsénk van - továbbpasszolja a megjelenítés feladatát egy másik programnak, legrosszabb esetben tárolhatja azt a helyi lemezünkön, hátha majd egyszer megértjük, mi van benne. A Jávát értõ böngészõkben viszont a kiszolgálóról letöltött Jáva programok bõvíthetik a felhasználható kommunikációs protokollokat (protocol handler) és a megjeleníthetõ adattípusokat (content handler). applets Az önállóan futtatható programok (application) és a böngészõk által letölthetõ és futtatható "programkák" (applet) között nem nagy a különbség, legfeljebb csak a biztonsági meggondolások miatt a böngészõk szigorúbban figyelik, korlátozzák a hálózatról letöltött programkákat. Önálló programnál ilyen védelem nincs, a felhasználó nyilván tudja, mit és miért indított el. A halózaton letölthetõ programok ötlete új színt hoz az elosztott rendszerekben divatos ügyfélkiszolgáló
paradigmába: a programok igény szerinti letöltése (distributed on demand) elmossa a kiszolgáló és az ügyfél közötti éles határokat. file:///E|/docs/Untitled/article.html (2 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu Röviden az elõzményekrõl Az 1990-es évek elején valahol a Sun berkeiben elindult egy kevéssé fontos projekt azzal a céllal, hogy a cég betörjön a felhasználói elektronikai piac egy új, az ún. "okos", processzorral vezérelt, programozható (smart) készülékeket alkalmazó területére. E készülékcsalád jellegzetes képviselõje a kábel-TV társaságok által használt vezérlõ (set-top box). Az ilyen készülékek programozásához igény volt olyan architektúra-független technológiára, amely lehetõvé tette a kész programok a hálózaton keresztül a készülékbe letöltését, megbízható futtatását. A projekt kezdetben a C++ nyelvet használta, ám a fejlesztõk ezt is, a
többi, akkor hozzáférhetõ programozási nyelvet is alkalmatlannak találták a célkitûzéseik maradéktalan megvalósítására, hát új nyelvet terveztek maguknak. Kiindulási alapként a C++ nyelvet használták, kigyomlálva belõle - az általuk - bonyolultnak, nem megbízhatónak talált szerkezeteket, hozzáadva innen-onnan átvett, hasznosnak tûnõ ötleteket, nyelvi elemeket. A felhasználói elektronikai alkalmazások lassabban fejlõdtek, mint azt elõre várták, a projekt szép csendben el is halt volna, ha közben az Internet hálózat nem indul rohamos fejlõdésnek. Szerencsére észrevették, hogy az Internet hálózat hasonló körülményeket teremt és hasonló igényeket támaszt egy új programozási technológiával szemben. A nyelv legfontosabb tulajdonságai About Egyszerû A nyelv szintaxisa és szemantikája nagyban hasonlít a sokak által ismert C illetve C++ programozási nyelvhez, megkönnyítve a kezdeti ismerkedést. A C++ nyelvbõl elhagytak
néhány - programozói vagy fordítóprogram írói szempontból - bonyolult elemet. Kimaradt például az operátorok felüldefiniálásának lehetõsége (operator overloading), a többszörös öröklõdés. Eltûnt a goto utasítás, az automatikus típuskonverziók (coercion), az összetett adatszerkezetek közül a union, illetve C++ban már amúgy is szükségtelen struct. Azért szerencsére nem gyomláltak ki mindent a C++-ból, megmaradt például a futásidejû hibák lekezelésének mechanizmusa, az. ún kivételkezelés (exception handling). Bár az "igazi programozók" megkönnyezik az eltávozott goto utasítást, de helyette címkézett ciklusokat, többszintû break és continue utasítást kaptunk. Sokaknak elsõre - többeknek talán másodszorra is - furcsa, de a Jáva nem használ mutatókat (pointer), egy csapásra megszûntetve ezzel a C programozók kedvelt programozási hibáinak egész seregét. A programozó munkáját nagymértékben
file:///E|/docs/Untitled/article.html (3 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu megkönnyíti az is, hogy a nyelv automatikusan felszabadítja a már nem használt tárterületeket (szemétgyûjtés, garbage collection). Ízelítõül álljon itt a kötelezõ "Szervusz világ" program egy kicsit módosított változata, amely az elsõ paraméterben megadott szöveget írja ki a "World" helyett, már amennyiben van ilyen. class HelloWorldApp { public static void main (String args[]) { System.outprintln("Hello "); if (args.length == 0) System.outprintln("World!"); else System.outprintln(args[0] + "!"); } } Objektum- Manapság az objektumorientáltság divatos programozási paradigma, bár a orientált szakirodalom nem teljesen egységes a kritériumainak meghatározásában. A Jáva lényegében a C++ objektumorientált tulajdonságait tartalmazza. A programozó absztrakt adattípusként
viselkedõ osztályokat definiálhat, az osztályok mûveleteket módszereket - tartalmaznak, amelyek a rejtett adatreprezentáción (egyedváltozók) operálnak. Létrehozhatunk objektumokat, azaz egyes osztályokba tartozó egyedeket Osztályok definiálásánál felhasználhatunk már meglévõ osztályokat, az új osztály (a leszármazott) örökli a szülõ adatait, módszereit. A módszerek hívásánál a meghívott módszer futási idõben, objektum aktuális típusának megfelelõen kerül kiválasztásra (virtuális módszerek, polimorfizmus). Az egyes osztályokban definiált változók és módszerek láthatóságát a C++-ban megismert módon - private, protected és public - lehet megadni. Eltérést jelent a C++-hoz képest, hogy a Jávában a beépített, egyszerû adattípusú numerikus, logikai és karakter típus - változók kivételével minden objektum; az egyetlen összetett adattípus, a tömb (array) teljes értékû osztályként viselkedik. A program nem
tartalmaz globális változókat és globális eljárásokat, minden adat és eljárás valamilyen objektumhoz, esetleg osztályhoz kötõdik. Persze a C++-t ismerõk tudják, hogy a globális változókat és függvényeket helyettesíteni lehet ún. osztályváltozókkal és statikus függvényekkel, ezek itt is használhatók. A Jávában minden módszerhívás - a fent említett statikus módszerek kivételével file:///E|/docs/Untitled/article.html (4 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu virtuális. A C++-hoz hasonlóan lehetõségünk van az egyes objektumok típusát futási idõben lekérdezni (ez a C++-ban is viszonylag új nyelvi elem az ún. RTTI, Run-Time Type Interface), sõt itt akár az osztályok forrásprogramban definiált nevét futás közben is felhasználhatjuk például objektumok létrehozására. Az osztályok mellett a Jáva az Objective-C programozási nyelvbõl átvette az Interface fogalmat. Az Interface nem
más, mint módszerek egy halmaza - adatszerkezeteket, egyedváltozókat nem tartalmaz -, amelyet egyes osztályok megvalósíthatnak (implementálhatnak). A Jáva a C++-szal ellentétben nem engedi meg a többszörös öröklõdést, viszont Interface-ek használatával, egyszerûbben, kevesebb implementációs problémával hasonló hatást lehet elérni. Architektúra- Napjaink hálózatait heterogén hardver- és szoftver architektúrájú számítógépek független alkotják. A programok fejlesztését nagymértékben megkönnyítené, ha a forráskódból és hordozható elõállított program bármely architektúrán azonos módon futna. Ezen cél elérése végett a Jáva nyelv nem tartalmaz architektúra- vagy implementációfüggõ elemeket. A C nyelvvel ellentétben a beépített adattípusok (pl. int) mérete - tárolásához szükséges memória mérete, a típus értelmezési tartománya - nyelvi szinten meghatározott. Ahhoz, hogy a lefordított program változtatás
nélkül futtatható legyen különbözõ hardver architektúrákon, a fordítóprogram a programot nem egy konkrét processzor gépi kódjára, hanem egy képzeletbeli hardver - virtuális gép (virtual machine) utasításrendszerére fordítja le. Az így létrejött közbülsõ, ún Byte kódot töltjük le a célarchitektúrára, ahol a virtuális gépet megvalósító program értelmezi és hajtja végre. A hordozhatóság nem csak a virtuális gépi utasítások, hanem a nyelv mellet szabványosított rendszerkönyvtárak szintjén is jelentkezik, ezek a könyvtárak valósítják meg a legfontosabb, operációs rendszerekhez kötõdõ feladatokat, mint például a be- és kiviteli rendszert, vagy a programok grafikus kezelõi felületét. Egy új architektúrán akkor futtathatók a Jáva programok, ha már implementálták rá a virtuális gépet, beleértve a rendszerkönyvtárakat is. A virtuális gépet C-ben írták, a kód POSIX.1 szabványnak megfelelõ operációs
rendszert tételez fel, így viszonylag kis munkával hordozható. A hordozhatóság érdekes aspektusa a fejlesztõi környezet hordozhatósága. A környezet egyes részei, mint például a fordítóprogram, nyomkövetõ eszközök, vagy maga a HotJava böngészõ is Jáva nyelven íródott. Na és ha a Jáva programok hordozhatók, akkor hipp-hopp (?), az egész környezet is átkerült az új architektúrára. file:///E|/docs/Untitled/article.html (5 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu Interpretált Az interpretált végrehajtás - kombinálva a klasszikus kapcsolatszerkesztõ (linker) és dinamikus helyett futás idejû betöltéssel - a fejlesztési ciklust nagy mértékben felgyorsítja. A Jávából eltûntek a C-bõl ismert header állományok, feltételes fordítás, más programállományok fordítás közbeni beolvasása (#include). A lefordított programok tartalmaznak a szerkesztéshez szükséges minden információt. Elég
csak a megváltozott állományokat lefordítanunk - nincs szükség a C-nél megszokott make programra, a forrásállományok közötti függõségek feltérképezésére -, a program máris futtatható. Egyébként a Jáva támogatja a nagybani programozást, összetartozó osztályok egy csomagba (package) foghatók, egyszerre fordíthatók. A láthatóság is figyelembe veszi a csomagokat, a C++ explicit friend deklarációjának szerepét itt a csomagra - de csak a csomagra - vonatkozó láthatóság veszi át. A kapcsolatszerkesztõ helyét az ún osztálybetöltõ (class-loader) veszi át, amely futás közben - ha szükség van rá - betölti az egyes osztályokat megvalósító lefordított, Byte kódú programállományokat. Az osztály-betöltõ nem csak helyi állományokból, de szükség esetén a hálózaton keresztül is képes kódot letölteni. Többek között a betöltõ feladatának megkönnyítése végett a Byte kód tartalmaz a forráskódból átvett
szimbolikus- illetve típus információkat. Lássunk egy példát arra, hol jöhet jól ez az információ. Az objektumorientált programozási paradigma egyik nagy ígérete, hogy általános célú, könnyen felhasználható osztály-könyvtárakat, "szoftver-IC-ket" hozhatunk létre a segítségével. Sajnos a C++ nyelv ilyen tekintetben nem váltotta be teljesen a hozzá fûzött reményeket. Nagyon nehéz olyan osztályokat tervezni, amelyeket késõbb nem kell majd úgy módosítani, hogy ne kelljen azt például új - bár a programozók elõl rejtett - adatkomponensekkel vagy módszerekkel bõvíteni. Bár az osztály külsõ interfésze nem feltétlen változott meg, ám a C++ az osztály reprezentációját, tárbeli elrendezését kihasználó fordítási mechanizmusa miatt ilyenkor az összes, a megváltozott osztályt - akár csak öröklésen keresztül - felhasználó programot újra kell fordítani. Ezt hívják "törékeny alaposztály" (fragile
base class) problémának A Jáva ezt a problémát úgy kerüli meg, hogy az osztályok adatkomponenseire, módszereire a Byte kódban is szimbolikusan hivatkoznak, a hivatkozások konkrét címekké kötése csak futási idõben, a virtuális gépben történik meg. A közbülsõ kódban megmaradt szimbolikus információk megkönnyítik a programok nyomkövetését. Sajnos az interpretált végrehajtásnak van egy nagy hátránya is, a programok sokkal - becslések szerint 10-20-szor - lassabban futnak, mint a gépi kódú megfelelõik. Bár a virtuális gép elég ügyesen lett kitalálva és a fordítóprogram is mindent megtesz azért, hogy ezt a virtuális architektúrát a lehetõ legjobban kihasználja, de még így sem vetekedhet a gépi utasítások sebességével. Ehhez még hozzáadódik a szimbolikus hivatkozások feloldásának ideje, a különbözõ betöltési- és futásidejû ellenõrzések - ld. késõbb -, a tárgazdálkodási modellel járó szemétgyûjtési
algoritmus futásához szükséges idõ. file:///E|/docs/Untitled/article.html (6 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu E lassúság ellen jelenleg nem sokat tehetünk, legfeljebb azzal vigasztalhatjuk magunkat, hogy az alkalmazások jelentõs részénél - gyakori felhasználói közremûködést, vagy hálózati kommunikációt igénylõ programoknál - a program sebessége nem a legfontosabb követelmény. Persze a Jáva programok meghívhatnak gépi kódú (native) eljárásokat is, de ezzel elvesztjük az architektúra- függetlenség, hálózaton letölthetõség tulajdonságát. De bejelentettek olyan fordítóprogramot is, amely közvetlenül gépi kódra fordít. Legígéretesebbnek az úgynevezett "röptében fordítás" (just-in-time, on-the-fly compilation) ötlete tûnik. A Byte kód úgy tele van tömve szimbolikus információkkal, hogy elvileg nem nehéz - ezt kiindulási nyelvnek tekintve - optimalizáló fordító
programot írni hozzá. Ráadásul a virtuális gép utasításrendszere nagyon hasonlít napjaink processzoraiéhoz, könnyû belõle jó kódot generálni. A fordítás történhet az egyes osztályok betöltésekor - a szükséges ellenõrzések után -, esetleg végrehajtás közben. Futás közben esetleg az is eldõlhet, hogy érdemes-e az adott programrészletet lefordítani, mert gyakran használjuk, avagy megmaradhat interpretáltnak. Másik érdekes kísérlet, hogy a Sun a Jáva virtuális gépet sziliciumon is megvalósítja, hamarosan kaphatók olyan mikroprocesszorok, amelyek a Jáva Byte kódot közvetlenül futtatják. Robusztus Ez a két fogalom a Jáva esetében kéz a kézben jár. Robusztus egy nyelv, ha és biztonságos megakadályozza vagy futás közben kiszûri a programozási hibákat, biztonságos, ha megakadályozza, hogy rosszindulatú programok kerüljenek a rendszerünkbe. Mindkét célkitûzés eléréséhez gyakran hasonló módszereket használhatunk. A
robusztusság nyelvi szinten a szigorú, statikus típusosságban jelenik meg. Minden adatnak fordításkor jól definiált típusa van, nincsenek automatikus konverziók, az explicit konverzió csak kompatibilis típusoknál sikerül, egyébként legkésõbb futtatáskor programhibát (exception) okoz. A mutatók eltûnésével rengeteg potenciális hibalehetõség eltûnt a nyelvbõl - pl. NULL pointer hivatkozás, levegõben lógó mutatók -, persze elvesztettük az "igazi programozók" egyik kedvencének, az inteknek és a mutatóknak ide-oda alakítgatásának lehetõségét is. A dinamikus szemétgyûjtés megkímél bennünket a hasznos memória elszivárgásától (memory leak). Az egyedüli összetett adatszerkezet, a tömb használatakor a túlcímzést futási idõben ellenõrzik. Az osztály-betöltõ arra is figyel, hogy a módszereket megfelelõ típusú paraméterekkel hívjuk meg. A biztonság (security) a robusztussággal kezdõdik, a fordító csak
korrektül viselkedõ programokat ad ki magából. Ez elegendõ lehet önálló alkalmazásoknál, de a programkák letöltésénél ennél többre van szükség. Kezdjük azzal, hogy ki garantálja, hogy a letöltött Byte kódot valóban egy megbízható Jáva fordító hozta létre, nem pedig file:///E|/docs/Untitled/article.html (7 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu egy bit-betyár barkácsolta össze a hexadecimális szerkesztõjével? A Byte kód minden utasítása információt tartalmaz az operandusok típusáról, az osztály-betöltõ függetlenül attól, hogy a helyi háttértárról vagy a hálózatról tölt be - ellenõrzi, hogy a program megfelel-e a nyelv szabályainak. Eldönti például, hogy minden operandus valóban a megfelelõ típusú, nem használjuk ugyanazt az adatot más-más típusúként is. Ellenõrizhetõ az is, hogy a módszerek a vermüket konzisztensen használják-e, valamint hogy a kód nem fér-e
hozzá számára nem engedélyezett - a nyelv definíciója szerint láthatatlan, rejtett - adatkomponensekhez, módszerekhez. A betöltõ egy hivatkozott osztályt elõször mindig a helyi háttértárból próbál betölteni, csak akkor fordul a hálózaton elérhetõ kiszolgálóhoz, ha az osztály nincs meg a helyi rendszeren. Így elkerülhetõ, hogy trójai falóként valamelyik rendszerkönyvtár helyett azonos nevû, távolról betöltött programot futtassunk. Ha a betöltött programkák átjutottak a betöltõ konzisztencia-ellenõrzésén, akkor a virtuális gép felügyelete alatt kezdenek futni, ez ellenõrzi, hogy a programok csak engedélyezett tevékenységet hajtanak végre. Szigorúan szabályozott - vagy teljesen tiltott - például helyi állományokhoz való hozzáférés, tiltott más helyi programok indítása, jelentõsen korlátozott a hálózaton felvehetõ kapcsolatok címzettje. Sajnos ezen biztonsági szabályok erõsen korlátozzák a programkák
képességeit. Biztonsági szempontból legfeljebb a helyi rendszerbõl betöltött - többé-kevésbé megbízható -, illetve hálózatról letöltött - eleve gyanús - osztályok között lehet különbséget tenni. Késõbbiekben lehetõség lesz nyilvános kulcsú titkosítás segítségével azonosítható forrású, garantáltan eredeti, változatlan, "megbízható" programok letöltésére és futtatására is. Többszálú A programok jelentõs része párhuzamosan végrehajtható részletekre - vezérlési szálakra - bontható. Így jobban kihasználható a számítógép központi egysége, a programok a külsõ - például felhasználói - eseményekre gyorsabban reagálhatnak. Az egymással kommunikáló, viszonylag laza kapcsolatban álló szálakra bontott feladat könnyebben áttekinthetõ, megvalósítható és belõhetõ. A többszálú programozáshoz a Jáva nyelvi szinten biztosítja az automatikus kölcsönös kizárást: szinkronizált (synchronized)
módszerek vagy utasítások, valamint a szálak létrehozásához, szinkronizációjának megvalósításához a rendszerkönyvtár tartalmaz egy ún. Thread osztályt. A Thread osztály a Hoare-féle feltételes változók (conditional variable) modelljét követi. Természetesen az összes, a rendszerkönyvtárakban definiált osztály használható többszálú programokból anélkül, hogy aggódnunk kellene az esetleges hibás mûködés miatt (thread-safeness). A Jáva virtuális gép a szálak futtatásához prioritáson alapuló preemptív - de nem feltétlenül idõosztásos - ütemezõt tartalmaz. Ez magyarázza például azt, hogy - a jelentõs felhasználói igények ellenére - nem született még Jáva virtuális gép a file:///E|/docs/Untitled/article.html (8 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu Microsoft Windows 3.1-es - csak kooperatív ütemezést tartalmazó - rendszerére A többszálú programozás támogatása
ellenére a Jáva nyelv - legalábbis mostani változatában - valósidejû programok írására nem alkalmas. A virtuális gép nem tartalmaz határidõs ütemezési képességeket, de még a prioritás-öröklést sem ismeri, a jelenleg implementált szemétgyûjtõ algoritmus sem alkalmas valósidejû futtatásra - bár ez utóbbi a virtuális gép "magánügye", a programok változtatása nélkül könnyen lecserélhetõ. Elosztott A Jáva technológiát beharangozó ismertetõk mindenhol kiemelik, hogy a technológia elosztott (distributed) rendszerek létrehozását támogatja. Itt azért én megjegyezném, hogy az elosztottság eléggé cseppfolyós fogalom, a Jáva jelenleg sokkal kevesebbet tud, mint amit sokak - köztük én is - szeretnének. Az elosztottság jelenleg két formában jelenik meg: mint már említettem, az osztálybetöltõ képes Jáva Byte kódot a hálózaton letölteni. Ezen túl a rendszerkönyvtárak tartalmaznak a TCP/IP protokollcsalád
alacsonyabb, szállítási (TCP és UDP), valamint magasabb, alkalmazói (pl. FTP, HTTP) szintû protokollok kezélésére szolgáló osztályokat. De egy Jáva program nem elosztott objektumorientált rendszer, nincs mód távoli objektumok létrehozásra, transzparens távoli módszerhívásra. Viszont komoly, biztató kisérletek történnek a Jáva és a CORBA (Common Object Request Broker Architecture) összeházasítására, de láttam már a hálózaton CORBA-tól független, de hasonló funkciókat nyújtó kisérleti osztály-könyvtárat is. Összefoglalás Surfer Duke A Jáva számos fent felsorolt tulajdonsága miatt érdekes, figyelemre méltó programozási nyelv; a nyelv tervezõi sokat tanultak a korábbi tapasztalatokból. Bár véleményem szerint a C++-t, mint objektumorientált nyelvet a közeljövõben nem fogja kiszorítani, de bizonyos - nem túl nagy méretû, interaktív, grafikus felhasználói felületû - feladatok megoldásánál hódítani fog. Az pedig,
hogy szorosan összefonódik a World Wide Web-el, garantálja a rohamos elterjedését, szinesebbé, gazdagabbá téve az Internet hálózat világát. Bár nem kell feltétlenül hálózathoz kötõdnie: nem lennék meglepve, ha hamarosan multimédiás CD-k lejátszásához is Jávával felcsinosított böngészõket használnánk. Persze a Jáva képességeivel nem egyedülálló napjaink számítástechnikájában. Hasonló úton indult el az Apple a Dylan rendszerével, a Microsoft pedig a Blackbird-del, emlegetnek egy Python nyelvet, a Free Software Foundation is foglalkozik virtuális gépen alapuló program-interpretálással és még lehetne sorolni a hasonól célú nyelveket, rendszereket. file:///E|/docs/Untitled/article.html (9 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu Ha a Jáva nyelv mégis elterjed - márpedig szerintem erre minden esély megvan -, akkor ehhez hozzájárul a jó reklám, az ügyes marketing stratégia valamint a
felhasználók és legfõképpen a szoftvergyártók erkölcsi és anyagi támogatása. Márpedig a szoftvergyártók tényleg ráharapni látszanak az új technológiára, olyannyira, hogy reménytelennek látszik teljes felsorolást adni azokról a cégekrõl, amelyek csatlakoztak, forrás licenszet vásároltak. Remélem nem sértem meg a kimaradókat, a teljesség igénye nélkül: a Sun-nál külön részleget hoztak létre a Jáva fejlesztésekre. A WWW szempontjából talán a legjelentõsebb esemény, hogy a Netscape megvásárolta a technológiát és integrálja az új böngészõjébe. Windows 95 alatti fejlesztõrendszerrel jelent meg a Symantec, hasonló termék kifejlesztését jelentette be a Borland, megvásárolta a technológia felhasználási jogát az IBM, sõt még a Microsoft is komolyan érdeklõdik. Ha már a licenszekrõl beszéltem: nincs szükség licenszre ahhoz, hogy valaki Jáva programot illetve programkákat fejlesszen, a lefordított programot
terjessze. Azon OEM szoftverfejlesztõk, akik a Jáva technológiát integrálni akarják termékeikbe, forrás licenszet vásárolhatnak. A Jáva technológiához kapcsolódóan csomó név és grafika a Sun - regisztrált - védjegye. Ezek közül a cikk elején látott Duke és a HotJava szimbóluma, a gõzölgõ kávéscsésze csak a Sun által használható. Hamarosan lesz egy ún. "Jávával turbósított" (Java Powered) grafika az olyan WWW lapokhoz, amelyek Jáva programkákat tartalmaznak, valamint egy "Jávával kompatibilis" (Java Compatible) grafika azon OEM termékeknek, amelyek elõállítói megvásárolták a forrás licenszet, termékükbe beépítették ezt a technológiát - pl. új architektúrára implementálták a virtuális gépet - és sikeresen megfeleltek a - most készülõ - kompatibilitási tesztnek. Ha valaki Jáva programokat akar fejleszteni, legegyszerûbb, ha a Sun-tól ingyenesen letölthetõ Jáva Fejlesztõi Csomagot (Java
Development Kit) használja, ami tartalmaz egy fordítóprogramot (javac), egy nyomkövetõt, hibakeresõt (jdb) a futtatáshoz szükséges virtuális gépet és egy a programkákat futtató alkalmazást (AppletViewer). A Sun a JDK-t csak a Solaris 2x, Windows 95 és Windows NT operációs rendszerekre készítette el, de más fejlesztõk nagyon sok egyéb elterjedt operációs rendszerre is hordozták. Igen, van a Linux-on is Komoly fejlesztéshez használhatók az integrált fejlesztõi környezetek (Integrated Development Environment, IDE), jelenleg a legismertebbek a Sun, a Microsoft és a Symantec termékei. A programkák futtatására pedig jók például a Netscape Navigator, illetve a Microsoft Internet Explorer Web böngészõk is. A Netscape csaknem minden elterjedt architektúrán fut, a Microsoft egyelõre csak a Windows 95/NT rendszeren, bár mindkét cég igéri a Windows 3.11-es változatát is Végezetül néhány kérdés, kétely Duke A Jáva technológia hatalmas
léptekkel fejlõdik. Látszólag nagy a nyomás fejlesztõgárdán, hogy minél hamarabb "végleges" változattal álljanak elõ. A nagy sietségben maradhatnak a rendszerben átgondolatlan, elnagyolt megoldások. "Jó" - azaz rossz - példa erre a grafikus programozási könyvtár (AWT, Abstract Windowing Toolkit) esete, amelyet az alfa és béta verzió között teljesen átírtak, file:///E|/docs/Untitled/article.html (10 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu de, bár mûködik, - nem csak - nekem még ez a mostani sem nagyon tetszik: a fejlesztõk beismerték, hogy a Netscape sürgette õket. Persze az objektumorientált könyvtárak bõvíthetõk, akár lecserélhetõk is, de nem mindegy, mi kerül az 1.0-s verzió specifikációba "Ami tapad az ragad", a korábbi verziókkal való kompatibilitás megõrzése miatt a rendszerek teherként hurcolják magukkal az elsõ verziók elsietett döntéseit. Az sem
látszik még, hogy a technológiát mennyire fogja egy-két erõs cég a saját érdekeinek megfelelõ irányba elvinni, avagy megmarad-e szélesebb körû érdekeket, véleményeket tükrözõ, nyílt technológiának. A C++ nyelvre is ráfért az elmúlt években bekövetkezett, széles felhasználói kört megmozgató tisztázási, szabványosítási eljárás, gondolom a Jávának sem ártana. Nem látom például, hogy azon felül, hogy a Jáva karakterei 16 bites Unicode rendszerben vannak ábrázolva, valaki foglalkozna a nemzetköziesítés (internalization) kérdéseivel. Sokan attól is félnek, hogy a "végleges" verzió megjelenése után a SUN szigorít a licensz politikáján, túl költségessé teszi a fejlesztõrendszerét, vagy pl. a HotJava-t A WWW hálózat terjedésében jelentõs szerepet játszott az a tény, hogy a szükséges programok - kiszolgálók is, böngészõk is - szabadon hozzáférhetõk, ingyenesek voltak. Bár jelenleg a Netscape uralni
látszik a böngészõk piacát, de nem biztos, hogy mindenki meg tudja, vagy akarja fizetni ennek az árát. Kérdés, hogy más kereskedelmi, vagy szabadon terjesztett böngészõk mennyire veszik át a Jáva technológiát, a WWW szerverek üzemeltetõi, a HTML lapok szerzõi mekkora potenciális, Jávát értõ olvasótáborra számíthatnak. Kiváncsi vagyok, hogy a felhasználók - fõleg a nagy cégek - mennyire fogadják el a rendszerbe beépített biztonsági mechanizmusokat. Elsõ ránézésre megbízhatónak - ha néha túl korlátozottnak is - tûnik a rendszer, ám tapasztalatok szerint a vírusírók zseniálisak. Ha elõbukkan néhány biztonsági luk, a felhasználók bizalma hamar megcsappanhat, elvégre a hálózaton letöltött programok hiányos védelmi rendszer mellett potenciálisan hatalmas zûröket okozhatnak a helyi rendszerben. Mindezen kérdések ellenére én bizalommal tekintek a Jáva jövõjére. Lábjegyzetek 1 Talán sokan emlékeznek rá, hogy a
SUN-nál már korábban is kitaláltak olyan érdekes, innovatív technológiákat, amelyek az üzleti vetélytársaknak nem nagyon tetszettek. Volt egyszer például egy News ablakozó rendszer, ami ellen elkezdték támogatni az MIT-n folyó X Window rendszer fejlesztést és létrehozták az X Konzorcium-ot. Késõbb a SUN beadta a derekát, õ is átállt az X-re, de ragaszkodott a saját ablakkezelõjéhez, az OpenWindows-hoz. Hát ezt sem szerették, így létrejött a Motif, és a SUN újra beadta a derekát . 2 file:///E|/docs/Untitled/article.html (11 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu Bár itt Magyarországon a Jáva szót hallva az Indonéz szigetvilág egyik legnagyobb szigetére gondolunk, az amerikaiak inkább - a kezdetben onnan importált - kávéra (az elkészített italra) asszociálnak. Ezért találhatók a témakörben olyan elnevezések, mint HotJava, Digital Espresso Fontosabb WWW címek Elsõdleges
információforrások Sun JavaSoft részlegének címlapja Jáva 1.0 Fejlesztõi készlet Java World elektronikus újság Jáva hírcsoport Digital Espresso, hetenkénti összefoglalója a Jáva világ eseményeinek Jáva gyûjtemények Yahoo Jáva gyûjteménye Gamelan Directory: a legnagyobb Jávával kapcsolatos gyûjtemény "Jáva Fejlesztõknek" a Digital Focus-tól John December összeállítása az online Jáva információkról Jáva Virtuális Könyvtár (ACM) Java User Resource Network Programkák a JavaSoft-nál Jáva GYIK-ok (Gyakran Ismétlõdõ Kérdések, FAQ) Jáva GYIK-ok gyûjtemény Eliotte Rusty Harold GYIK-ja comp.langjava GYIK-ja Bevezetõk a Jávával ismerkedõknek Sun bevezetõje file:///E|/docs/Untitled/article.html (12 of 13)20040118 3:01:02 A Jáva programozási nyelv Forrás: http://www.doksihu Eliotte Rusty Harold bevezetõje Nelson Yu bevezetõi a Jáváról és az AWT-rõl "Hogyan kell ." a Digital
Focus-tól Java Workshop (Thingtone) Jáva könyvekrõl A már megjelent és megjelenés elõtt álló könyvekrõl The Java Series at Addison Wesley Kiss István updated: 96/06/15, http://www.eunethu/infopen/cikkek/java/articlehtm file:///E|/docs/Untitled/article.html (13 of 13)20040118 3:01:02 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu A Jáva programozási nyelv rejtelmei Tartalomjegyzék: Az alapok Egy példaprogram A program szerkezete Változók és értékek Megjegyzések a programban A fõprogram Vezérlési szerkezetek Kivételkezelés A program törzse Módszerek Hálózati kommunikáció Fordítás, futtatás Objektumorientált programozás Jáva módra Absztrakt adattípusok létrehozása Objektumok Osztályok definíciója Egyedváltozók Módszerek Konstruktorok Osztályváltozók és -módszerek Tömbök Szövegek Pakkok Láthatóság Öröklõdés és következményei Osztályok leszármaztatása Láthatóság Mi öröklõdik, és mi
nem Polimorfizmus Interfészek Szálak Szálak létrehozása file:///E|/docs/Untitled/javaprog.html (1 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu Szálak futása Ütemezés Szinkronizáció és kommunikáció Programkák Különbségek a programkák és a programok között A programkák szerkezete A futás vezérlése Rajzolás Programkák egy Web oldalon Az alapok Ismeretes, hogy a Jáva nyelv a C++ nyelvbõl született, sok helyen egyszerûsítve, esetenként bõvítve azt. Az ismertetõben feltételezem, hogy az olvasó legalább a C nyelvet alaposan ismeri, bár C++ nyelv, illetve az objektumorientált programozás fogalmainak ismerete sem árthat. Azt is remélem, hogy az olvasó nem riad vissza, ha az Internet hálózat világából vett szolgáltatásokat, protokollokat emlegetek. Egy példaprogram Tapasztalataim szerint egy programozási nyelvet a száraz ismertetés helyett példákat követve könnyebb megérteni. Persze
nem könnyû az ismerkedés elejére érthetõ, rövid, de nem túlzottan egyszerû példát találni és sajnos a "Szervusz világ!" programot már megmutattam. A bevezetõ példa a Internet hálózat világába visz el bennünket. A drótposta (email) továbbítására itt az ún. SMTP (Simple Mail Transfer Protocol) protokoll használatos A levéltovábbító programok (Message Transfer Agent, általában a sendmail program) a 25-ös TCP kapun várakoznak arra, hogy valaki kiépítse velük a kapcsolatot, ha a kapcsolat létrejött, egy nagyon egyszerû, karakterorientált párbeszédbe kezdenek a hívóval. A párbeszéd ritkán használt, de néha nagyon hasznos parancsa, a VRFY (Verify) segítségével megkérdezhetjük egy SMTP kiszolgálótól, hogy egy adott nevû felhasználónak van-e a gépen postaládája. A mi programunk pontosan ezt csinálja, a java SMTPclient host user parancs hatására a host számítógép SMTP szerverétõl a user felhasználó felõl
érdeklõdik, a kapott választ pedig kiírja a konzolra. file:///E|/docs/Untitled/javaprog.html (2 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu Lássunk egy példa párbeszédet a két gép között! Dõlt betûkkel a megszólított SMTP kiszolgáló (a hapci. mmt.bmehu gépen), normális betûkkel az ügyfél, a mi programunk (a tudormmtbmehu gépen) üzenetei láthatók. A példa egy sikeres és egy sikertelen lekérdezést is tartalmaz 220 hapci.mmtbmehu 565c8/BMEIDA-144 Sendmail is ready at Wed, 14 Feb 1996 17:31:03 +0100 HELO tudor.mmtbmehu 250 Hello tudor.mmtbmehu, pleased to meet you VRFY kiss 250 Kiss Istvan <kiss> VRFY duke 550 duke. User unknown QUIT 221 tudor.mmtbmehu closing connection Látható, hogy a kiszolgáló minden üzenetét egy számmal is kódolja. A program szerkezete A programok import utasításokkal kezdõdhetnek, felsorolva a programban felhasznált könyvtárak nevét. Ez nem kötelezõ, az egyes
könyvtári elemekre való hivatkozásnál is megadhatjuk a könyvtár nevét. C programozók figyelem: ez nem #include parancs, nem a fordítóprogramnak szóló üzenet a forrásszöveg beolvasására. Az import a kapcsolatszerkesztõnek, betöltõnek szól, már lefordított kódú könyvtárakra hivatkozik. Importálásnál csomagokból (package) osztályokat (class) importálunk, azaz a programunkban felhasználhatóvá tesszük. A csillag az adott csomag összes osztályát jelenti import java.net*; import java.io*; import java.lang*; import java.util*; Ezután rögtön egy osztálydeklarációnak kell következni, a Jáva programban minden változó, minden utasítás csak osztályok törzsében szerepelhet. Eltûntek a C globális változói, globális függvényei Aki most lát elõször C++-ból átvett osztálydeklarációt, ne essen kétségbe, egyelõre fogadja el, hogy még a legegyszerûbb Jáva program is a class osztálynév { . } mintát követi. Az osztálynév-ben,
mint a Jáva minden azonosítójában, a kis- és nagybetûk különbözõek file:///E|/docs/Untitled/javaprog.html (3 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu class SMTPclient { Változók és értékek Az osztályok belsejében változókat deklarálhatunk, a deklaráció szintaxisa egy-két módosító alapszó (static vagy final) kivételével megfelel a C-nek: típus változónév [ = kezdeti érték ] A nyelv tartalmaz néhány beépített, egyszerû adattípust, amelynek neve és értékkészlete a következõ táblázatban található: egész típusok byte 8 bit kettes komplemens short 16 bit kettes komplemens 32 bit kettes komplemens int 64 bit kettes komplemens long valós típusok float 32 bit IEEE 754 lebegõpontos double 64 bit IEEE 754 lebegõpontos karakter típus char 16 bites Unicode karakter kód logikai boolean true vagy false Látható, hogy csak elõjeles egész típusok vannak, bár ez nem jelenti azt, hogy nem
lehet rájuk például a szokásos bitmûveletek alkalmazni. A C-tõl eltérés az is, hogy itt az egyes beépített típusok mérete, helyfoglalása nyelvi szinten definiált, nem függ a programot futtató gép architektúrájától. A karakterek tárolásánál a nemzetközileg elfogadott, 16 bites Unicode-ot használják. static final int SMTPport = 25; A Jávában nincs #define, sem a C++ const-ja, ennek a legközelebbi megfelelõje a final változó, a fordítóprogram gondoskodik róla, hogy ennek értéke ne változhasson meg. Látható, hogy a változó deklarációjával együtt kezdeti értéket is adhatunk neki, ez persze final változó esetén kötelezõ. A static módosító egyelõre ne zavarjon bennünket, pontos jelentésére majd az osztályok ismertetésénél térünk ki. Elöljáróban csak annyit, hogy ezek azonosak a C++-ból ismert osztályváltozókkal és ezek közelítik meg leginkább a szokásos nyelvek globális változóit. A beépített numerikus
típusokon a C-bõl jól ismert mûveletek értelmezettek. Az numerikus típusú file:///E|/docs/Untitled/javaprog.html (4 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu értékekkel a szokásos aritmetikai mûveletek használhatók. Az egész típusú értékekre használható bit mûveletek kiegészültek a >>> operátorral, amely jobbra léptetésnél 0-t és nem az elõjelet lépteti be a legnagyobb helyiértékû bitre. Ezek az operátorok értékadással is kombinálhatók, pl: +=, /=, A logikai értékek a C-vel ellentétben nem egész típusúak. Azonos típusú értékek összehasonlítására használt operátorok logikai értéket állítanak elõ, ilyen értékekre használhatók az ismert logikai mûveletek is. A következõ táblázat tartalmazza a Jáva nyelv összes operátorát - némelyikrõl egyelõre nem beszéltem precedenciájuk csökkenõ sorrendjében: (pre- vagy poszt-) inkremens és dekremens, ++ -logikai
és bitenkénti negálás, ! ~ típus ellenõrzés instanceof 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 &= |= <<= >>= >>>= Az egyszerû, beépített típusokon túl a Jáva csak kétfajta összetett adattípust tartalmaz, a programozók által definiálható osztályokat (class) illetve a tömböket (array), amelyek egyébként teljes értékû osztályok. Nincs struct, union, de nincs typedef sem, sõt mutatók (pointer) sincsenek! static Socket smtpconn; static DataInputStream instream; static DataOutputStream outstream; A fenti 3 sor a szabványos Jáva könyvtárakban definiált osztályok - Socket, DataInputStream, DataOutputStream - egy-egy
példányának, egyedének (objektum) foglal helyet, pontosabban ezek egyelõre csak üres hivatkozások, az objektumok még nem jöttek létre. file:///E|/docs/Untitled/javaprog.html (5 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu Megjegyzések a programban // Program: drótposta címek ellenõrzése SMTP kiszolgáló segítségével // Használata: // java SMTPclient <host> <user> A Jáva örökölte a C-bõl a /* . */ stílusú megjegyzés szintaxist, a C++-ból a //-val kezdõdõ egysoros megjegyzéseket, végül a /* . */ alakú megjegyzések a kiegészítõ dokumentációs rendszerrel (javadoc) együtt használhatók. A fõprogram Minden Jáva alkalmazásnak, pontosabban az egyik osztályának - mivel a Jávában minden utasítás csak osztályok definíciójában szerepelhet - tartalmaznia kell egy main nevû, itt következõ fejlécû függvényt: public static void main (String args[]) { A public a módszer
láthatóságáról nyilatkozik, jelentése: bárhonnan meghívható. A static jelentésérõl egyelõre annyit, hogy az eljárás csak osztályváltozót használ, void a módszer visszatérési értékének típusa: nem ad vissza értéket. A Jáva alkalmazás futtatását a virtuális gép a main eljárás végrehajtásával kezdi A main eljárás paramétere egy szövegtömb, amelynek egyes elemei a parancssorban megadott argumentumokat tartalmazzák. A szövegek tárolására, kezelésére szolgáló String egy elõre definiált osztály, nem pedig karaktertömb, mint a C-ben. A tömbök indexértékei itt is nullától kezdõdnek, viszont itt az args[0] nem a program nevét adja vissza, mint a C-ben, hanem ténylegesen az elsõ argumentumot. Akinek hiányzik a megszokott argc argumentumok száma paraméter, ne aggódjon, a Jáva tömbök méretét futás közben is le lehet kérdezni. Az egyes eljárásokban természetesen használhatunk lokális változókat, itt a String
osztály egyedére lesz szükségünk, amelyet deklarációjával egyidejûleg a new parancs segítségével létre is hozzuk. String res = new String(); Lokális változókat a módszerek törzsében tetszõleges helyen deklarálhatunk, sõt az egyes programblokkok - { . } - saját, máshonnan nem látható lokális változókkal rendelkezhetnek Vezérlési szerkezetek file:///E|/docs/Untitled/javaprog.html (6 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu Kezdjük a programunkat azzal, hogy megvizsgáljuk, megfelelõ számú argumentummal hívták-e meg! Amennyiben a programnak nem 2 argumentuma volt - az SMTP kiszolgáló és a keresett felhasználó neve -, tájékoztató üzenetet írunk ki és befejezzük a program mûködését. if (args.length != 2) { System.outprintln("Usage:"); System.outprintln(" java SMTPclient <host> <user>"); System.exit(1); } A System könyvtár a Jáva programok futtatásához
szükséges objektumokat, módszereket tartalmazza. Ilyen a programok szabványos kimenetét (standard output) - pl. konzol periféria - megvalósító out objektum. A kiíró eljárás a print illetve println, amelynek csak egyetlen paramétere van, de elég "intelligens" ahhoz, hogy karakteres formában tetszõleges típusú értéket (igen, még a felhasználó által definiált objektumokét is) "megjelenítsen". A programunkban csak szövegek kiíratására fogjuk használni. A println módszer a paraméterének kiírása után még egy új sort is kiír A programból vagy a main módszer befejezésével, vagy a System könyvtár exit módszerének meghívásával lehet kilépni. A Jáva nyelv átvette a C vezérlési szerkezeteit, az elágazásokhoz az if-else és switch; ismétlésekre, ciklusszervezésre a for, while és do-while utasítások használhatók. Eltérés, hogy az összes feltételnek logikai értéknek kell lennie, int nem használható, ezért
a fordítóprogram kiszûri a C programozók "kedvenc" hibáját, amikor if-ben értékadást ("=") írunk egyenlõség-vizsgálat ("==") helyett. A nyelvbõl kimaradt az ugró utasítás (goto), de megmaradtak a címkék (label). A címkéket ciklusutasítások megjelölésére használhatjuk, így a ciklus törzsében kiadott break és continue utasítások nem csak a legbelsõ, hanem bármelyik, címkével ellátott beágyazó ciklusra hivatkozhatnak. Kivételkezelés Van még egy utasításcsoport, amely a program végrehajtásnak sorrendjét befolyásolhatja, a try-catchthrow csoport, amely nagyon hasonló formában a C++ nyelvben is megtalálható. A tisztességesen megírt C programok legnagyobb problémáját az egyes eljárások végrehajtása közben esetleg elõbukkanó hibák, ún. kivételek (exception) lekezelése jelenti Kisebb gondossággal megírt programoknál a programozó hajlamos elfeledkezni arról, hogy legtöbbször az eljárás
visszatérési értékének tesztelésével ellenõrizze, sikerült-e a végrehajtott mûvelet. Ha mégis megteszi, leggyakrabban egyszerûen befejezi a programot, olyan bonyolult a hiba elõbukkanását és okát "felfelé" terjeszteni és a file:///E|/docs/Untitled/javaprog.html (7 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu megfelelõ helyen lekezelni azt. Ezen segíthetnek a fenti utasítások Most csak a felületesen ismerkedhetünk meg a kivételkezelés rejtelmeivel, majd késõbb részletesen visszatérünk a témához. try { Egy try blokkba zárt utasításcsoporton belül bárhol elõforduló kivétel hatására a program normális futása abbamarad és a vezérlés automatikusan a catch blokkra kerül. Itt a catch paramétereként megkapjuk a hiba okát - általában egy Exception típusú objektumot -, aztán kezdjünk vele, amit tudunk. A példaprogramunk egyszerûen kiírja a hiba okát. A programozó maga is
definiálhat ilyen kivételeket, amiket - no meg az egyes catch blokkokban lekezelhetetlen kivételeket - a throw utasítással felfele passzolhatunk, amíg valaki - legrosszabb esetben a virtuális gép - "lekezeli". A program törzse A programunk szerencsére nagyon egyszerû: kiépítjük az SMTP kapcsolatot az elsõ argumentumként megadott géppel: openSMTPconnection(args[0]); Elküldünk egy HELO üzenetet, hozzáfûzve a saját gépünk nevét (részletekrõl majd máskor), a visszakapott választ (res tartalma) nem használjuk. res = sendMessage("HELO " + java.netInetAddressgetLocalHost() getHostName()); Elküldünk egy VRFY üzenetet a második argumentumként megkapott felhasználó nevével. A visszakapott választ kiírjuk. res = sendMessage("VRFY " + args[1]); System.outprintln(res); Elküldjük a búcsúzó QUIT üzenetet és lezárjuk a kapcsolatot. res = sendMessage("QUIT"); closeSMTPconnection(); } Bármi hiba történt,
kiírjuk a program kimenetre. file:///E|/docs/Untitled/javaprog.html (8 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu catch(Exception e) { System.outprintln("Error: " + etoString()); } }; Egész egyszerû, nemde? Persze csaltam, azért ilyen egyszerû minden, mert "magasszintû", a feladathoz alkalmazkodó eljárásokat használtam. Ezeket még definiálni kell, mert sajnos nem szerepelnek a Jáva könyvtárakban. Módszerek Emlékeznek még arra, hogy egy osztály - SMTPclient - belsejében vagyunk? Az osztályok belsejében definiált függvényeket az objektumorientált terminológia szerint módszereknek (method) hívják. Definíciójuk nem különbözik a C-ben megszokottaktól, persze a mi programunkban a main-hez hasonlóan itt is meg kell adni a static módosítót, mert ezek a módszerek is használják a fent definiált osztályváltozókat. static void openSMTPconnection (String host) throws IOException {
Persze a korábban megismert kivételkezelés belezavar a képbe: a Jáva nyelv megköveteli, hogy a módszerekben elõforduló kivételeket vagy le kell kezelni, vagy deklarálni kell, hogy lekezeletlenül továbbadjuk. A módszer fejében a throws parancs erre szolgál (Megjegyzés: a lekezeletlen kivételek deklarálásának szabálya alól is vannak "kivételek", de errõl is csak késõbb.) Hálózati kommunikáció A programhoz szükséges hálózati kommunikációt szerencsére a Jáva net könyvtára segítségével könnyû megoldani. A részletek mellõzésével: a könyvtár definiál egy Socket osztályt, amely egyszerû TCP kapcsolat kiépítésére és azon adatok átvitelére szolgál. Elõször létrehozunk egy új Socket-et, egyben megnyitva az összeköttetést a paraméterként megkapott gép 25-ös (SMTP kiszolgáló) kapujával (port). smtpconn = new Socket(host, SMTPport); Az átvitelre két - input és output - stream objektum szolgál, amelyeket a
get.Stream eljárással kibányászunk a kapcsolatból. file:///E|/docs/Untitled/javaprog.html (9 of 34)20040118 3:01:04 A Jáva programozási nyelv rejtelmei Forrás: http://www.doksihu instream = new DataInputStream(smtpconn.getInputStream()); outstream = new DataOutputStream(smtpconn.getOutputStream ()); Ezen stream-ek segítségével már közvetlenül olvashatunk vagy írhatunk a kiépült kapcsolaton. Itt az elsõ beérkezõ sort - az SMTP kiszolgáló bejelentkezõ üzenetét - egyszerûen eldobjuk. String dummy = instream.readLine(); }; A kapcsolat lezárása egyszerû: static void closeSMTPconnection () throws IOException { smtpconn.close(); }; Egy SMTP üzenet kiküldéséhez egy kicsit ügyeskednünk kell: static String sendMessage(String msg) throws IOException { Elõször is a kiküldendõ üzenetet - a String típusú msg paramétert - Byte-okká alakítva kell elküldeni. Ne feledjük el, hogy a Jáva a karakterek tárolására - és egy szöveg is ezekbõl áll - 16
Bites Unicode-ot használ, a szegény SMTP kiszolgáló alaposan meg lenne lepve, ha ezt kapná. A Byte-sorozat végére még odabiggyesztjük a protokoll által megkívánt CR és LF karaktereket. Legalább látunk arra is példát, hogyan lehet - úgy, mint a C-ben - karakter konstansokat megadni. outstream.writeBytes(msg); outstream.write('