01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti...

106
JAVA gyakorlat Tartalomjegyzék Bevezetés......................................................2 Alapozás.......................................................9 Csomagok......................................................13 Függvények....................................................14 Kivételek.....................................................14 Objektumorientált alapok......................................17 Absztrakt Adattípus...........................................22 OO gyakorló feladatok.........................................27 Streamek......................................................30 IO Gyakorlás..................................................34 Gyűjtemény keretrendszer......................................36 Generic.......................................................40 Reflection....................................................43 GUI...........................................................46 GUI Kiegészítés...............................................50 Networking....................................................54 Threading.....................................................58 Threading - Kiegészítés.......................................66 Kapcsolat az adatbázissal.....................................70 Szerializáció.................................................74 Remote Method Invocation......................................77 Környezet beállítása..........................................80 Gyakran előforduló hibák......................................84 1 / 106

Transcript of 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti...

Page 1: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

JAVA gyakorlat

TartalomjegyzékBevezetés.......................................................................................................................................2Alapozás........................................................................................................................................9Csomagok....................................................................................................................................13Függvények..................................................................................................................................14Kivételek......................................................................................................................................14Objektumorientált alapok............................................................................................................17Absztrakt Adattípus.....................................................................................................................22OO gyakorló feladatok................................................................................................................27Streamek......................................................................................................................................30IO Gyakorlás................................................................................................................................34Gyűjtemény keretrendszer...........................................................................................................36Generic.........................................................................................................................................40Reflection.....................................................................................................................................43GUI..............................................................................................................................................46GUI Kiegészítés...........................................................................................................................50Networking..................................................................................................................................54Threading.....................................................................................................................................58Threading - Kiegészítés...............................................................................................................66Kapcsolat az adatbázissal............................................................................................................70Szerializáció.................................................................................................................................74Remote Method Invocation.........................................................................................................77Környezet beállítása.....................................................................................................................80Gyakran előforduló hibák............................................................................................................84

1 / 89

Page 2: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

BevezetésA Java nyelvről, általánosan.

Linkek

A tárgy honlapja Kozsik Tamás oldalán: http://aszt.inf.elte.hu/~kto/teaching/java/ Oracle Java oldala http://www.oracle.com/technetwork/java/index.html Java Development Kit (JDK) fejlesztői környezet (fordító, stb.), Java Runtime Environment (JRE) csak futtatói környezet Java forráskód egy (jó) része nyílt, a forrás megtalálható a JDK könyvtárában (src.zip fájl) Elsődleges információforrások:

o Java referencia alapvető fontosságú http://download.oracle.com/javase/6/docs/api/ o Java tutorial http://download.oracle.com/javase/tutorial/reallybigindex.html vagy Java 5.0 Útikalauz

programozóknak (Nyékyné)o Java Language Specification Harmadik kiadás, rendes specifikáció, HTML, PDF formátumban.

http://java.sun.com/docs/books/jls/ Közösségi oldalak, levlisták, fórumok, stb.

o Java levlista http://lists.javaforum.hu/mailman/listinfo/javalist o Javagrund http://javagrund.hu/web/java/index (pillanatnyilag offline, amíg az Oracle-lel nem rendeződnek

a dolgok)o Javaforum http://www.javaforum.hu/javaforum

Környezetek ízlés szerint o Konzol (ld. a megfelelő mellékletet)o Eclipse http://www.eclipse.org/downloads/ o NetBeans http://netbeans.org/downloads/

Hello World

Hozzatok létre egy HelloWorldApp.java nevű állományt a következő tartalommal:

/** * Hello world program. */public class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); }}

Fontos, hogy a fájl neve megegyezzen a benne definiált publikus osztály nevével (tehát ha XXX.java a fájl neve, akkor benne egy darab publikus osztály, public class XXX definícióval, különben beszól a fordító).

Std. Output System.out.println( ... ); Std. Error System.err.println( ... ); Escape sequences \r, \n, \t, \b, stb. Részletesen: http://download.oracle.com/javase/tutorial/java/data/characters.html Kilépés System.exit( 0 ); Egyéb függvények a System osztály leírásában: http://download.oracle.com/javase/6/docs/api/java/lang/System.html Konzol kezelése java.io.Console osztály segítségével:

http://download.oracle.com/javase/6/docs/api/java/io/Console.html

Környezet beállítása

Windows alatt Windows + R, majd cmd.exe:

C:\Users\rlegendi> PATH=%PATH%;C:\Program Files\Java\jdk1.6.0_21\binC:\Users\rlegendi> echo %PATH%...;C:\Pogram Files\Java\jdk1.6.0_21\binC:\Users\rlegendi> javac -versionjavac 1.6.0_21

Ha nem akarod minden használat előtt ezt eljátszani, akkor Windows + Break, Advanced system settings, Environment variables..., és a PATH végéhez hozzáfűzöd a megadott elérési utat.

Megjegyzés Itt az ELTE-n Windows alatt nem valószínű, hogy lesz jogotok a globális PATH változó beállítására. Érdemes erre egy egyszerű batch/ps scriptet készíteni. Linuxon ilyen probléma nincs.

2 / 89

Page 3: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Fordítás

javac HelloWorldApp.java

Használható *.java a default package fordítására.

Futtatás

java HelloWorldApp

(.class nélkül!)

Dokumentáció generálás

javadoc HelloWorldApp.java

Részletesen http://download.oracle.com/javase/tutorial/getStarted/cupojava/win32.html Ezen tutorial magyar fordítása megtalálható a feladatgyűjtemény mellékleteként.

Kódolási konvenciók

package java.blah; // top-level domain, kisbetus karakterek

/** * Osztalyleiras.. * * @version 1.0 * @author Mr. T */public class Foo extends Bar {

/** classVar1 egysoros comment. */ public int classVar1;

/** * classVar2, aminek meg tobbsoros * a leirasa. */ private static String classVar2;

/** * Konstruktor komment... */ public Foo() { // ... }

/** * Fuggveny komment... */ public void doSomething() { // ... }

/** * Valami masik fuggveny komment... * * @param someParam valami parameter * @return valami ertek */ public int returnSomeValue(Object someParam) { // ... }

/** * Logikai fuggveny... */ public boolean isSomething() { // ... }}

Egyelőre ökölszabály Osztály név = fájl név, nagybetűvel kezdődik. Csomag név = könyvtár név, kisbetűvel kezdődik (később lesz több osztály is egy fordítási egységen belül).

Részletesen http://www.oracle.com/technetwork/java/codeconv-138413.html

3 / 89

Page 4: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Kiegészítés Ékezetes karaktereket ne használjatok! Főleg azonosítók esetében ne! A Java ugyan ezt megengedi (minden UTF-8 karakter használható azonosítóban, ugyanakkor a különböző környezetekbe való konvertáláskor (latin2 ↔ UTF-8 ↔ Cp1250) összetörnek a karakterek! Az ilyen forrásokat fordítani, következésképp értékelni sem tudom.

Típusok

Primitív típusok:

byte, short, int, long, float, double, char, boolean default értékek (0, false, stb.) oktális (int octVal = 01), hexa érték (byte hexVal = 0xff), scientific notation (double d = 1.23e4) wrapper osztályok (Byte, Short, Integer, ...)

Konverziók:

bővítő automatikus szűkítő típuskényszerítéssel (byte b = (byte) 10)

Szövegkonverzió:

Stringgé: String s = "" + 1; (precedenciára figyelni!) Stringből: Integer.parseInt("1"), Double.parseDouble("2.0"), ...

Valós számok

A gépi számábrázolás rengeteg problémát vet fel, amik még egy tapasztaltabb programozónak is okozhatnak kellemetlen meglepetéseket. Ezt elkerülve igyekszem leírni pár olyan tipikus hibát, amikbe bele lehet esni, és igyekszem rávilágítani, hogy hogyan lehet azokat megoldani (amennyiben egyáltalán van rá lehetőség).

Ez az alfejezet nem csak és kizárólag Java programozóknak szól: általában a programozási nyelvekben előjövő gyakorlati tanácsokat találhattok összefoglalva.

Aki esetleg mélyebben érdeklődne, a Numerikus Analízis c. tárgy keretein belül részleteiben tárgyaljátok ezt a témakört.

Approximáció

A gépeken tárolt valós változók közelítések, approximációk. Alapvetően kétféle megközelítést használnak a programozási nyelvek: fixpontos ill. lebegőpontos ábrázolásmódot. Előbbit úgy képzeljétek el, hogy fix számú biten tárolják az előjelet, egészrészt valamint a törtrészt (ez már maga komoly numerikus hibákkal járhat), utóbbinál pedig a következő formában: (-1)^s * m * 10^k, ahol 0 <= |m| <= 10 a mantissza, k pedig a karakterisztika (ezt hívják normál alaknak, a bináris reprezentációban tízes alap helyett kettest használnak). Van nyelv, ami az egyiket, van, ami a másikat támogatja, és van, ami mindkettőt (pl. a Pascal, Ada).

A legtöbb programozási nyelv az 1985-ben elfogadott IEE 754 szabvány szerint kezeli a számokat, ezek alól a Java sem kivétel.

Ami a lényeg: ha leírsz egy számot, az közelítés, hiába gondolsz bármi mást. Mutatok egy példát:

// Az eredmenye: 1System.out.println( 0.2 + 0.2 + 0.2 + 0.2 + 0.2 );

Ez többé-kevésbé egybevág az ember intuitív elvárásával. Ez viszont teljesen véletlen, a csillagok állásának köszönhető: azon múlt, hogy a 0.2d egyike azon ritka valós számoknak, amely viszonylag kis numerikus hiba mellett ábrázolható.

Próbáljuk meg például a fenti kódot 0.1 értékekkel:

// Az eredmenye: 1.0000001System.out.println( 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f );

// Az eredmenye: 0.9999999999999999System.out.println( 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d );

Ezzel sajnos nem tudsz mit csinálni. Sőt, további gondokhoz vezet. Nézzünk erre most néhány példát a következő alfejezetekben!

4 / 89

Page 5: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Az == operátor

A fenti pont egy következménye, hogy ha leírunk egy ilyen kifejezést:

// Akkor az bizony hamis lesz:System.out.println( 0.3 == 0.1d + 0.1d + 0.1d );

Ebbe a csapdába egy kezdő programozó könnyen beleeshet, vegyük például a következő számlálós ciklust:

for (double d=0.0; d != 0.3; d += 0.1) { // Hopp! Vegtelen ciklus!}

Mit tudunk akkor hát ezekkel kezdeni? Nos, a legegyszerűbb megoldás az, ha a programozó felállít egy önkényes hibahatárt, amin belül egyezőnek vél két valós számot - azaz annak epszilon környezetébe való tartozást vizsgáljuk egyenlőség helyett. Például:

final double DELTA = 1.0E-5; // Hibahatarfinal double d1 = 0.3;final double d2 = 0.1 + 0.1 + 0.1;

if ( Math.abs( d1 - d2 ) < DELTA ) { System.out.println("d1 == d2");}

Túl-, és alulcsordulás

Ilyet már valószínűleg az egyszerű egész típusosztály körében is láttatok: van minden típusnak egy maximális ill. minimális értéke (Java esetén ezt az Integer.MIN_VALUE, Integer.MAX_VALUE, stb. konstansok deklarálják).

A valós számok esetén is előjönnek ezek a problémák, hatványozottan. Tekintsük a következő példát:

final double big = 1.0e307 * 2000 / 2000;System.out.println( big == 1.0e307 ); // Hamis lesz!

A programkódtól ránézésre intuitív módon az ember igaz értéket várna, azonban hamis lesz! Miért is? Beszorzok egy számot X értékkel, aztán azzal le is osztok, így az eredeti értéket kellene kapnom. Nos, a magyarázat jelen esetben a túlcsordulás: Java szigorú kiértékelési sorrendel rendelkezik (balról jobbra azonos precedenciák esetében). Mikor beszorozzuk a számot, kimegyünk az ábrázolható tartományból, kapunk valami teljesen más értéket (ami jelen esetben ez az Infinity), így azt elosztva X értékkel közel sem az eredeti számot kapjuk vissza. S minderről a programozó semmi visszajelzést nem kap...

A túl kicsi és túl nagy számok esete

A lebegőpontos számábrázolásnak van egy speciális problémája. Matematikában megszokhattátok, hogy adott d1, d2 számok esetén d1 + d2 > d1. Nos, a lebegőpontos ábrázolás ezt is tönkrevághatja: mi van, ha az egyik szám olyan nagy, hogy a másik szám hozzáadása az ő bináris alakján semmi változtatást nem eredményez?

Például:

System.out.println( 1234.0d + 1.0e-13d == 1234.0d ); // Igaz lesz!

WYSINWYG - What You See Is Not What You Get

Cseles módon, mikor kiírunk a konzolra egy valós számot, az nem a reprezentációban használt közelített érték lesz. Azt már tudjuk, hogy a 0.1 nincs tökéletesen ábrázolva, ugyanakkoor ha kiírjuk a képernyőre az értékét, a következőt látjuk:

System.out.println( 0.1d ); // Megjeleno ertek: 0.1

Ajjjaj! Sőt, hogy bonyolítsuk a helyzetet, nézzük csak meg, mi lesz a következő kódrészlet eredménye:

System.out.println(0.1 == 0.099999999999999998); // HamisSystem.out.println(0.1 == 0.099999999999999999); // IgazSystem.out.println(0.1 == 0.100000000000000001); // Igaz

Puff neki. Az első furcsaság, hogy kerekít a kód, ez teljesen jó, de ...998 felett? Nem ...995 körül kéne? Nem.

A másik, hogy a 0.1 ugyanaz, mint 0.099999999999999999? Igen.

5 / 89

Page 6: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Mi ennek az oka? Nos, hogy ezt kicsit megvilágítsuk, nézzük meg a közelített értéket egy speciális osztály segítségével:

// A kiirt ertek: 0.1000000000000000055511151231257827021181583404541015625System.out.println( new BigDecimal(0.1) );

Fura, mi?

És akkor még a nullával való osztásról, a végtelenről, illetve a NaN (Not a Number) értékekről még nem is beszéltünk - de ezek már valamivel több ismeretet igénylő anyagok.

Részletesen

http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html §3.10.2

http://blogs.sun.com/darcy/resource/Wecpskafpa-ACCU.pdf

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.22.6768

http://firstclassthoughts.co.uk/java/traps/big_decimal_traps.html

http://firstclassthoughts.co.uk/java/traps/java_double_traps.html

Tömbök

Minden T típushoz van T[] Példakód:

int[] arr1 = new int[5];int arr2[];

int arr3[] = { 1, 2, 3, 4, 5 };

for (int i=0; i<arr3.length; ++i) { System.out.println(arr3[i]);}

Inicializálásnál az 1. dimenzió megadása kötelező (pl. int[][] arr = new int[5][]; teljesen legális definíció!)

Operátorok

Szokásos operátorok (==, !=, &&, ||, %, ++, -- (prefix, postfix), ...), részletes táblázat itt található: http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html.

Fontos Az operátorok eredményének típusa mindig a bővebb paraméter típusa (double d = 1 / 2; eredménye 0.0 lesz!), de minimum int (pl. byte b = 1+2 nem megy explicit típuskényszerítés nélkül, mert itt 3 egy int értékként szerepel)

Prefix és postfix operátorok (++i, i++) int i = 0; System.out.println(i++); // kiir, megnovel: "0" System.out.println(++i); // megnovel, kiir: "2"

o Mi az eredménye (v.ö. C++)? java int i = 0; System.out.println("" + i++ + ++i); // C++: architektura fuggo

o Szintén, mi lesz az eredménye? java int i=0; i=i++; i=i++; i=++i; System.out.println(i);

Objektumok összehasonlítása

Az equals() metódussal: az == operátor referencia szerinti összehasonlítást végez csak, nem tartalom szerintit.

Stringek összehasonlítása6 / 89

Page 7: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Mint az objektumokat, ugyanúgy az equals() függvény segítségével.

boolean b1 = "a" == "a"; // lehet hamis!boolean b2 = "a".equals("a"); // mindig megfeleloen mukodik

Összehasonlító operátor feltételekben

Baloldalra lehetőleg konstanst írjunk. C++ probléma itt nem lehet, mert 0, != 0 nem szerepelhet elágazás, ciklus terminálási feltételében, kizárólag logikai feltétel, de kellemetlen helyzetek így is adódhatnak:

boolean b = false;

if ( b = true ) { // ...}

Igyekezzünk baloldalra konstansokat írni.

Vezérlési szerkezetek

A nyitó, záró {, } párok kirakása nem kötelező, ellenben javallott.

Elágazások

if ( ... ) { ...} else if (...) { ...} else if ( ... ) { ...} else { ...}

Switch

byte, short, char, int típusokra (ill. ezek csomagoló osztályaira: Character, Byte, Short, Integer) használható (long típusra nem).

final int month = 8;switch (month) { case 1: System.out.println("Jan"); break; case 2: System.out.println("Feb"); break; case 3: System.out.println("Mar"); break; case 4: case 5: case 6: System.out.println("Apr, Maj vagy Jun"); break; default: System.out.println("Egyeb honap");break;}

Ciklusok

while ( true ) { ...}

do { ...} while ( true );

for (inicializalas; terminalo feltetel; leptetes) { ...}

for ( ; ; ) { // vegtelen ciklus ...}

for (String act : args) { // tombokre, iteralhato adatszerkezetekre System.out.println(act);}

Branching kifejezések

7 / 89

Page 8: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

break, continue, return

goto van, de fenntartott szó, nem működik...

+/- Feladatok

Fizz-Buzz Test

Írj egy programot, amely kiírja a számokat 1-től 100-ig! Azon számokhoz, amelyek hárommal oszthatók, a szám helyett "Fizz"-t írjon ki, és azok helyett, amelyek öttel oszthatók, "Buzz"-t. Azon számok helyett, amelyek mind hárommal, mind öttel oszthatók, "FizzBuzz"-t írjon ki!

Motiváció Coding Horror, Why Can't Programmers... program? http://www.codinghorror.com/blog/2007/02/why-cant-programmers-program.html

Példa:

12Fizz4Buzz...1314FizzBuzz

Collatz-sorozat

Írjunk programot, amely előállítja a Collatz-sorozat tagjait az a_0 = N kezdőtagból kiindulva (N<100 parancssori paraméter, ezt ellenőrizzük is!), egészen addig, míg a_n = 1! A sorozat tagjait a következő szabályok alapján generáljuk:

a_{n} = \frac{1}{2}~a_{n-1}, ha ~ a_{n-1} ~ pros $$ ill.a_{n} = 3 * a_{n-1} + 1, ha ~ a_{n-1} ~ ptlan $$

Példa:

> java Collatz 33 10 5 16 8 4 2 1> java Collatz 55 16 8 4 2 1> java Collatz 77 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

Részletesen: http://mathworld.wolfram.com/CollatzProblem.html

Gyakorló feladatok

1. Készítsünk egy hőmérséklet konvertáló programot! Olvassunk be két szám paramétert. Ha az első szám 0, konvertáljuk a második paramétert celsiusról fahrenheit fokra az alábbi képlet alapján (egyébként fahrenheitről celsiusra):

2. C = (F-32) * 5 / 9

3. Készítsünk egy minimális konzolos számológépet! Olvassunk be három szám paramétert! Ha az első szám:o 1, akkor adjuk összeo 2, akkor vonjuk kio 3, akkor szorozzuk összeo 4, akkor osszuk el a másik két paramétert egymással!o Minden egyéb esetben írjuk ki, hogy nem értelmezett művelet!

A megoldáshoz használjunk switch-case szerkezetet!

4. Készítsünk programot, amely egy beolvasott számra eldönti, hogy az egy tökéletes szám-e! Tökéletes számnak nevezzük azokat az egész számokat, amelyek megegyeznek osztóik összegével (1-et beleértve, önmagukat kivéve). A négy legkisebb ilyen szám 6, 28, 496, és 8128.

5. Egészítsük ki az előző feladatot úgy, hogy 1-től a paraméterként megadott határig minden számot ellenőrizzen le, hogy tökéletes szám-e, valamint adja meg, hogy hány ilyen számot talált! Ha nem talált egyetlen számot sem, írja ki, hogy "Egyetlen szám sincs a megadott intervallumban."

8 / 89

Page 9: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

AlapozásVáltozók

Deklaráció, inicializáció Kezdeti érték? Primitív típus, érték? Objektum, referencia? Kifejezések? Kiértékelési sorrend? Szigorúan balról jobbra (v.ö. C++)

Felhasználói interakció

Használjátok a java.io.Console osztályt (JDK 1.6 óta van csak, erre figyeljetek!).

java.io.Console c = System.console();String line = c.readLine();int lineAsInt = Integer.parseInt( line );

Tömbök

Minden T típushoz van T[] Referencia: null értéke lehet! Indexelés nullától Túl-, ill. alul indexelés: ArrayIndexOutOfBoundsException (futásidejű kivétel) Inicializáció:

// barr1, barr2, barr3 ekvivalens definicioboolean[] barr1 = { true, false };boolean[] barr2 = new boolean[] { true, false }; // kifejezesben kotelezo!boolean[] barr3 = new boolean[2];barr3[0] = true; barr3[1] = false;

Tömbök elemei default értéket kapnak (pl. objektum null-t, int 0-t, boolean false-t, stb.) Bejárás: tömb tudja a méretét

int iarr[] = { 1, 2, 3, 4, 5 };

for (int i=0; i<iarr.length; ++i) { System.out.println(iarr[i]);}

Többdimenziós példa:

public static void enumerate(int[][] arr) { for (int i=0; i < arr.length; ++i) { for (int j=0; j < arr[i].length; ++j) { System.out.print( arr[i][j] + " " ); } }}...enumerate( new int[][] { {0, 1}, {2, 3}});

Inicializálásnál az 1. dimenzió megadása kötelező (pl. int[][] arr = new int[5][]; teljesen legális definíció!)

Tömb értékű kifejezések

Inicializálásnál elég az { e_1, e_2, ... } forma. DE! Mindenhol máshol, ahol tömb típusú kifejezést szeretnénk leírni (new), a fordítási hibák kiszűrése miatt a típust is meg kell jelölnünk. Pl.:

public static int sum(int[] arr) { ... }

public static void main(String[] args) { int result = sum( new int[] {1, 2, 3} );}

Tömb segédosztály

9 / 89

Page 10: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

java.util.Arrays, hasznos pl. a toString(), binarySearch(), fill(), etc. Részletesen: http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html

Összehasonlítás

Az == operátor nem használható (referencia szerinti egyenlőség vizsgálat, nem érték szerinti). A megoldás a java.util.Arrays osztály: equals(), deepEquals() (vagy megírod kézzel).

Függvények

Érték szerint Referenciák? - Azok is Tömbök, objektumok Vararg paraméterek: tetszőleges számú formális paraméter, kezelés mintha tömb lenne:

public static void printMessages(String... messages) { System.out.println("# of params: " + messages.length); for (String act : messages) { System.out.println(act); }}...printMessages( "hello", "hi", "bye");

Ha minden függvényben szükséges egy érték:

public class A { public static int X = 1;

public static void inc() { X++; } public static void dec() { X--; }}

Stringek

Létrehozás:

String s = "hai!";

Objektum, így lehet az értéke null! Ha null értéket próbáljátok feloldani akkor az eredmény egy NullPointerException lesz.

String nullString = null;

if (nullString != null) { // Helyes ellenorzes ...}

nullString.isEmpty(); // NPE!

Rengeteg hasznos szolgálgatás:

int length = s.length;char firstChar = s.charAt(0);char[] carr = s.toCharArray();

boolean isExecutable = s.endsWith(".exe");boolean isEmpty = s.isEmpty();boolean aidx = s.indexOf('a');boolean hasEM = s.contains('!');

String upper = s.toUpperCase();String hai = s.substring(1, 3);String haiThere = hai + " there".String[] haiThereArr = haiThere.split(" ");

Részletesen http://download.oracle.com/javase/6/docs/api/java/lang/String.html

Karakterenkénti bejárás:

10 / 89

Page 11: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

for (int i=0; i<s.length(); ++i) { char act = s.charAt(i); ...}

// vagy:for (char act : s.toCharArray()) { ...}

replaceAll(), split() használható regexp (ld. Pattern osztály dokumentációja http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html)

Immutable (megváltoztathatatlan) adatszerkezet

String string = "AAAxAAA";string.replace('x', 'A');System.out.println(string); // "AAAxAAA"string = string.replace('x', 'A');System.out.println(string); // "AAAAAAA"

Vagy StringBuilder, StringBuffer használható:

StringBuffer sb = new StringBuffer();sb.append("Hello ").append("World");sb.reverse();System.out.println( sb.toString() ); // "dlroW olleH"sb.reverse();sb.setCharAt(6, '-');System.out.println( sb.toString() ); // "Hello-World"sb.deleteCharAt(6);System.out.println( sb.toString() ); // "HelloWorld"sb.delete(0, sb.length() );System.out.println( sb.toString() ); // ""

Összehasonlítás: equals() metódussal (az == operátor referencia szerinti összehasonlítást végez csak, nem tartalom szerintit).

boolean b1 = "a" == "a"; // lehet hamis!boolean b2 = "a".equals("a"); // mindig megfeleloen mukodik

Részletesen http://download.oracle.com/javase/6/docs/api/java/lang/StringBuilder.html

Feladatok

A feladat megoldásához használjatok függvényeket, és megfelelő hibakezelést (pl. IllegalArgumentException, saját típust még nem kell definiálnotok)! Egyelőre minden függvényt lássatok el a public static módosítószavakkal! Az összes megoldást rakjátok egy javagyak.basics csomagba! A feladatok nem feltétlen nehézségi sorrendben követik egymást!

+/- Feladat Minden feladatcsoportból egy tetszőlegesen választott feladat.

Tömbök

A következő függvények implementálásához használjátok nyugodtan a már meglévőket. Például az átlagolás, normálás esetén szükség van az összegre, itt használjátok azt a függvényt, amit az adott feladatban megírtatok!

1. Készíts egy függvényt, amely kiszámítja egy tömb elemeinek az összegét!2. Készíts egy függvényt, amely kiszámítja egy tömb elemeinek az átlagát!3. Készíts egy függvényt, amely normálja egy tömb összes elemeit (az elemek összege legyen kb. 1)!4. Készíts egy függvényt, amely növekvő sorrendbe rendezi egy tömb elemeit!5. Készíts egy függvényt, amely meghatározza egy tömb minimális és maximális elemét!6. Készíts egy függvényt, amely összefűzi egyetlen Stringbe a paraméterként kapott Strinkgeket. Az első paraméter

legyen az elválasztó karakter (minden konkatenáció közé ezt kell beszúrni), és a függvény fogadjon el tetszőleges számú paramétert!

7. Az előző pontban készített függvényhez készíts egy azonos nevű (túlterhelt) változatot, amelynek nincs szüksége az első paraméterre, és a ' ' karakterrel fűzi össze a karakterláncokat!

8. Készíts egy függvényt, amely képes meghatározni két paraméterként kapott tömb skaláris szorzatát!9. (?) Készíts egy függvényt, amely képes meghatározni két paraméterként kapott tömb vektoriális szorzatát! % TODO:

2 dimenzióra!10. Készítsetek egy kódoló függvényt, amely egy char[] paraméterként megadott szöveget úgy kódol, hogy minden

karaktert egy konstans értékkel XOR-ol (használjátok a ^ operátort!).11. Készítsétek el a dekódoló változatát (a kódolt char[] paramétert XOR-oljátok végig még egyszer ugyanazzal az

értékkel, így megkapjátok az eredeti értékeket!).

11 / 89

Page 12: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Többdimenziós tömbök

1. Készíts egy függvényt, amely megfelelően formázva kiír a képernyőre egy 2 dimenziós tömböt!

Példa (az asMatrix függvényt csak visszaadja Stringet!):

doule[][] arr = new double[3][3];arr[1][1] = 1System.out.println( asMatrix( arr) );Eredmény:

0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0

1. Készíts egy függvényt, amely képes megmondani, hogy egy kapott, 2 dimenziós tömb soraiban, oszlopaiban, és főátlójában szereplő elemek összege mennyi!

A program valami hasonló kimenetet generáljon:

0 1 2 | 3 1 2 3 | 6 2 3 4 | 9 ------/ 3 6 9 6

1. Készíts egy függvényt, amely képes meghatározni egy paraméterként kapott, 2 dimenziós tömbként reprezentált mátrix és egy valós érték szorzatát!

2. Készíts egy függvényt, amely képes meghatározni két paraméterként kapott, 2 dimenziós tömb mátrix összegét!3. Készíts egy függvényt, amely képes meghatározni két paraméterként kapott, 2 dimenziós tömb mátrix szorzatát!

Stringek

Igyekezzetek tanulmányozni a dokumentációt! A feladatok lényegi részei maximum 5 sorban megoldhatók a megfelelő API függvények használatával!

1. Készítsetek egy programot, amely egy parancssori argumentumként megadott Stringet átalakít a következőképpen:1. Minden numerikus karaktert változatlanul hagy2. Minden betűt kisbetűvé alakít3. Minden egyéb karaktert lecserél egy _ karakterre

2. Készítsetek egy programot, amely minden ékezetes karaktert lecserél a megfelelő, ékezet nélküli változatára!3. Készítsetek egy függvényt, amely egy parancssori argumentumként megadott Stringben lecseréli az első karaktert

nagybetűre! A visszatérési értéke legyen ez az új String!4. Készítsétek el az előző függvény fordított változatát: az első karaktert cserélje kisbetűre!5. Készítsetek egy függvényt, ami 2 String paramétert kap, és megmondja, hogy az első a másodikkal kezdődik-e. Az

összehasonlításnál a kisbetű, nagybetű eltérés nem számít (azaz pl. "Windows 7", "win") paraméterekre adjon vissza igaz értéket!).

12 / 89

Page 13: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

EmlékeztetőKörnyezet beállítása

Emlékeztető:

Microsoft Windows XP [verziószám: 5.1.2600](C) Copyright 1985-2001 Microsoft Corp.

c:\tmp>set PATH=%PATH%;c:\Program Files\Java\jdk1.6.0_12\bin\

c:\tmp>javac -versionjavac 1.6.0_12

c:\tmp>javac HelloWorldApp.java

c:\tmp>java HelloWorldAppHello World!

c:\tmp>

CsomagokModularizáció, névütközések feloldása, hozzáférés szabályozás, etc. (mint a C++ namespace). Osztályok, interfészek gyűjteménye. Használható a * wildcard. Alapértelmezetten látszik a java.lang.* csomag minden eleme, minden mást importálni kell (anélkül ún. fully qualified classname segítségével hivatkozhatunk, pl. java.util.Vector):

import java.util.Vector; // 1 tipushozimport java.math.*; // Minden package-beli tipus lathatova valik

import java.awt.*; // GUIimport java.awt.event.*; // GUI - esemenykezelesimport javax.swing.*; // Advancedebb GUIimport java.util.*; // Adatstrukturakimport java.io.*; // IOimport java.util.regex.*; // Regexp

// static import: minden static konstans lathato az adott osztalybol// fenntartasokkal hasznalniimport static java.lang.Math.*;

A fordítás nehézkes, nincs rekurzív javac -R *.java. Leképezés a fájlrendszerre: minden . karakterrel szeparált rész egy könyvtárat jelent, fordítás a gyökérkönyvtárból történik. Static importot csak offtosan (strukturáltság, enkapszuláció, egységbezárás ellen hat - használjatok helyette dedikált osztályt vagy interfészt). Csomag definíciója a Java fájl legelején:

package pkg;

// Import utasitasok

public class HelloWorldApp { public static void main(String args[]) { System.out.println("Hello World!"); }};

Fordítás teljes útvonal megadásával:

C:\tmp>javac pkg/*.java

C:\tmp>java pkg.HelloWorldAppHello World!

C:\tmp>

Ha esetleg névütközés van (2 azonos nevű osztály), akkor minősített névvel érhetjük el az egyiket (pl. java.util.List, java.awt.List). Importokat használjatok nyugodtan, nem gáz, nem emészt erőforrást (nem C++, dinamikus osztálybetöltés van).

13 / 89

Page 14: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

FüggvényekÁltalános prototípus:

<módosítószavak> <visszatérési érték> <név>( <paraméterek listája> ) [ throws <kivétel lista> ] { <utasítás1>; <utasítás2>; ...}

Paraméter átadás érték szerint történik (még a referenciák is!).

Módosítószavak: o Láthatóság: public, protected, private. Ha nem definiált, akkor ún. package-private láthatóság.o Lehet abstract: ekkor nincs implementáció (mint a C++ pure virtual függvényei) leszármazottban

kötelezően felüldefiniálandóo Lehet final: felüldefiniálhatóság letiltásárao Lehet static: osztály szintű függvény (Fontos: static kontextusból csak static módosítóval ellátott

hivatkozás szerepelhet)o Egyéb, pl. strictfp, native, synchronized, transient, volatile (utóbbi kettő csak fieldekre). Ezekről

később. Visszatérési érték szerinti csoportosítás:

o void: eljáráso Minden egyéb: függvény

Metódusnév: lowerCamelCase formátumban Paraméter átadás: minden paraméter érték szerint adódik át még a referenciák is.

Szignatúra a függvény neve és paramétereinek típusa -- más nem. Például:

eredmenyMeghatarozasa( double, int, int )

Overloading, overriding.

KivételekÁltalános forma:

try { ... // Kritikus utasitasok} catch (Exception1 e1) { ...} catch (Exception2 e2) { ...} finally {

}

A finally opcionális, de elképzelhető csak try-catch, try-finally blokk is:

try { ...} finally { ...}

try { ....} catch (Throwable t) { ....}

Az első ág, amelybe a kivétel osztályhierarchia szerint beleillik, lekezeli. Újradobás lehetséges: throw e1;, stb.

Alapvetően három típusú kivétel:

1. Felügyelt kivételek: definiálni kell őket a függvényben, és ha definiáltak, le is kell őket kezelni (ősosztály: java.lang.Exception}, pl. java.lang.ClassNotFoundException, java.io.IOException)

2. Nem felügyelt kivételek: nem kötelező sem difiniálni, sem lekezelni őket (ősosztály: java.lang.RuntimeException, pl. ArrayIndexOutOfBoundsException, NumberFormatException, DivisionByZeroException)

14 / 89

Page 15: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

3. Léteznek még Error-ok, ezek a Throwable leszármazottai. Kritikus esetben fordulnak elő, a legtöbb esetben a lekezelésük is felesleges (pl. OutOfMemoryError, StackOverflowError)

Mindkettő őse a Throwable osztály, ezt kell hát lekezelni, ha mindent lehetőségre fel akarunk készülni. Ökölszabály: üres kivételkezelő blokkot soha ne készítsünk! Legegyszerűbb megoldás: e.getMessage() vagy e.printStackTrace(). További funkciók az Exception osztály leírásában (javadoc). Kivételt dobni a throw utasítással lehet (mindig van paramétere!).

Példa

Egyszerű kivételkezelés

public static void main(String[] args) { try { int res = Integer.parseInt(args[0]); // ... } catch (NumberFormatException nfe) { System.err.println("Hibas input: " + args[0]); nfe.printStackTrace(); }}

Megjegyzés Kivételek neve általában e, de igazából ízlés kérdése.

Függvénydefiníció

// Egyszerubb forma, ha nem akartok uzeneteket//class ZeroParameterException extends Exception {}

class ZeroParameterException extends Exception { public ZeroParameterException() { super(); }

public ZeroParameterException(final String msg) { super(msg); }}

static double divide(int a, int b) throws ZeroParameterException { if (0 == b) { throw new ZeroParameterException("b erteke nem lehet 0!"); }

return (double) a / b;}

public static void main(String[] args) { try { double res = divide(1, 0); } catch (ZeroParameterException e) { System.err.println(e.getMessage()); } catch (Exception e) { System.err.println(e.getMessage()); } finally { System.err.println("vege"); }}

Részletesen http://download.oracle.com/javase/tutorial/essential/exceptions/

Saját kivétel is definiálható, csak származtatni kell (pl. a java.lang.RuntimeException, java.lang.Exception osztályokból, ezekről később).

Megjegyzés Az alábbi Explanations of Common Java Exceptions egy humoros leírása a common Java kivételeknek. Mielőtt komolyan vennétek, hangsúlyozom, ez csak poén, de ha már megragad 1-2 Exception neve, akkor már megérte átröhögni :-) Thx to Björn Andersson!

15 / 89

Page 16: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

+/- FeladatokA feladatokat a gyak2.f1 ill. gyak2.f2 csomagba rakjátok!

Euclid

Készítsetek egy függvényt, amely az Euklideszi-algoritmus alapján meghatározza két szám legnagyobb közös osztóját! Az algoritmus pszeudokódja:

function gcd(a, b) if a = 0 return b while b != 0 if a > b a := a - b else b := b - a return a

Készítsd el a függvény rekurzív változatát is!

Quadratic

Készítsetek egy függvényt, amely megadja egy másodfokú egyenlet gyökeit! A függvény definíciója legyen a következő:

private static double[] sqroots(final double a, final double b, final double c) { // ...}

A függvény dobjon nem ellenőrzött és ellenőrzött kivételeket is (pl. IllegalArgumentException és egy saját), ha a == 0, vagy a diszkrimináns negatív! A függvény által dobott kivételeket kezeld is le a main() függvényben! A paramétereket a parancssori argumentumok határozzák meg, és az Integer.parseInt() függvény által dobott NumberFormatException kivételt is kezeljétek le ugyanabban a kivételkezelő ágban!

16 / 89

Page 17: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Objektumorientált alapokHatókör, Élettartam

Alapvető fogalmak:

Hatókör: Ahol a változó használható Élettartam: Ahol a változó még "él"

class A { static int x = 0;

static void f(int x) { System.out.println( x ); // parameter System.out.println( A.x ); // osztaly valtozo }}

Hol deklarálhatok változót?

Konzol használata

Tantárgyi ajánlás a java.util.Scanner használata - itt nem, de akit érdekel: http://download.oracle.com/javase/6/docs/api/java/util/Scanner.html. Helyette: java.io.Console#readLine() függvénye és String#split().

Osztályok, Objektumok

Miért?

Egységbe zárás, adatelrejtés, absztrakt adattípus = adatabsztrakció, adattípus és a rajta értelmezett műveletek.

Példa

class Koordinata { public int x, y;

public void eltol(int dx, int dy) { x += dx; y += dy; }}

A tagok elérése:

Koordinata k = new Koordinata();k.x = 10;k.y = 20;k.eltol(10, 0);

Módosítószavak

static: Osztályszintű tag: minden példány rendelkezik vele, és ugyanazt a változót, függvényt látják.

Fontos Statikus környezetből azonban csak statikus változókat, függvényeket érhetünk el! Miért? V.ö. eddigi függvénydefiníciókkal!

Példa: adott osztály példányainak számolása:

public class Foo { private static int ctr = 0; private final int idx; ...

public Foo() { ... idx = ctr++; }}

17 / 89

Page 18: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

final: Ha változó, akkor az adott referencia nem állítható át (azonban ha az egy objektum, tömb, akkor az elemei igen! V.ö. C++ const). Ha függvény, akkor nem lehet felüldefiniálni (ld. később!).

public class Main { public static final int DEBUG = true;

public sum(int[] arr) { if ( DEBUG ) { System.out.println( "Sum params: " + Arrays.toString( arr ) ); } ... }}

Láthatósági módosítószavak: o public Minden más osztályból elérhető (függvény, adattag, vagy osztály)o protected Adott csomagon belülről, valamint a származtatott osztályokból elérhetőo private Kizárólag az adott osztályon belülről használhatóo (default) Ha nem deklarálsz semmit, az az alapértelmezett, ún. package-private láthatóság: az adott

csomagon belül látszik csak.

Definíció

Az osztálydefiníció tartalmazhat adattagokat, függvényeket, és egyéb osztályokat. Függvénydefiníció tartalmazhat újabb, lokális osztályokat.

Osztályok definiálhatók azonos forrásállományban (de csak egy public lehet), másik osztályban (belső osztályok), függvényen belül (lokális osztályok). Például:

package oo.basics;

class A { ... }

public class B { ... class C { ... }

void f() { class D { ... } ... }}

Beágyazott osztályok lehetnek static-ok, ekkor nincs szükség a befoglaló osztály egy példányára (így a példányváltozókhoz sem férnek hozzá). Ha egy osztály final, nem származtatható belőle újabb osztály.

Mikor melyiket használjuk?

Ha szükség van egy adott osztály tagjainak elérésére, akkor beágyazott osztályt Ha úgy logikusabb, akkor beágyazott statikus osztály Ha más osztályban nincs rá szükség, de közvetlen nem függ össze a reprezentációval, akkor a public osztállyal

azonos forrásállományba Ha általános osztályt készítünk, akkor saját fordítási egységbe

Ha bizonytalan vagy, tégy minden minden osztályt külön fordítási egységbe!

Származtatás

Miért?

Kódmegosztás, kódkomplexitás csökkentése, karbantarthatóság, modularizáció, ...

Példa

abstract class Sikidom { public static final double PI = 3.1415;

public abstract double kerulet(); public abstract double terulet();}

class Kor extends Sikidom {

18 / 89

Page 19: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

private double r = 1.0;

@Override public double kerulet() { return 2 * r * PI; }

@Override public double terulet() { return Math.pow( r, 2 ) * PI; }

class Teglalap extends Sikidom { private double a = 1, b = 1;

@Override public double kerulet() { return 2 * ( a + b ); }

@Override public double terulet() { return a * b; }}

Javaban csak egyszeres öröklődés van, kivéve az interfészek esetében. Általános forma:

class Foo extends Bar implements Baz1, Baz2, ... { ...}

Felüldefiniálás, túlterhelés

Felüldefiniálás Ha a szignatúra megegyezik Túlterhelés Minden más esetben

A felüldefiniált függvények elé írjuk oda az @Override annotációt, és segít a compilernek kiszűrni az elgépelésből adódó problémákat fordítási időben. Ha hibát ad a fordító, valami nem stimmel (pl. nem egyezik a szignatúra).

Származtatásnál a szűkebb hatókör nem megengedett. Visszatérési értékre nem lehet túlterhelni, mert az nem része a szignatúrának. Visszatérési értéket lehet specializálni (hasznos pl. a clone() függvénynél - kovariáns kötés).

A kivétel lista nem lényeges ebből a szempontból.

abstract class A { public abstract int f(int a, int b); public abstract int g() throws Exception; public abstract A h();}

class B extends A { @Override int f(int a, int b) { return 0; } // Feluldefinialas

void f(int a, int b) {}; // Hibas: visszateresi ertek nem kompatibilis int f(int a) { return f(a, 0); } // Tulterheles (parameterek szama) int f(Integer a, Integer b) { ... } // Tulterheles (parameterek tipusa)

@Override int g() { return 0; } // OK: Exception lista nem szamit

@Override B h() { return null; }; // OK: Visszateresi ertekre specializal}

A this pszeudováltozó.

Adattagok elérése

Enkapszuláció elve: minden osztály rejtse el a reprezentációját (hogy könnyen le lehessen cserélni), és csak a publikus metódusain (interfészén) keresztül lehessen megváltoztatni.

19 / 89

Page 20: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Azaz az adattagok elérése getter és setter függvényeken keresztül történjen:

class Koordinata { private int x, y; // private lett, csak belul hasznalhato ... public int getX() { return x; }

public void setX(int x) { this.x = x; }}

Konstruktorok

Objektum létrehozásáért felelnek, "speciális függvények". Általános forma:

<módosítószó> <Osztály neve>( <paraméter lista> ) { <inicializációs utasítások>}

Például:

class Koordinata { private int x, y;

public Koordinata(int x, int y) { this.x = x; this.y = y; } ...}

Ha származtatás is játszik a történetben, az kicsit bonyolultabbá teheti. Konstruktorban a szülőre a super(), az aktuális példány valamely konstruktorára this() hívással hivatkozhatunk. Ha ezeknek a paramétere egy függvény visszatérési értéke lehet, az csak statikus függvény lehet.

Példa:

class A { protected int size;

public A(int size) { this.size = size; } ...}

class B extends A { public B() { this(0); } // B(int) hivasa public B(int size) { super(size); } // A(int) hivasa ...}

Létrehozás, életciklus

Objektum létrehozása a new operátorral történik:

A a = new A(5); // Konstruktorhívás

Felszabadítással nem kell foglalkozni, azt megoldja a Garbage Collector (finalize). Memória: dinamikus/statikus/stack (utóbbihoz nem fértek hozzá), automatikusan felügyelt (eden, stb.), System.gc(), finalize(). Az aktuális értékek lekérdezhetők a Runtime osztály metódusaival.

Statikus/dinamikus típus: statikus, amivel definiálva lett, dinamikus, amilyen referenciára éppen mutat.

A a = new B(5);

A fenti példában az a változó statikus típusa A, dinamikus típusa B (megengedett, altípusos polimorfizmus, ld. Liskov-féle szubsztitúciós elv). A dinamikus típus leellenőrizhető az instanceof operátorral:

if (a instanceof B) { ... }else if (a instanceof C) { ... }

20 / 89

Page 21: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Object

Minden típus az Object leszármazottja, ha nincs közvetlen őse. Javaban nincs többszörös öröklődés (kivéve interfészeknél). Fontosabb függvények:

equals(Object) Azonosság vizsgálat, contract szerint reflexív, tranzitív, szimmetrikus reláció, valamint konzisztens, és x.equals(null) értéke mindig hamis legyen.

hashCode() Hasheléshez (pl. egyes halmaz implementációk, vagy a Hashtable esetén). Contract szerint:o Ugyanarra az objektumra hívva konzisztens értéket ad (ha az objektum nem változik, ugyanazt az értéket

adja).o Ha két objektum az equals() szerint megegyezik, a hashCode() is egyezzen meg.o Két különböző objektumra nem kell különböző értéket adni (ld. hash collision).

Példa:

class Sample { private int i = 0; private String str = "str"; private boolean b = false;

@Override public int hashCode() { return (i * 31 + str.hashCode() ); }}

toString() Az objektum szöveges reprezentációját adja vissza (Stringként). Egyéb függvények: clone(), finalize(), notify(), wait(), getClass()

Részletek http://download.oracle.com/javase/6/docs/api/java/lang/Object.html

Feladatok

A feladatok megoldásához használjatok saját osztályokat, objektumokat. Használjatok megfelelő módosítószavakat! Az összes osztályt tegyétek legalább az oo.basics csomagba!

+/- Feladat: egy tetszőlegesen választott feladat.

Objektumok használata

Készíts egy interaktív programot, amely a felhasználó által megadott szövegeket fordítva kiírja a képernyőre. A megoldáshoz használj StringBuilder osztályt, a felhasználói interakcióhoz pedig a java.io.Console osztályt! A program addig kérjen újabb és újabb stringeket a felhasználótól, amíg üres stringet nem kap az inputról!

Készítsetek egy könyvtár listázó alkalmazást! Ez parancssori paraméterként egy teljes elérési utat várjon, és hozzon létre egy java.io.File objektumot (File dir = new File(args[0]);)! Ezután listázzátok ki a könyvtárban található összes, ".java"-ra végződő fájlt (String#endsWith(), File#listFiles())!

Készíts egy interaktív programot, amely a felhasználó által megadott α értékre visszaadja annak szinusz, koszinusz és tangens értékeit! A megvalósításhoz használd a Math osztály statikus függvényeit, a felhasználói interakcióhoz pedig a java.io.Console osztályt! A program addig kérjen újabb és újabb α értékeket a felhasználótól, amíg "END" értéket nem kap az inputról!

Készíts egy interaktív konzolos kockadobó alkalmazást! A program kérdezze meg, hogy hány 6 oldalú kockával dobjon, majd írja az eredményt a képernyőre! A megoldáshoz használd a java.util.Random osztályt, a felhasználói interakcióhoz pedig a java.io.Console osztályt! A program addig kérjen újabb és újabb értékeket a felhasználótól, amíg üres stringet nem kap az inputról!

21 / 89

Page 22: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Absztrakt AdattípusAbsztrakt adattípus = adatabsztrakció, absztrakt adattípus és a rajta értelmezett műveletek.

Emlékeztető: Object Függvények felüldefiniálásapublic class Student { private String name; private String ETR; private int yearsAtUni;

// ...

@Override public int hashCode() { return name.hashCode() + ETR.hashCode() + yearsAtUni; }

@Override public boolean equals(final Object obj) { if (obj instanceof Student) { final Student other = (Student) obj;

// Esetleges null ellenorzeseket tessek elvegezni! // Itt az attekinthetoseg kedveert ettol eltekintettem. return ( name.equals( other.name) && ETR.equals( other.ETR ) && yearsAtUni == other.yearsAtUni ); }

return false; }

@Override public String toString() { return "Student [name=" + name + "," + "ETR=" + ETR + ", " + "yearsAtUni=" + yearsAtUni + "]"; }

}

Absztrakt osztályok

Ősosztályok "közös nevezőre" hozzák leszármazottaikat: definiálnak egy interfészt (külső felületet), vagyis egy adat-, és metóduskészletet, amelyen keresztül a leszármazottak egységesen kezelhetők.

Megvalósítás nélküli metódusokat absztrakt osztályok tartalmazhatnak (abstract módosítószó az osztályhoz, metódushoz). A fordító nem engedi meg, hogy abstract módosítószó szerepeljen private, final, static mellett (ezeket nem lehet felüldefiniálni). Absztrakt osztály nem példányosítható.

Absztrakt osztály kiterjesztésekor nem kell minden függvényt implementálni (de ekkor a leszármazottnak is absztraktnak kell lennie).

Részletesen http://download.oracle.com/javase/tutorial/java/IandI/abstract.html

Példa:

abstract class Sikidom { protected boolean tukorszimmetrikus;

public Sikidom(boolean tukorszimmetrikus) { this.tukorszimmetrikus = tukorszimmetrikus; }

public abstract double kerulet(); public abstract double terulet();

public void isTukorszimmetrikus() { return tukorszimmetrikus; }

public void kiir() { System.out.println( "K: " + kerulet() ); System.out.println( "T: " + terulet() ); }}

class Kor extends Sikidom { private static final double PI = 3.1415;

22 / 89

Page 23: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

private double r = 1.0;

public Kor() { super( true ); }

@Override public double kerulet() { return 2 * r * PI; }

@Override public double terulet() { return Math.pow( r, 2 ) * PI; }}

class Teglalap extends Sikidom { private double a = 1, b = 1;

public Teglalap() { super( true ); }

@Override public double kerulet() { return 2 * ( a + b ); }

@Override public double terulet() { return a * b; }}

Használatra példa:

public class Main { public static void keruletKiir(Sikidom sikidom) { System.out.println( sikidom.kerulet() ); }

public static void main(String[] args) { Sikidom s = new Kor(); // v.o. statikus-dinamikus tipus keruletKiir( s ); }}

Interfészek

Új referencia típus, absztrakt függvények és konstansok gyűjteménye (gyakorlatilag teljesen absztrakt osztályok, amik kizárólag konstans adattagokat tartalmazhatnak).

Absztrakciós szintet vezet be, felületet definiál. Osztály megvalósít egy interfészt (implements), ha minden függvényét megvalósítja (abstract) osztálynál nem kötelező, ugye).

Eltérés az osztályoktól:

Többszörös öröklődés (névütközésre figyelni, függvényekre fordítási hiba lesz, nem C++, konstansok minősített névvel elérhetők). Szépen ezt úgy mondják, hogy a specifikáció többszörösen örökölhető, kód csak egyszeresen.

Nincs közös ős (mint osztályoknál az Object) Nem tartalmazhat implementációt (csak absztrakt függvényeket és konstansokat)

Részletesen http://download.oracle.com/javase/tutorial/java/IandI/index.html

Deklaráció

Mint az osztályoké:

interface A {}

public interface B {}

Öröklődési reláció neve itt kiterjesztés, lehet többszörös:

interface C extends A, B {}

23 / 89

Page 24: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Körkörös kiterjesztés fordítási hibát eredményez.

Tagok

Mint az osztályoké, de:

minden adattag public, static és final alapból (ezeket nem kell kiírni sem, ugyanakkor az egyértelműség kedvéért ajánlott a feltüntetésük)

minden függvény public és abstract alapból (ezeket nem kell kiírni sem). Más nem lehet.

Előbbiből következik, hogy minden adattagot inicializálni kell (különben fordítási hibát kapunk), és ez csak már ismert érték lehet (forward referencing tilos):

interface I { int A = B; // Hibas definicio! int B = 0;}

Nem szerepelhet this, super sem. Módosítószavak között nem szerepelhet synchronized, transient, volatile - ezek olyan dolgokat kötnek meg, amiknek implementációs szinten kell eldőlniük, használatuk ésszerűtlen lenne (legalábbis ez a hivatalos álláspont).

Főleg tulajdonságok, viselkedés hozzáadására. Például:

interface Beolvashato { public abstract void beolvas(); }

class Kor implements Beolvashato { ...

public void beolvas() { String sor = Console.readLine("r = ?"); r = Integer.parseInt( sor ); }}

Summarium

It boils down to this. Amit mindenképp meg kell jegyezni, az a következő:

Interfész használatával megoldható a többszörös öröklődés Absztrakt osztály pedig megvalósítást is tartalmazhat

Interfész

public interface GroupedInterface extends Interface1, Interface2, Interface3 { ... }

vagy például:

class A extends B implements I1, I2 { ... }

Részletesen http://download.oracle.com/javase/tutorial/java/IandI/interfaceDef.html

Absztrakt osztályra példa

public abstract class Point { private int x = 1, y = 1;

void move(final int dx, final int dy) { x += dx; y += dy; alert(); }

abstract void alert();}

Részletesen http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#34944

24 / 89

Page 25: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Feladatok

A feladatok megoldásához használjatok saját osztályokat, objektumokat. Használjatok megfelelő módosítószavakat! Az összes osztályt tegyétek legalább egy oo.adt csomagba!

+/- Feladat egy tetszőlegesen választott feladat.

Interfészek

Készíts egy saját osztályt, amely implementálja a java.lang.CharSequence interfészt úgy, hogy a konstruktorában megadott Stringet fordítva tartalmazza!

Készíts két saját tetszőleges Kirajzolhato és Mozgo interfészt. Adj hozzájuk szemléltető implementációkat, amelyek bemutatják az interfészek használatát külön-külön és mindkét esetben is!

Osztályok készítése

Ügyelj a láthatóságok helyes használatára (private, protected adattagok, és ezekhez megfelelő public lekérdező függvények). Az osztályok külön fordítási egységekben legyenek! A Main osztály a oo.adt.fx csomagban legyen, az összes többi a oo.adt.fx.data csomagban (ahol x a feladat sorszámát jelöli)! A megadott példakódokat használjátok, azokat szűkíteni nem, de bővíteni megengedett (sőt, ajánlott is).

Készítsd el a többdimenziós pontok absztrakt osztályát (APont). Pontokat lehessen eltolni, forgatni és tükrözni! Készítsd el ez alapján az ősosztály alapján az 1D, 2D, 3D pontok megvalósítását (tartalmazzák a szükséges double koordinátákat, valamint az absztrakt függvények implementációit).

Közös adattag legyen az első, x koordináta (ezzel minden származtatott osztály rendelkezik). Az eltoláshoz használj változó számú paramétert (vararg), a következő minta alapján:

public abstract void translate(double... coordinates);

A forgatást vedd úgy, hogy az origó kürül kell elforgatni a megadott pontot, a paraméterként specifikált alpha szöggel (3D pont esetén elég valamelyik tengely körül forgatni)!

Készíts egy Kirajzolható interfészt! Ezt az 1D pont implementálja úgy, hogy a koordinátáinak megfelelő számú szóköz után rajzoljon egy # karaktert a konzolra (negatív esetben az # után rakjon szóközöket).

Készíts egy Frissitheto interfészt! Ez egyetlen metódust írjon elő:

public abstract void frissit();

Ezzel a képernyőről, felhasználói interakció révén lehessen frissíteni az adott objektum értékeit! Minden implementáció valósítsa meg ezt az interfészt!

> **Tipp/Csel** Használhatjátok a későbbiekben leírt mátrix osztályt!

Készítsetek egy kódoló alkalmazást! Hozzátok létre a kódolóalgoritmusok absztrakt osztályát (AKodolo), amely a következő definíciókat tartalmazza:

public abstract class AKodolo { public abstract String kodol(String eredeti); public abstract String dekodol(String kodolt);}

A különböző megvalósítások a kapott eredeti szöveget kódolják ill. fejtik vissza (kódolás előtt alakítsátok nagybetűssé a kapott szöveget).

Készítsetek legalább két különböző kódoló algoritmus implementációt:

Caesar-kódolás: 3 betűvel legyenek eltolva a karakterek (A = D, B = E, ..., X = A, Y = B, Z = C)

Monoalfabetikus kódolás: a karakterek megfeleltethetők egymásnak az alábbi szabályok szerint: Eredeti: ABCDEFGHIJKLMNOPQRSTUVWXYZ Kodolt: ZEBRASCDFGHIJKLMNOPQTUVWXY

25 / 89

Page 26: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Tipp/Csel Nehogy switch-case szerkezetet használjatok! :-)

Készítsd el a sorozatok absztrakt osztályát (ASorozat)! Sorozatoknak általánosan lehessen lekérdezni az első n tagját, az n tag részletösszegét, valamint hogy monoton növekvő-e, csökkenő-e a sorozat. Készítsd el ez alapján az ősosztály alapján a számtani és mértani sorozatok megvalósítását (tartalmazzák a specifikus adatokat, mint pl. az első szám, és kvóciens vagy differencia).

Készíts egy Util osztályt, amely a következő definíciót tartalmazza:

public final class Util { public static ASorozat beolvas() { //... }

private Util() {}}

Ez a felhasználótól kérdezze meg, hogy milyen sorozatot szeretne megadni, segítsen neki létrehozni egyet, és ezt a létrehozott sorozatot adja is vissza.

Valósítsd meg a mátrixok típusát Javaban! Két konstruktor legyen: az egyik a méretet adja meg (négyzetes mátrixot hozzon létre, és minden elem 0 legyen), a másik pedig egy double[][] paramétert kapjon! Mátrixokat lehessen összeadni, és adott valós számmal beszorozni, valamint lekérdezni, hogy négyzetes-e.

Egészítsd ki az előző feladatot az általános, Object osztályból örökölt függvényeket (equals(), hashCode(), toString()).

Egészítsd ki az előző feladatot a következő funkciókkal:o transzponáláso nyom kiszámítása (átló elemeinek összege, ha négyzetes)o mátrixok szorzása mátrixokkal (amennyiben lehetséges)

26 / 89

Page 27: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

OO gyakorló feladatokZH gyakorló feladatok

A feladatok a ZH-ra való felkészülést segítik, ennek okán kicsit bonyolultabbak az eddigieknél. +/- szempontjából szorgalmi feladatnak tekinthetők, nem kötelező őket megcsinálni, ugyanakkor ++ jár valamelyikük elkészítéséért.

Törekedj a gyakorlatokon vett objektumorientált technikák használatára! Készíts saját típusokat! Rendezd őket egy logikus csomagstruktúrába! Használj absztrakt osztályokat, és ahol lehetséges, és indokoltnak érzed, interfészeket! Absztraháld a közös részeket! Használj megfelelő láthatósági módosítókat!

További szempontok, amiket vegyetek figyelembe az implementáció során:

Figyelj a megfelelő inputkezelésekre! Lekezeletlen kivételt ne dobjon a program (pl. NumberFormatException)! Az bemeneti értékek ellenőrzését minden esetben végezd el (pl. számnak ne fogadj el karakterláncot!)

Definiáld felül az Object osztályból származó tanult függvényeket (equals(), hashCode(), toString()) Használd a kiírásokhoz a saját toString() implementációdat!

A feladatok nem nehézségi sorrendben követik egymást!

Tőzsde

Készíts egy tőzsde nyilvántartó programot! A program kezeljen mind vételi, mind eladási ajánlatokat. A keretrendszer rendelkezzen egy interaktív konzolos menüvel, ami legalább a következő funkcionalitásokkal rendelkezzék:

[1] Uj eladasi ajanlat felvetele[2] Uj veteli ajanlat felvetele[3] Jelenleg aktiv ajanlatok listazasa[4] Letrejott tranzakciok listazasa[5] Tozsde zarolasa--------------------------------------Valasztas:

A megvalósítandó funkciók a következők:

Új eladási ajánlat felvételekor meg kell adni az eladandó nevét, az arany mennyiségét és a preferált eladási árat. Maximum 5 aktív eladási ajánlat lehet egyszerre, ha újat szeretnénk felvenni, adjunk hibaüzenetet. Ezután le kell futtatni a párosító algoritmust. Két eladási ajánlat akkor egyezik meg, ha az eladó neve ugyanaz. Egy eladó csak egyetlen ajánlatot tehet fel egyszerre.

Új vételi ajánlat felvételekor meg kell adni a vásárló nevét, a vásárolni kívánt arany mennyiségét. Maximum 5 aktív vételi ajánlat lehet egyszerre, ha újat szeretnénk felvenni, adjunk hibaüzenetet. Ezután le kell futtatni a párosító algoritmust. Két vételi ajánlat akkor egyezik meg, ha a vevő neve ugyanaz. Egy vevő csak egyetlen ajánlatot tehet fel egyszerre.

A jelenleg aktív ajánlatok listázásánál írjuk ki mind a jelenleg aktív eladási, mind a vételi ajánlatokat! Az utolsó 5 létrejött tranzakciót tartsuk nyilván! Ehhez tároljuk el a vevő és az eladó nevét, az eladott arany

mennyiségét, az árat, és a tranzakció dátumát (ehhez használd a java.util.Date osztály egy példányát!) Zárolás esetén, a helyes jelszó megadása után (ez legyen egyelőre beégetve a kódba) egyetlen tranzakció sem vehető

fel. Ilyenkor minden új ajánlat felvételekor adjunk hibaüzenetet! A jelszó beolvasásához használd a Console osztály readPassword() metódusát!

A párosító algoritmus az ajánlatok beérkezésének sorrendjében működik. Ha egy ajánlat mennyisége nullára csökken, eltávolítjuk. Ha két ajánlat párosítása során az egyik ajánlat nem teljes mennyiséggel kerül felhasználásra, akkor az ajánlatból megmaradt mennyiség alapján ún. maradékajánlattal kell helyettesíteni az eredeti ajánlatot (azaz a részteljesítés megengedett).

Moziműsorok

Készíts egy programot, amely moziműsorokat képes nyilvántartani! Minden kihirdetett előadásról a következő információkat tároljuk:

a film azonosítóját a film forgalmazójának azonosítóját a vetítés időpontját

Ezen felül készítsünk reprezentációs osztályokat a filmeknek és a forgalmazóknak! Filmek esetén tároljuk azok:

27 / 89

Page 28: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

azonosítóját (egyedi, tetszőleges típus) a címét a rendezőjének nevét az egységes jegyárat a kiadás évét

Készíts külön osztályokat a 2D és 3D filmeknek! A jegyárat a következő képlet alapján számold ki 1500 / ( 2010 - ev ) 2D filmek esetében; 3D filmeknél ez az összeg ennek kétszerese.

Kiadó esetén tároljuk azok:

azonosítóját (egyedi, tetszőleges típus) nevét az alapításuk évét

A program hozzon létre és tároljon 5 különböző kiadót és filmet! Két azonos kiadó, film nem lehet a rendszerben (ezek azonosságát az egyedi azonosítókon keresztül vizsgáld!). Az új előadások hirdetésénél figyelj arra, hogy azonos időpontra ne lehessen meghirdetni egy előadást. A program nyújtson lehetőséget a filmek, kiadók közti keresésre az azonosító alapján!

Ha a programot -html kapcsolóval indítják, akkor a standard outputra írjon ki egy minimális HTML forrásfájlt, amely az előadásokat egy táblázatban tartalmazza.

KKK szimuláció

Készíts egy egyszerű kaland-játék-kockázat szimulációt!

A program hozzon létre 5 különböző karakterkombinációt. Egy karakter a következő tulajdonságokkal rendelkezik, amelyek értékei 1-12 között lehetnek, és ezek között szétosztható 25 pont tetszőlegesen: fizikum, asztrál, mentál. A karakter egy származtatott értékkel is rendelkezik, az életerővel, ami a fizikuma + 1 értékkel egyezik meg alapból. A karakternek még egy fontos tulajdonsága van, a sebzés, amely mindegyiknél 2.

A létrehozott karakterek különböző szörnyekkel hadakoznak (amelyek ugyanezekkel a tulajdonságokkal rendelkeznek, bestiárium a feladat végén), a következő szabályok szerint:

Akinek nagyobb az asztrálja, az kezdi a kört Dobunk 2k6-tal (2 db 6 oldalú kockával), és hozzáadjuk a fizikumhoz. Ha ez nagyobb vagy egyenlő, mint a másik fél

védőértéke (fizikumának és mentáljának összege), akkor életerejéből le kell vonni a sebzés mértékét.

Ha a támadódobás értéke 12, akkor dupla sebzés történik. Minden sebzés automatikusan csökkenti az asztrál értéket is eggyel.

Ugyanezt megismételjük a másik féllel. A kör végén mindenki levon egyet a mentál értékéből.

Ha a csata során bármely fél asztrálja 5-tel kisebb, mint az ellenfélé, akkor az elmenekül a csatából. A harc addig folytatódik, amíg valakinek az életerő pontja nullára csökken, ekkor az illető meghal. Ha a mentálérték csökken nullára, akkor az azt jelenti, hogy az illető nem tud megfelelően koncentrálni a csatára, így minden sebzéséből levonódik egy.

A harc végén az értékek visszaállnak a maximumra.

A szimuláció során készíts statisztikát a megnyert, elvesztett csaták arányából, hogy mely karakterkombinációk bizonyultak a legsikeresebbeknek!

Bestiárium

Farkas, tulajdonságok: o Fizikum: 6o Asztrál: 9o Mentál: 8o Életerő: 9o Sebzés: 1

Csontváz, tulajdonságok: o Fizikum: 6o Asztrál: 3o Mentál: 3

28 / 89

Page 29: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

o Életerő: 10o Sebzés: 2

Orgyilkos, tulajdonságok: o Fizikum: 7o Asztrál: 8o Mentál: 6o Életerő: 7o Sebzés: 2

Láncfűrészes goblin, tulajdonságok: o Fizikum: 5o Asztrál: 6o Mentál: 5o Életerő: 7o Sebzés: 3

29 / 89

Page 30: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

StreamekCsatornák, absztrakciós szint bemenet-kimenet kezelésére (hiext, lorem).

Részletesen: http://download.oracle.com/javase/tutorial/essential/io/

Példa

package io;

import java.io.FileWriter;import java.io.PrintWriter;

public class WriteSampleFile { public static void main(String[] args) throws Exception { PrintWriter pw = new PrintWriter( new FileWriter("dummy.txt") ); pw.println("Dummy data here"); pw.close(); }}

Csoportosítás

Szervezés szerint:

InputStream, OutputStream (bájtszervezésű) Reader, Writer (karakterszervezésű)

Ezekből rengeteg változat, pl.

StringReader, FileReader, BufferedReader, etc. FileInputStream, DataInputStream, etc. FileOutputStream, PrintStream, etc. FileWriter, PrintWriter, etc.

Pl. FileReader, FileWriter, FileInputStream, FileOutputStream

Feladat szerinti csoportosítás:

Adatforrás, adatnyelő (pl. FileInputStream, FileReader) Szűrők: meglévő csatornához plusz funkcionalitás (pl. BufferedInputStream). Összekapcsolhatók (pl.

SequenceInputStream), csatornák hozhatók létre (pl. kommunikációs közeg szálaknak, PipedInputStream, stb.)

Alapvető műveletek

Megnyitás automatikus, lezárás: close() (ne felejtsd el, mert nem fogsz tudni hozzáférni) flush(): automatikus endline karakterre a szöveges fájlokban. Kiírás: write(), print() Olvasás: read(). Ha a csatorna kiürül, akkor az olvasó művelet blokkolódik, amíg adatot nem kap:

public static void main(String[] args) throws Exception { int i = System.in.read(); System.out.println("A kapott karakter: " + i);}

"Könyvjelző-mechanizmus", ha támogatott: markSupported(), mark(), reset() Padding átugrása: skip() Csatorna ürességének ellenőrzése: ready() Hány bájtot lehet minimum olvasni? available()

int meret = new FileInputStream("tmp.txt").available();

Speciális streamek

30 / 89

Page 31: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Sorok számolására: LineNumberInputStream#getLineNumber() Adatok olvasása, visszafűzése a csatornára: PushbackInputStream, PushbackReader Bufferelt csatornák: BufferedReader, BufferedInputStream Véletlen elérésű fájlok: RandomAccessFile (későbbb kicsit részletesebben is) Szövegfeldolgozás: StringTokenizer (van sima StreamTokenizer is) System.in, out, err: InputStream ill. PrintStream-ek. Pl. standard input átirányítása:

BufferedReader br = new BufferedReader( new InputStreamReader(System.in) );

Részletesen: http://download.oracle.com/javase/6/docs/api/java/io/package-summary.html

Példák

Fájl írása

package files;

import java.io.FileNotFoundException;import java.io.PrintWriter;

public class WriteFile { public static void main(String[] args) { PrintWriter pw = null;

try { pw = new PrintWriter(args[0]);

pw.println("Line1"); pw.println("Line2"); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (pw != null) pw.close(); } }}

Fájl olvasása

package files;

import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;

public class ReadFile { public static void main(String[] args) { BufferedReader br = null;

try { br = new BufferedReader(new FileReader(args[0])); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } }}

Egyéb megjegyzések

31 / 89

Page 32: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Oprendszer függő tulajdonságok:

// PATH elvalaszto, pl. ":" - Unix, ";" - Windowsfinal String PATH_SEPARATOR = File.pathSeparator;// Ugyanaz, csak karakterkentfinal char PATH_CHAR = File.pathSeparatorChar;

// Nev szeparator, pl. "/" - Unix, "\" - Windowsfinal String SEPARATOR = File.separator;// Ugyanaz, csak karakterkentfinal char SEPARATOR_CHAR = File.separatorChar;

// Sorvege karakter, pl. "\n" - Unix, "\r\n" - Windows// Reszletesen lasd FAQ!final String EOL = System.getProperty("line.separator");

FileNotFoundException: Ha nem tudod, hol keresi az IDE, vagy a Java a megadott file-t, alkalmazhatod ezt a cselt:

File file = new File("test.txt");System.out.println( file.getAbsolutePath() );

Közvetlen elérésű fájlok

A java.io.RandomAccessFile, kb. mint egy bájtvektor, olvasható és írható. Fájlmutató az aktuális pozícióra, ez lekérdezhető (getFilePointer()), állítható (seek(int)). Implementálja mind a DataInput, DataOutput interfészeket (mindkettőt egyszerre), a műveleteivel tetszőleges típus írható, olvasható (úgy használható, mint a DataInputStream, DataOutputStream: write*(), read*() függvények), byte-ok átugorhatók (skip(int)).

Példaalkalmazás:

package files;

import java.io.IOException;import java.io.RandomAccessFile;

public class RandomFileTest { public static void main(final String[] args) throws IOException { final RandomAccessFile raf = new RandomAccessFile("dummy.dat", "rw");

raf.writeInt(0xCAFEBABE); raf.seek(16); raf.writeInt(0xDEADBEEF); raf.seek(32); raf.writeInt(0xBADF00D0); raf.seek(48); raf.writeInt(0xDEADC0DE); raf.close(); }}

Megjegyzés: bájtokat írunk ki, nem elfelejteni! Hexa módban kell megnyitni a fájlt, hogy lássuk ténylegesen mi is íródott ki, pl. Total Commander + F3 + 3, vagy vi + ":\%!xxd".

Gotchaz:

write(int) - hiába van int paramétere, csak byte-ot ír ki, a legalját seek(), write(...) - nem tolódik tovább a stream, kézzel kell mindent odébbmásolni raf.seek(file.length()); - file végére ugrás, ahhoz hozzáfűzés write() - elfogad byte[] paramétert, de writeBytes() - csak Stringet EOFException - elindexelésnél (IOException leszármazottja)

Részletesen: http://download.oracle.com/javase/6/docs/api/java/io/RandomAccessFile.html

Feladatok

Készíts egy szűrő programot, amely két parancssori argumentumot kap: egy input fájl elérési utat, és egy stringet! A program olvassa be az inputfájlt, és írja ki a képernyőre azokat a sorokat, amelyekben a megadott karakterlánc előfordul!

Készíts egy programot, amely két parancssori argumentumot kap: egy input fájl elérési utat, és egy stringet! A program olvassa be az inputfájlt, és számolja meg a megadott szó előfordulásainak számát!

Készíts egy interaktív programot, amely a felhasználó által megadott sorokat (egészen az üres sorig) elmenti egy fájlba. Az output fájl nevét kérje be a program indulásnál.

32 / 89

Page 33: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Készíts egy programot, amely egy parancssori argumentumként megadott fájlnak kiírja az első N sorát (N=5 alapértelmezett értékkel rendelkezik, azonban opcionális parancssori argumentummal ezt állítani lehessen).

Készíts egy programot, amely egy parancssori argumentumként megadott fájlnak kiírja az utolsó N sorát (N=5 alapértelmezett értékkel rendelkezik, azonban opcionális parancssori argumentummal ezt állítani lehessen).

Készíts egy programot, amely három parancssori argumentumot kap: két input fájl és egy output fájl elérési utat. A program fűzze össze az első két fájlt egymás után az output fájlba!

Adott egy fájl a következő szerkezettel: # Comment sor # Ezeket at kell ugrani # A file formatuma: # <Nev>:<Szuletesi ev>:<honap>:<nap> Citad Ella:1984:10:10 Har Monika:1956:5:6 Git Aron:1992:11:23 Tek Elek:2002:6:14

A program olvassa be ezeket az adatokat, és tárolja egy megfelelő reprezentációban (készíts pl. egy Person osztályt a szükséges adattagokkal). A program parancssori argumentumként kapjon egy hónapot, és listázza ki, hogy az adott hónapban mely személyeknek van születésnapja. Használjátok a String osztály split() metódusát.

Készíts egy programot, amely kiírja egy parancssori argumentumként megadott fájl páratlan sorait a képernyőre, páros sorait pedig egy "even.txt" fájlba! Ezután a "even.txt" tartalmával felülírja az eredeti fájlt.

Készítsünk egy egyszerű l33t5p34k (leetspeak) generátort! A program 1 parancssori argumentumot kapjon: egy input fájl elérési utat. A program olvassa be az input fájlt, és minden szón végezze el a következő módosításokat, majd írja ki a képernyőre a módosított szöveget:

o Ha a szó vége: "s" helyett "z" "ck" helyett "x"

o "a" helyett "@" o "e" helyett "3" o "i" helyett `"1"o "o" helyett "0" o "u" helyett "v" o "f" helyett "ph" o "s" helyett "$" o "g" helyett `"9"o "y" helyett "j" o "t" helyett "+" o "!" helyett "1" o Ezen kívül minden 2. karakter esetén a kisbetűből csináljon nagyot, a nagybetűből kicsit!

Készítsünk egy Sudoku ellenőrző programot! A program inputja egy fájl, amelynek soraiban pontosan 81 karakter található, és egy-egy Sudoku sorfolytonos ábrázolását jelenti. A program outputja egy fájl legyen, amelyben az érvényes kitöltést tartalmazó sorok kerülnek bele!

Példa input fájl sorok:

123456789123456789123456789123456789123456789123456789123456789123456789123456789 123456789234567891345678912456789123567891234678912345891234567891234567912345678

Készítsünk egy egyszerű konzolos alkalmazást, amely képes fájlok bináris karbantartására! A program első paraméterként kapja meg a szerkesztendő fájl nevét. A további paraméterek a következők lehetnek:

o mb <pozíció> <byte>: az adott pozíción lévő byte érték módosításao mi <pozíció> <int>: az adott pozíción lévő int érték módosításao i <pozíció> <szöveg>: a specifikált szöveg beillesztése az adott pozícióra. A program illessze be a

szöveget, azaz tolja el a bájtokat megfelelőképp

33 / 89

Page 34: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

IO GyakorlásTree

Készíts egy alkalmazást, amely faszerkezetű megjelenítéssel képes kiírni a konzolra egy könyvtárban található fájlokat.

Példa:

$ java io.gyak.Tree /src+- src/ +- site/ +- apt/ | +- index.apt | +- xdoc/ | +- other.xml | +- fml/ | +- general.fml | +- faq.fml | +- site.xml

Pwd

Készíts egy alkalmazást, amely kiírja a képernyőre az aktuális könyvtár teljes elérési útját.

Példa:

$ java io.gyak.Pwd/var/home/belkar

Grep

A parancs két paramétert kap legalább: egy input fájl elérési utat, amelyből kiírja a képernyőre azokat a sorokat, amelyek az összes többi paraméterként megadott szót tartalmazzák.

$ cat /etc/passwdroot:x:0:0:root:/root:/bin/bashopeator:x:11:0:operator:/root:/sbin/nologin$ java io.gyak.Grep /etc/passwd rootroot:x:0:0:root:/root:/bin/bash

Könyvtárméretek

Készíts egy programot, amely kiírja a képernyőre a parancssori argumentumként megadott könyvtárban található fájlok neveit, méretét, valamint az összes mért fájl méretnek hány százalékát teszi ki az adott fájl! A programnak fogadjon el egy -R kapcsolót, amelyre ugyanezt rekurzívan megteszi minden alkönyvtárra is!

$ java io.gyak.DirSizes .A.txt 1024 20%B.txt 4096 80%

Cut

Az első, paraméterként megadott fájl minden sorának egy megadott oszlopát "vágja ki" és jeleníti meg. A kívánt oszlopok az alábbi módon adhatók meg:

* `-c2`: második mező értéke* `-c3,5`: harmadik, ötödik mező, sorrend nem számít* `-c1-3`: az elsőtől a harmadik mezőig* `-c-4,6-`: az elsőtől a negyedik mezőig és a hatodiktól az összes mező

Find

Készíts egy programot, amely két parancssori argumentumot kap: egy könyvtárat és egy mintát. A program rekurzívan járja be a könyvtárt, és írja ki az összes olyan fájlnevet, ami illeszkedik a megadott mintára!

34 / 89

Page 35: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Sort

Készíts egy programot, amely két parancssori argumentumot kap: egy input és egy output fájl elérési utat. A program rendezze lexikografikusan a megadott input fájlt, és írja ki a megadott output fájlba!

Merge

Készíts egy programot, amely legalább két parancssori argumentumot kap. Az első egy output fájl, amelybe összefűzi egymás utáni sorrendben a megadott fájlokat.

35 / 89

Page 36: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Gyűjtemény keretrendszerGeneric - Bevezetés

Egyelőre csak a collectionökhöz, bevezető jelleggel. Típussal paraméterezhetőség. Type erasure: csak fordítási időben ismert a típusinformáció, utána automatikusan törli a fordító, bájtkódból nem szerezhető vissza - nem C++ template-ek, nem generálódik fordítási időben új típus, nincs template metaprogramozás.

Nem kötelező velük foglalkozni (@SupressWarnings({"rawtypes", "unchecked")}), de rendkívül hasznosak, fordítási időben tudunk potenciális hibalehetőségeket kiszúrni - persze ez is a programozón múlik. Kényelmes, típusbiztos. Aki meg heterogén adatszerkezeteket használ, megérdemli.

Collectionöknél aktívan használjuk őket:

Vector<String> s = new Vector<String>();

Az előnyük:

// Pre-1.5 era:Vector v = new Vector();

v.add( new Integer(1) );v.add( new Integer(2) );

for (int i=0, n=v.size(); i<n; ++i) { Integer act = (Integer) v.get(i); System.out.println(act);}

// Uj:Vector<Integer> v = new Vector<Integer>();v.add(1);v.add(2);

for (int i=0, n=v.size(); i<n; ++i) { Integer act = v.get(i); System.out.println(act);}

Autoboxing-unboxing

Csak objektum referenciákat tárolhatnak, ezért primitív típusok helyett ún. csomagoló (wrapper) osztályokat (Integer, Character, Double, etc.) kell használnunk - azonban ezek ilyen esetekben automatikusan konvertálódnak (ld. fenti példa). Amire figyelni kell: teljesítmény, == operátor, null unboxing NullPointerException-nel jár.

Példa:

v.add(1);// Implicit a kovetkezot jelenti:v.add( new Integer(1) );

v.add(1);boolean eq = v.get(0) == v.get(1); // LEHET hamis! (*)

v.add(null);for (int act : v) { ... } // RECCS!

Megjegyzés A (*)-gal jelölt rész speciel pont mindig igaz lesz, de ez mágia műve: a -127-126 intervallumon lévő számok wrapper objektumait cache-eli a virtuális gép, azok mindig ugyanazok a példányok lesznek. Így itt tapasztalható probléma nem lép fel, de általában ezzel gond lehet.

Gyűjtemény keretrendszer

Collections Framework, java.util.* csomag, objektumok memóriában tárolására, lekérdezése, manipulálása (v.ö. C++ STL). Általános célú adatszerkezetek:

Collection o Listo Dequeo Set

SortedSet

36 / 89

Page 37: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

o Map SortedMap

Nem megvalósított művelet UnsupportedOperationException kivételt dob. Copy konstruktorok vannak (egyik a másikra konvertálható). Műveletek 3 csoportja:

1. Alapvető műveletek: size(), isEmpty(), contains(), add(), remove() 2. Elemek együttes kezelése: addAll(), containsAll(), removeAll(), clear(), retainAll() 3. Tömbbé konvertálás - gány:

A[] arr = (A[]) list.toArray(new A[list.size()]);

// Kicsit egyszerubb, bar kevesbe hatekony, biztonsagos:A[] arr = (A[]) list.toArray();

Iterátorokkal rendelkeznek, használhatók for-each-ben. Példa:

package collections;

import java.util.Vector;

public class VectorTest { public static void main(String[] args) { Vector<Double> vector = new Vector<Double>();

for (int i=0; i<5; ++i) { vector.add( Math.random() ); }

for (double act : vector) { System.out.println(act); }

// Ellenorzeskeppen kiirhatjuk a teljes vektort az alabbi modon is: System.out.println(vector); }}

Halmaz

Duplikált elemeket nem tartalmazhat, kell hozzá az objektumon az equals() és hashCode() (hashelő implementációk, nem számít a sorrend, 2 halmaz egyenlő, ha ugyanazokat az elemeket tartalmazzák). HashSet, TreeSet: előbbi hatékonyabb, utóbbi rendezett.

Feladat

Készíts egy programot, amely megszámolja a parancssori argumentumként megadott fájl szavaira, hogy azokban hány különböző betű van (kis-, és nagybetűk között ne tegyünk különbséget, és az egyéb karakterekkel ne foglalkozzunk)! A megvalósításhoz használj halmazt (Set<Character>, String#toCharArray())! Példa output:

$ cat input.txtIa! Shub-Niggurath! The Black Goat of the Woods with a Thousand Young!$ java collections.CharCounter input.txtIa! -> 2Shub-Niggurath! -> 11The -> 3Black -> 5Goat -> 4of -> 2the -> 3Woods -> 4with -> 4a -> 1Thousand -> 8Young! -> 5

Lista

Elemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását távolítja el, az add(), addAll() a lista végéhez fűz hozzá. Két lista egyenlő, ha ugyanazokat az elemeket tartalmazzák, ugyanabban a sorrendben. A lista iterátora a ListIterator, 2 irányban is bejárható: hasNext(), next(), ill. hasPrevious(), previous(). Részlista: balról zárt, jobbról nyílt intervallumot kell megadni. Két alapvető implementáció: ArrayList, LinkedList, előbbi a pozicionáló műveleteknek kedvez, utóbbi akkor, ha a lista elejére kell sokat beszúrni, és iteráció közben törölni (általában az ArrayList használata a célravezetőbb).

37 / 89

Page 38: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Feladat

Készíts egy programot, amely a parancssori argumentumként megadott fájl szavait lexikografikusan rendezi, az eredményt kiírja a képernyőre, és el is menti egy (szintén parancssori argumentumként megadott) fájlba! A feldolgozás előtt minden nem alfanumerikus karaktert távolíts el a szavakból. A megvalósításhoz használ egy tetszőleges lista adatszerkezetet (ArrayList, LinkedList, Stack, Vector), valamint a java.util.Collections#sort() függvényt! Példa output:

$ cat input.txtPh'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn$ java collections.StringSorter input.txt output.txt[Cthulhu, Phnglui, Rlyeh, fhtagn, mglwnafh, wgahnagl]$ cat output.txtCthulhuPhngluiRlyehfhtagnmglwnafhwgahnagl

Leképezés

Kulcs-érték párokhoz: HashMap, Hashtable (minimális különbség: utóbbi szinkronizált, megengedi a null értékeket is). Minden kulcshoz egy érték tartozhat. Nem iterálható, azonban lekérdezhető a keySet(), entrySet(), ami már igen.

Feladat

Készíts egy programot, amely megszámolja egy fájlból az egyes szavak előfordulásainak számát! A program a fájl elérési útját argumentumként kapja. A megvalósításhoz használj egy String → Integer leképezést (HashMap<String, Integer>)! Példa output:

$ cat input.txtIa! Ia! Cthulhu fhtagn!$ java collections.WordCounter input.txt{Ia!=2, Cthulhu=1, fhtagn=1}

Megoldási javaslat: minden szó esetén ellenőrizd le, hogy szerepel-e már az adatszerkezetben. Ha nem, rakd bele 1-es értékkel; ha igen, vedd ki az előző értékkel, és eggyel nagyobb értékkel tedd vissza!

Rendezés

Beépített típusoknak értelemszerű a relációja - felhasználói típusokat a programozó dönti el. Comparable interfész compareTo() metódusa, melynek eredménye int típusú:

0, ha a két objektum egyenlő < 0, ha az adott objektum kisebb a paraméternél > 0, ha fordítva

Implementáció:

class Foo implements Comparable<Foo> { ... public int compareTo(final Foo foo) { return ...; }}

Ha ennek használatára nincs lehetőség, marad egy saját Comparator készítése (pl. egyazon objektumot több szempont szerint kell rendezni).

Feladat

Készítsetek egy Date osztályt, amely tartalmazza az év, hónap, nap adatokat (mind számok). Implementáljátok vele a Comparable<Date> interfészt, és ennek megfelelően valósítsátok meg a compareTo() függvényt! Hozzatok létre kódból 3 objektumot, és tároljátok el ezeket egy tetszőleges lista adatszerkezetben. Ezt aztán rendezzétek le kronológiai sorrend szerint a Collections#sort() függvénnyel, és írjátok ki az eredményt!

38 / 89

Page 39: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Kényelmi lehetőségek

1. java.util.Arrays#asList(): tömbből listát csinál2. java.util.Collections

o nCopies(int n, Object o): két paraméter, amely n-szer tartalmazza o-to Egyelemű, üres, módosíthatatlan, szinkronizált listáko Algoritmusok:

Rendezés, összefésüléses módszerrel (n log(n), rendezett listát már nem rendez, szemben a quick sorttal): sort()

Összekeveerés: shuffle() Megfordítás, feltöltés, másolás: reverse(), fill(), copy() Bináris keresés: a keresett elem első talált indexét adja vissza, vagy (-i-1)-et ad vissza, ahol i az

első olyan elem indexe, amely nagyobb a keresett elemnél. Minimum, maximum elem: min(), max()

Megjegyzések:

capacity() != size() Az interfész műveleteken kívül rengeteg egyéb hasznos funkcionalitás, érdemes a javadocot olvasgatni Saját implementációk: hajrá! A Collections Framework absztrakt osztályokat biztosít (AbstractList, AbstractSet,

etc.), lehet származtatni. További adatszerkezetek: Dequeue, Stack, BitSet, Vector, etc. Felhasználás: paraméterként, változódeklarációként célszerű minél általánosabb interfészt megadni (a collections

framework előnye a rugalmassága):

Vector<Integer> v1 = new Vector<Integer>(); // vektorkent kezelesList<Integer> v2 = new Vector<Integer>(); // listakent kezeles

Részletesen: http://download.oracle.com/javase/tutorial/collections/index.html http://download.oracle.com/javase/6/docs/api/java/util/package-summary.html

Feladat

Készítsünk egy sorozat rendező alkalmazást! A program inputja a következő formátumú fájl legyen:

# evad : epizod : cim12:7:Super Fun Time12:4:Canada on Strike8:13:Cartman's Incredible Gift10:8:Make Love, Not Warcraft

A # karakterrel kezdődő sorokat hagyjuk figyelmen kívül (használjuk a vizsgálat előtt a String#trim())! Készítsünk egy Sitcom osztályt a megfelelő adattagokkal (season, episode, title), és implementáljuk vele a Comparable<Sitcom> interfészt! A compareTo() működjön úgy, hogy elsődleges szempont szerint az évad, azon belül pedig az epizódszám alapján rendezzen! Az adatokat tároljuk egy Vector<Sitcom> adatszerkezetben. A saját osztály helyes működéséhez implementáljuk az equals(), toString(), hashCode() függvényeket is!

A program beolvasás után rendezze a használt vektort, és biztosítson egy interaktív konzolos felületet a felhasználónak, amely a következő funkcionalitásokkal rendelkezzen:

Új epizód felvétele Epizódlista mentése (kilépés után ezt töltse be) Adott epizód adatainak módosítása Epizódok listázása a képernyőre Kilépés

39 / 89

Page 40: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

GenericEgyszerűbb példák (java.utilcsomagból):

public interface List<E> { void add(E x); Iterator<E> iterator();}

public interface Iterator<E> { E next(); boolean hasNext();}

E - formális típusparaméter, amely aktuális értéket a kiértékelésnél vesz fel (pl. Integer, etc.).

Altípusosság

Nem konvertálhatók, ennek oka:

List<String> l1 = new ArrayList<String>();List<Object> l2 = l1; // error

// Mert akkor lehetne ilyet csinalni:l2.add(new Object());l1.get(0); // reccs, Object -> String castolas

Magyarul ha S <= T =x=> G<S> <= G<T> - ez pedig ellent mond az ember megérzésének. Castolni lehet (warning), instanceof tilos (fordítási hiba)!

Wildcardok

Probléma: általános megoldást szeretnénk, amely minden collectiont elfogad, függetlenül az azokban tárolt elemektől (pl. ki szeretnénk őket írni), vagy nem tudjuk azok konkrét típusát (pl. legacy code). Collection<Object> nem őse (ld. előző bekezdés). Ha nem használunk genericeket, megoldható, viszont warningot generál:

void print(Collection c) { for (Object o : c) System.out.println(o);}

A megoldás a wildcard használata: Collection<?> minden kollekcióra ráillik. Ilyenkor Objectként hivatkozhatunk az elemekre:

void print(Collection<?> c) { for (Object o : c) System.out.println(o);}

Vigyázat! A ? != Object! Csak egy ismeretlen típust jelent. Így a következő kódrészlet is fordítási hibához vezet:

List<?> c = ...;l.add(new Object()); // forditasi hiba

Nem tudjuk, hogy mi van benne, lekérdezni viszont lehet (mert tudjuk, hogy minden objektum az Object leszármazottja).

Bounded wildcard

Amikor tudjuk, hogy adott helyen csak adott osztály leszármazottai szerepelhetnek, első (rossz) megközelítés:

abstract class Super {}class Sub1 extends Super {}class Sub2 extends Super {}...void func(List<Super> l) {...} // Rossz!

Probléma: func() csak List<Super> paraméterrel hívható meg, List<Sub1>, List<Sub2> nem lehet paramétere (nem altípus). Megoldás: bounded wildcard:

void func(List<? extends Super> l) {...}

40 / 89

Page 41: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Belepakolni ugyanúgy nem tudunk, mint a ? esetén, azaz erre fordítási hibát kapunk:

void func(List<? extends Super> l) { l.add(new Sub1()); // reccs}

Felfelé is megköthető a wildcard a <? super T> jelöléssel.

Generikus osztályok, függvények

Osztálydefinícióban bevezethető típusparaméter az osztályhoz, ez minden membernél használható. Példa:

package generics;

public class Pair<T, S> { private final T first; private final S second;

public Pair(final T first, final S second) { super(); this.first = first; this.second = second; }

public T getFirst() { return first; } public S getSecond() { return second; }

// Esetleges null ellenorzeseket tessek elvegezni! // Itt az attekinthetoseg kedveert ettol eltekintettem. @Override public boolean equals(final Object obj) { if (obj instanceof Pair) { Pair<?, ?> pair = (Pair<?, ?>) obj; return first.equals( pair.first ) && second.equals( pair.second ); }

return false; }

// Esetleges null ellenorzeseket tessek elvegezni! // Itt az attekinthetoseg kedveert ettol eltekintettem. @Override public int hashCode() { return first.hashCode() + second.hashCode(); }

@Override public String toString() { return "(" + first + ", " + second + ")"; }

}

Generikus függvények esetén szintén a definícióban használható. Példa:

package generics;

public class ArrayUtils { public static final <T, S extends T> boolean isIn(final T[] arr, final S element) { for (final T t : arr) { if (t.equals(element)) return true; }

return false; }

public static void main(final String[] args) { final String[] sarr = {"a", "b", "c"}; System.out.println( isIn(sarr, "c") ); }}

Részletesen: http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

41 / 89

Page 42: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Feladatok

A megoldáshoz készített osztályokat tegyétek a javagyak.generics csomagba, valamint a teszteléshez használt osztályokat (amik a main() definícióit is tartalmazzák) a javagyak.test csomagba!

Triple

Készíts el egy generikus Triple osztályt, amely 3 (nem feltétlen) különböző típuból alkotott rendezett hármas! Valósítsd meg vele a szokásos műveleteket (equals(), toString(), hashCode())!

Reverse

Készíts egy generikus reverse() függvényt, amely egy tetszőleges lista adatszerkezetet képes visszafelé kiírni a képernyőre!

Fill

Készíts egy generikus fill() függvényt, amely a paraméterként kapott, tetszőleges lista minden elemét lecseréli a megadott elemre.

addAll()

Készíts egy generikus addAll() függvényt, amely egy tetszőleges lista adatszerkezetbe beleteszi a második paraméterként megadott lista összes elemét!

MiniMax

Készíts egy olyan generikus min() és max() függvényt, amely egy tetszőleges kollekcióban megkeresi és visszaadja a minimális és maximális elemet! (Cseles! Kell a Comparable interfész is ugye...).

Tömbös (*)

Készíts két generikus függvényt: az egyik segítsen tömböt kollekcióvá konvertálni, a másik pedig kollekcióból tömböt.

Stack (*)

Készíts egy saját, generikus Stack implementációt! Az implementáció illeszkedjen a Java gyűjtemény keretrendszerébe! Ennek módját tetszőlegesen megválaszthatod, a reprezentációt is, de a Collection<E> mindenképp legyen őse!

Generikus bináris keresőfa (*)

Készítsünk egy egyszerű, általános bináris keresőfa implementációt! A fához lehessen elemet hozzáadni (add()), kiírni, valamint a minimum, maximum elemet megkeresni (min(), max()). A típusparaméterének összehasonlíthatónak kell lennie (<T extends Comparable<T>>).

42 / 89

Page 43: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Reflection"Önelemzés" - futás közben a program lekérdezheti a lehetőségeit, milyen részekből áll, etc. Lehetőségek: program passzív vizsgálata (pl. ahol a program publikus szolgáltatásainak felderítése, Java Beans), ill. korlátozottan egyes részek módosítása (pl. láthatóság).

A Java Core Reflection erősen típusos, biztonságos felület osztályok, objektumok vizsgálatára, használható a következőkre (amennyiben a biztonsági szabályok ezt lehetővé teszik):

új objektumok, tömbök létrehozása adattagok lekérdezése, módosítása függvények lekérdezése, meghívása tömbelemek lekérdezése, módosítása új osztályok létrehozása

Fontos osztályok: java.lang.reflect.* csomag:

Field, Method, Constructor adattagok, függvények (invoke(...)), konstruktorok (newInstance(...)) lekérdezéséhez

Class osztály-, ill. interfész információk eléréséhez Package csomagok kezeléséhez Proxy új osztályok létrehozásához Array tömbök dinamikus létrehozása, lekérdezése Modifier módosítók visszafejtésében segít (public, protected, final, etc.)

Class

Objektumreferencia megszerzése: Objektumtól lekérdezhető:

Class<?> clazz = this.getClass();

Osztálytól lekérdezhető:Class<?> intClazz = int.class;

Közvetlenül név szerint lekérdezhető:Class<?> clazz = Class.forName("java.lang.Boolean");

Új osztály létrehozása:Proxy.getProxyClass(clazz.getClassLoader(), clazz.getInterfaces());

Példa

package reflection;

import java.lang.reflect.Method;import java.lang.reflect.Modifier;

public class ReflectionTest { public static void analyze(final Class<?> clazz) { System.out.println("Osztaly neve: " + clazz.getName()); System.out.println("Csomagja: " + clazz.getPackage()); System.out.println("Osossztalyanak neve: " + clazz.getSuperclass());

System.out.println("Deklaralt public fuggvenyek:"); for ( final Method act : clazz.getDeclaredMethods() ) { if ( Modifier.isPublic( act.getModifiers() ) ) { System.out.println(act.getName()); } } }

public static void main(final String[] args) { analyze( ReflectionTest.class ); }}

Feladatok

43 / 89

Page 44: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Készíts egy programot, amely egyetlen parancssori argumentumot kap, egy osztály teljes hivatkozási nevét (fully qualified name), és

eldönti, hogy az adott osztály belső, névtelen, vagy lokális osztály-e. Ha egyik sem, akkor nézze meg, hogy felsorolási típus, annotáció vagy interfész-e (a sorrendre figyeljetek, mert az annotáció is interfésznek minősül).

bejárja az osztályban deklarált összes adattagot, és kiírja azok nevét, típusát, és módosítószavait. megkeresi az osztály összes publikus, deklarált konstruktorát, valamint kiírja azok paramétereinek a számát. lekérdezi az összes adattagot, és megnézi, hogy hányhoz van getter, setter függvény definiálva, valamint hány olyan

van, amelyhez mindkettő definiálva van. megvizsgálja, hogy az adott osztálynak van-e nullary (zero-arg) konstruktora, és ha talál ilyet, csinál belőle egy

példányt, valamint az alapértelmezett toString() függvényének a segítségével kiírja a képernyőre. kiírja az összes (azaz nem csak a deklarált!) függvény módosítószavait, visszatérési értékének típusát, nevét, valamint

paramétereinek típusát. végigmegy az adott osztály összes statikus függvényén, és készít egy listát az ezen függvények által dobható

kivételekről.

Részletek http://download.oracle.com/javase/6/docs/api/java/lang/reflect/package-frame.html

Megjegyzés Primitív típusok (+void), pl. boolean reprezentációjának Class példánya java.lang.Boolean.TYPE (ezeknek van egy rövidebb formája is, jelen esetben ez a boolean.class, többinél ugyanígy).

Tömbök

Az Array osztály segítségével manipulálhatók az elemek (getter, setter függvények), új tömbök hozhatók létre (newInstance()), ill. a Class osztálynak vannak hasznos függvényei, pl.:

package reflection;

public class ReflectionArrayTest { public static void arrayTest(final Class<?> clazz) { if ( ! clazz.isArray()) { System.out.println("Nem tomb"); return; }

Class<?> act = clazz; int dim = 0; while (act.isArray()) { act = act.getComponentType(); dim++; }

System.out.println( dim + " dimenzios"); System.out.println( "Belso tipusa: " + act.getSimpleName()); }

public static void main(final String[] args) { arrayTest( new int[][] { {1, 2}, {3}}.getClass() ); }}

Megjegyzés Hülye jelölés, nem szívrohamot kapni:

int[][] arr = { {1, 2}, {3} };System.out.println( arr );

// Eredmeny: [[I@42e816

Ok: B - byte, C - char, D - double, F - float, I- int, J - long, Losztálynév - osztály vagy interfész, S - short, Z - boolean, [ - tömb

Feladat

Készítsünk egy programot, amely képes létrehozni egy adott típusú tömböt, majd az elemeit beállítani egy kitüntetett értékre. A program a paramétereket parancssori argumentumként kapja (elég a 8 primitív típusra felkészülni, valamint String objektumokra).

Feladat

44 / 89

Page 45: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Készíts egy mélységi String deepToString(Object[] arr) segédeljárást tömbökhöz! A függvénynek egyetlen paramétere legyen: a kiírni kívánt tömb. A függvény menjen végig a az elemeken, és vizsgálja meg őket. Ha az nem tömb, akkor fűzze hozzá a szöveges reprezentációját az objektumnak a visszaadott Stringhez. Ha tömb, akkor vizsgálja meg mind a nyolc primitív típusra (elementClass == byte[].class, etc.), és annak megfelelően dolgozza fel az elemeket. Ha nem primitív típus az elemtípus, akkor hívja meg a rekurzív függvényt újabb feldolgozásra!

Függvények

Függvényeket meg is tudunk hívni, ld. Method#invoke(Object o, Object... args) függvény. Ha a függvény statikus, akkor az első paraméter lehet null (különben reccs), paraméterlista lehet üres, visszatérési értéke egy Object. Példa:

package reflection;

import java.lang.reflect.Method;

public class Invoking { public static int add(final int a, final int b) { return a + b; }

public static void main(final String[] args) throws Exception { final Method method = Invoking.class.getMethod("add", new Class[] { Integer.TYPE, Integer.TYPE });

System.out.println( method.invoke(null, 1, 2) ); }}

Feladat

Készíts egy tetszőleges objektumot, majd reflection segítségével keresd meg az összes, paraméter nélküli getter függvényét! Ezeket hívd is meg reflection segítségével, és az eredményüket írd ki a képernyőre!

Feladatok

Osztályhierarchia

Készítsünk egy programot, amely képes egy adott osztály osztályhierarchiáját előállítani, valamint meg tudja mondani, hogy pontosan milyen interfészeket implementál (az ősosztályok által implementáltakat is)! Az osztály nevét parancssori argumentumként kapjuk. Példa:

interface I1 {}interface I2 extends I1 {}

class A implements I2 {}class B extends A {}

A B osztály vizsgálata esetén a következő listát adja vissza a program:

[class reflection.B, class reflection.A, interface reflection.I2, interface reflection.I1, class java.lang.Object]

Here be dragons!

Bizonyítsd be, hogy a String osztály csak gyengén tekinthető immutable osztálynak (azaz reflection segítségével kiügyeskedhető az általa reprezentált szöveg megváltoztatása)!

A szöveg legyen ugyanolyan hosszú, de egy karakterét tetszőlegesen változtasd meg. A program megírásához szükséged lesz a String osztály forráskódjára (esetleg reflectionnel történő vizsgálatára), ezt a JDK/src.zip fájlban találhatod meg (vagy a különböző IDE-k segíthetnek a felkutatásában, pl. Eclipse alatt a Ctrl + Snift + T billentyűkombináció).

Megjegyzés Az ilyesmivel azért csak offtosan! Mivel magában a reprezentációban turkálunk, anélkül, hogy figyelnénk az objektum konzisztenciájának megőrzésére, gondok lehetnek a használatából (pl. a String#hashCode() is lazy instantiationnel cache-eli az eredményt)! Ugyanakkor - sajnos - néha elkerülhetetlen, ilyenkor rendkívül hasznos tud lenni ez a csel.

45 / 89

Page 46: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

GUIAbstract Windowing Toolkit (nehézsúlyú) vagy Swing (pehelysúlyú komponensek). Előbbi oprendszer szintű, utóbbi Javaban íródott, független az oprendszertől. Egyéb ablakozó keretrendszer is használható (pl. SWT, Qt, etc.).

Használható komponensek (beviteli, vezérlő, megjelenítő komponensek): http://download.oracle.com/javase/tutorial/ui/features/compWin.html

Ill. C:/Program Files/Java/jdk1.6/demo/jfc alatt SwingSet2 és SwingSet3 példa alkalmazások.

Példakód

package gui.basics;

import java.awt.*;

public class AWTTest { Frame frame = new Frame("AWTTest"); Label label = new Label("Hello AWT!");

public AWTTest() { frame.add(label); frame.setSize(200, 100); frame.setLocation(300, 300); frame.setVisible(true); }

public static void main(String[] args) { AWTTest test = new AWTTest(); }}

Életciklus

1. Felület felépítése. Egyszerű példa alkalmazás

package gui.basics;

import java.awt.*;

public class AWTTest { Frame frame = new Frame("GUI Test"); TextField textField = new TextField("10"); Button button = new Button("Ok"); Label label = new Label("=");

public AWTTest() { frame.setLayout(new FlowLayout());

frame.add(textField); frame.add(button); frame.add(label);

frame.setVisible(true); frame.setSize(200, 100); frame.setLocation(300, 300); }

public static void main(String[] args) { AWTTest test = new AWTTest(); }}

1. Használata (eseményfigyelők)

button.addActionListener( new ActionListener() { @Override public void actionPerformed(final ActionEvent ae) { try { final int N = Integer.parseInt(textField.getText()); int res = 1; for (int i=2; i<=N; ++i) res *= i; label.setText("= " + res); } catch (final NumberFormatException e) { label.setText(e.getMessage()); }

}});

46 / 89

Page 47: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

1. Bezárása

frame.addWindowListener( new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); }});

Adapterek, Listenerek

XXXListener interfész, ha nem kell az összes esemény, használható az XXXAdapter absztrakt osztály is (üres implementációkat tartalmaz). Pl. WindowListener, WindowAdapter. Hívási lánc alapján.

Fontosabb Listenerek:

ActionListener: menü, gombnyomás, Enter egy TextField objektumon

public void actionPerformed(ActionEvent e) { ... }

KeyListener: Billentyű leütése

public void keyTyped(KeyEvent e) { ... }public void keyPressed(KeyEvent e) { ... }public void keyReleased(KeyEvent e) { ... }

MouseListener: Egérlenyomás (van MouseMotionListener, MouseWheelListener is)

public void mousePressed(MouseEvent e) { ... }public void mouseReleased(MouseEvent e) { ... }public void mouseEntered(MouseEvent e) { ... }public void mouseExited(MouseEvent e) { ... }public void mouseClicked(MouseEvent e) { ... }

WindowListener: ablak eseményeinek kezelése

public void windowActivated(WindowEvent e) { ... }public void windowClosed(WindowEvent e) { ... }public void windowClosing(WindowEvent e) { ... }public void windowDeactivated(WindowEvent e) { ... }public void windowDeiconified(WindowEvent e) { ... }public void windowIconified(WindowEvent e) { ... }public void windowOpened(WindowEvent e) { ... }

Stb., lásd referenciát.

Elrendezési stratégiák

Részletesen http://download.oracle.com/javase/tutorial/uiswing/layout/visual.html

BorderLayout BoxLayout CardLayout FlowLayout GridBagLayout GridLayout GroupLayout/SpringLayout

Komponensek

Konténer komponensek (Container), legfelső szinten top-level containerek ((J)Applet, (J)Frame vagy (J)Dialog). Minden grafikus osztály közös őse: (J)Component. A java.awt.* csomagban.

Panel (konténer) Label Button RadioButton TextArea, TextField etc.

47 / 89

Page 48: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Swing

Az osztályok nevének közös prefixe egy J betű. AWT-s eseménykezelés itt is megvan. A javax.swing.* csomagban (Java extended). További előnyök:

Független az oprendszertől Szabad forma Átlátszó felületek Egyszerűen módosítható megjelenés

Menük

frame.setMenuBar(), MenuBar → Menu, Menu → Menu vagy MenuItem. Van szeparátor is.

JMenuBar menuBar = new JMenuBar();

JMenu fileMenu = new JMenu("File");menuBar.add(fileMenu);

JMenuItem exitMenu = new JMenuItem("Exit");fileMenu.add(exitMenu);exitMenu.addActionListener( ... )

frame.setJMenuBar(menuBar);

Üzenetablakok

JOptionPane.showXXXDialog(), pl.:

JOptionPane.showMessageDialog(null, // ki az ose, ha van, akkor modalis "alert", // uzenet "alert", // title JOptionPane.ERROR_MESSAGE // tipus);

Részletesen http://download.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html

Scrollozható komponensek

frame.add( new JScrollPane(textArea) );

Linkek

http://community.java.net/javadesktop http://java.sun.com/javase/technologies/desktop/articles.jsp http://download.oracle.com/javase/tutorial/ui/index.html http://download.oracle.com/javase/tutorial/uiswing/index.html

Feladatok

Szövegszerkesztő

48 / 89

Page 49: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Készítsünk egy egyszerű szövegszerkesztő alkalmazást! A programból a menüből lehessen szöveges állományt megnyitni, elmenteni, valamint kilépni.

Ezen kívül az alábbi funkciók közül legalább kettőt valósíts meg!

Használj tooltipeket, amikben HTML formázott szöveg van (setToolTipText("<html> ..."))! Állíts be az alkalmazásnak egy tetszőleges ikont (setIconImage(...))! Készíts egy Help menüt, amibe teszel egy egyszerű About... menüelemet. Ha erre rákattint a felhasználó, írja ki a

program verziószámát, valamint a készítő nevét (JOptionPane)! Állíts be gyorsgombokat és mnemonicokat az egyes menüelemekhez (setAccelerator(...), setMnemonic(...))! Az alkalmazás egy JFileChooser segítségével válassza ki, hogy milyen fájlt szeretnél megnyitni! Használj egy JTabbedPane panelt, amivel egyszerre több állomány is megnyitható!

Kirakós

Készítsünk egy egyszerű, 3x3-as kirakós játékot! A fő panel tartalmazzon 9 nyomógombot, amelyeken 1..8-ig számok szerepelnek, a kilencediken pedig egy "*" karakter. A számokat kezdetben véletlenszerűen helyezzük el (Math.random(), de az is elég, ha van egy beégetett összekevert kombináció). Ha egy számot tartalmazó nyomógombra kattintunk, akkor ha az szomszédos a "*" karakterrel, cseréljük fel a gombok szövegét! A cél, hogy a számokat sorfolytonosan kirakjuk, és a "*" karakter a jobb alsó sarokban legyen. Ha ezt sikerült elérnie a felhasználónak, adjunk egy gratuláló üzenetet!

49 / 89

Page 50: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

GUI KiegészítésListenerek egyéb megvalósításai

Saját listener megvalósítása:

public class GUI1 { private final JButton ok = new JButton("Ok");

private class OkButtonActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { System.out.println("Ok pressed"); } }

public GUI1() { OkButtonActionListener listener = new OkButtonActionListener(); ok.addActionListener(listener); }}

vagy maga az osztály implementálja az interfészt, mindenre rá lehet aggatni, majd setActionCommand() ill. getActionCommand() függvény használható a megkülönböztetésre:

public class GUI2 implements ActionListener { private final JButton ok = new JButton("Ok"); private final JButton cancel = new JButton("Ok");

private final String OK_COMMAND = "ok"; private final String CANCEL_COMMAND = "cancel";

public GUI2() { ok.addActionListener(this); ok.setActionCommand(OK_COMMAND);

cancel.addActionListener(this); cancel.setActionCommand(CANCEL_COMMAND); }

public void actionPerformed(ActionEvent e) { if (OK_COMMAND.equals(e.getActionCommand())) { System.out.println("Ok pressed"); } else if (CANCEL_COMMAND.equals(e.getActionCommand())) { System.out.println("Cancel pressed"); } }}

Komplexebb grafikus felület

Containerekkel (Panel, JPanel).

TODO: kép

JOptionPane

Ha super != null, akkor modális, pl.:

JFrame frame = ...;...JOptionPane.showMessageDialog( frame, "Modalis uzenet");

MVC

Model-View-Controller. Egyes GUI komponensek nem direkt módon tárolják az adatokat (többféle reprezentáció), ilyenkor modelleket kell használni (pl. JProgressBar, JNumberSpinner, JTable, stb.). Példa:

int val = progressBar.getModel().getValue();progressBar.getModel().setValue(++val);

50 / 89

Page 51: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

BorderLayout

Használatra példa:

JPanle panel = new JPanel( new BorderLayou() );

panel.add( new JLabel("North"), BorderLayout.NORTH );panel.add( new JLabel("South"), BorderLayout.SOUTH );panel.add( new JLabel("East"), BorderLayout.EAST );panel.add( new JLabel("West"), BorderLayout.WEST );panel.add( new JLabel("Center"), BorderLayout.CENTER );

CardLayout

Példa:

final static String APANEL = "Panel 1";final static String BPANEL = "Panel 2";

JPanel card1 = new JPanel();JPanel card2 = new JPanel();

CardLayoult layout = new new CardLayout();cards = new JPanel( layout );cards.add(card1, APANEL);cards.add(card2, BPANEL);

layout.show(cards, APANEL );layout.show(cards, BPANEL );

layout.first(cards);layout.last(cards);

JRadioButton

ButtonGroup használata kell, ha szeretnénk, hogy egyszerre csak választható ki közülük:

JRadioButton button1 = new JRadioButton("A");JRadioButton button2 = new JRadioButton("B");

ButtonGroup group = new ButtonGroup();group.add( button1 );group.add( button2 );

JFileChooser

Használatnál figyeljünk a visszatérési értékre!

final JFileChooser fc = new JFileChooser();...int ret = fc.showOpenDialog( frame );if ( JFileChooser.APPROVE_OPTION == ret ) { ...}

Feladatok

Hex editor

Készíts egy egyszerű hexadecimális szövegszerkesztőt! Egy sorban 16 karakter legyen, amely az egyes bájtok értékeit reprezentálják. A program kínáljon lehetőséget byte, int módosításra, adott pozíción, megadott értékkel. A szövegmezőn keresztüli szerkesztés legyen letiltva (setEnabled(false)). Ha megnyomják a modify gombot, akkor az adott értéket írjuk ki a file-ba (RandomAccessFile segítségével) a megadott pozícióra, és frissítsük a szövegmező tartalmát!

51 / 89

Page 52: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Képernyőterv - Hex editor

Kvíz alkalmazás

Készítsünk egy egyszerű kvíz-alkalmazást, amely az alábbi típusú kérdéseket tartalmazhatja:

Eldöntendő kérdés, pl.: Hány fia volt Ádámnak a Biblia szerint? ( ) 2 ( ) 3 (*) 33

Kiválasztós, pl.: Mely országok határosak Magyarországgal? [x] Szerbia [x] Szlovénia [ ] Japán

Minden kérdésben 3-3 lehetőség van. Ezeket fájlból olvassuk, inicializálás során. A formátuma a következő:

C:Hany versszakbol all a himnusz?:4:6:8:false:false:true S:Mely szamok primek?:1:2:7:false:true:true ...

Az inputban : karakterrel elválasztva 8 mező található, ezek jelentések a következő:

Az első karakter megmondja, hogy milyen típusú kérdés adatait tartalmazza az adott sor. C = eldöntendő, S = kiválasztós kérdés

A kérdés szövege A lehetséges 3 válasz A válaszok helyessége

A játék képernyőterve az alábbi ábrán található.

52 / 89

Page 53: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Képernyőterv - Kvíz alkalmazás

A program a következő funkciókat biztosítsa:

Egyszerre 5 kérdést adjon Lehessen menüből kilépni, valamint új játékot kezdeni (ezekre kérjen megerősítést a program!) A program jelezze a teszt kitöltöttségét egy JProgressBar segítségével Pontozás: minden jól megválaszolt eldöntendő kérdés 10 pont. Minden eltalált kiválasztós kérdés 5 pont. A játék végén írjon ki egy gratuláló üzenetet, amely tartalmazza, hány pontot ért el a felhasználó

Példakérdések http://people.inf.elte.hu/legendi/java/res/questions.txt

További lehetőségek

Játékot lehessen elmenteni, betölteni! (memento) Egyszer lehessen segítséget kérni egy '?' gombbal! Ha használtuk, tiltsuk le a gombot. A végén meg lehessen nézni az eredményeket. Itt színes labelekkel jelezzük, hogy sikerült az adott kérdést teljesíteni

(zöld - OK, piros - Fail, sárga - skip).

53 / 89

Page 54: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

NetworkingElméletben OSI modell ("All People Seem To Need Data Processing" vagy "Please Do Not Throw Salami Pizza Away"), gyakorlatban TCP/IP:

Alkalmazás (SMTP, Telnet, FTP, etc.), Transzport (TCP vagy UDP), Hálózati (IPv4, IPv6), Adatkapcsolati, Fizikai rétegek (kommunikáció)

Szolgáltatási pont definiálásához három dolog kell:

Internet cím (IPv4 vagy DNS által feloldva) Protokoll azonosító (TCP v. UDP) Port (lehet TCP, UDP is, a címtartományok függetlenek (!), 16 bites egész érték 0-65535)

Java esetén a java.net.* csomag használható.

Összeköttetés-alapú kapcsolat

Kliens-szerver modell, a szerver általában:

Lefoglal egy TCP portot Várakozik egy kliens kapcsolódására Ha kliens jelzi a kapcsolódási szándékát, felveszi vele a kapcsolatot, és kiszolgálja Folytatja a 2. ponttól

A kliens működése általában:

Lefoglal egy TCP portot, ezen keresztül kommunikál a szerverrel Kapcsolódik a másik végponton a szerverhez, azon a porton, amelyet az közzétett Lezajlik a kommunikáció A kliens bontja a kapcsolatot a szerverrel

Megjegyzések

a kliens lokális portját nem kell ismernünk a kapcsolat kiépítése után az full-duplex (kétirányú) a szerver szinte mindig többszálú (ld. következő óra!)

Összeköttetés-mentes kapcsolat

Majd előadáson ;]

Címek kezelése

Hasznunkra válik az InetAddress osztály:

getByName(String): név → cím getByAddress(byte[]): IPv4/6 → cím getAllByName(): név → címek (attól függ, hogy van behegesztve a NS) getLocalHost(): → saját cím

Részletesen http://download.oracle.com/javase/6/docs/api/java/net/InetAddress.html

Példa

54 / 89

Page 55: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Szerveralkalmazás

package networking;

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;

public class SimpleServer { public static void main(final String[] args) throws IOException { final int port = Integer.parseInt(args[0]); final ServerSocket server = new ServerSocket(port);

Socket client = null;

while (true) { client = server.accept(); final BufferedReader br = new BufferedReader( new InputStreamReader(client.getInputStream())); final PrintWriter pw = new PrintWriter(client.getOutputStream());

final String line = br.readLine(); System.out.println("Got message: " + line);

final String ret = new StringBuilder(line).reverse().toString(); System.out.println("Sending reply: " + ret);

pw.println( ret ); pw.flush();

client.close();

if (line.equals("exit")) { break; } }

server.close(); }}

Használat

$ java SimpleServer 5000

Kliens alkalmazás

package networking;

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;

public class SimpleClient { public static void main(String[] args) throws UnknownHostException, IOException { String host = args[0]; int port = Integer.parseInt(args[1]); String value = args[2];

Socket socket = new Socket(host, port);

BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream());

System.out.println("Message: " + value); pw.println(value); pw.flush();

System.out.println( "Response:" + br.readLine() ); socket.close(); }}

Használat

55 / 89

Page 56: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

$ java SimpleClient localhost 5000 mentegetnem$ java SimpleClient localhost 5000 ideseggesedi$ java SimpleClient localhost 5000 exit

Palindromok, haha http://hu.wikipedia.org/wiki/Magyar_nyelvű_palindromok_listája

Internet és a WWW-objektumok elérése

Socketek helyett [Http]URLConnection osztály használatával.

Hasznos segédeszközök

ping, netstat, netcat, telnet, tcpdump, etc.

Feladatok

Konzolos HTTP kliens

Készítsünk egy egyszerű alkalmazást, amely egy megadott HTML oldalt megjelenít a konzolon. Ennek szabványos kommunikációja így zajlik:

$ telnet index.hu 80Trying 217.20.130.97...Connected to index.hu.Escape character is '^]'.GET / HTTP/1.1Host: index.hu

$

Megjegyzés A végén két új sor karakter van!

Port scanner

Készítsetek egy minimális port scanner alkalmazást! A programnak egyetlen parancssori argumentuma legyen, a tesztelendő host címe. Ezután a program az [1..1024] intervallumban (ezek az ún. well known portok) tesztelje végig, hogy hol fogad kapcsolatot az adott gép (próbáljon meg egy TCP socket kapcsolatot létrehozni). Amennyiben ez sikeres, jelezzük a felhasználónak, majd írjuk ki, hogy milyen szolgáltatás fut valószínűleg a gépen. Localhoston teszteljétek. A host azonosításához használjátok az InetAddress osztályt!

Egy lista, amely tartalmazza a szolgáltatások neveit: http://www.iana.org/assignments/port-numbers

Bonyolultabb feladatok

Chat alkalmazás

Készítsünk egy közös chat alkalmazást! Ti írjátok a kliens programot, amely csatlakozik a pandora.inf.elte.hu szerver 5000-es portjára. A program parancssori argumentuma a felhasználó választott nickneve (ez csak alfanumerikus karaktereket tartalmazhat).

Indulás után építsen ki egy standard TCP kapcsolatot, majd küldje el a szervernek a "NICK nick" üzenetet. Ezután a felhasználó megkapja a jelenleg chatelő nickneveket (; karakterrel elválasztva, egyetlen sorban). Ha új felhasználó lép a chatszobába, minden más felhasználó kap egy "JOIN nick" üzenetet. Ha valamely felhasználó bontja a kapcsolatot, minden más felhasználó kap egy "QUIT nick" üzenetet. Ha a szervert valamely okból leállítják, minden felhasználó kap egy "DISCONNECT message" üzenetet. Ha valaki üzenetet küld, akkor minden más felhasználó kap egy "MSG message" üzenetet. A szerver minden üzenetre visszajelez: "OK uzenet", vagy "ERR hibauzenet" formában (pl. az adott nicknév ár

foglalt, etc.). A fenti programhoz készíts egy tetszőleges vezérlő felületet (lehet konzolos, lehet grafikus).

Tetszőleges protokoll megvalósítása

56 / 89

Page 57: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Válassz ki egy tetszőleges alkalmazási protokollt (HTTP, SMTP, FTP, IRC, stb.). Készíts egy minimális kliens alkalmazást hozzá, amely egyszerű funkciók ellátására képes. Nézz utána, hogy működik az adott protokoll, majd próbáld meg telnet segítségével használni. Ha sikerül, írj a kisebb funkciókra egy programot.

Tipp Google → FTP over telnet

57 / 89

Page 58: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

ThreadingMottó: "Concurrency is hard and boring. Unfortunately, my favoured technique of ignoring it and hoping it will go away doesn't look like it's going to bear fruit."

Párhuzamosság: több részfeladat egyidejűleg történő végrehajtása.

Miért?

A feladat logikai szerkezete A program több, fizikailag is független eszközön fut Hatékonyság (v.ö. Amdahl's law )

Elég régóta foglalkoztatja az embereket. Látszat párhuzamosságról is hallani még (oprendszerek, multitasking: egyszerre egy folyamatot hajt végre, de adott időtartam alatt akár többet is), de a valódi párhuzamosság is már mindennapos (pl. többmagos, többprocesszoros gépekben).

Párhuzamosság szintjei Utasítások Taskok Folyamatok (processes) Szálak (threads)

Viselkedésük alapján lehetnek:

Függetlenek Versengők Együttműködők

Alapproblémák Kommunikáció: kommunikációs közeg: socket, signal handler, fájl, osztott memória,

etc. Szinkronizáció: folyamatok összehangolása, szinkron - aszinkron

Alapdefiníciók Szinkronizáció Olyan folyamat, amellyel meghatározható a folyamatokban szereplő

utasítások relatív sorrendje Kölcsönös kizárás osztott változók biztonságos használatához Kritikus szakasz program azon része, ahol egy időben csak egyetlen folyamat

tartózkodhat Atomi művelet bármilyen közbeeső állapota nem látható a többi folyamat számára

Miért kell ez az egész? Pl. x++, 64 bites JVM , long-on ábrázolva 2 regiszterben van tárolva → 2 olvasás + 2 írás

58 / 89

Page 59: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Szálak létrehozásaKét lehetőség:

1. Thread osztályból származtatva: a run() metódust kell felüldefiniálni, majd a start() segítségével indítható az új szál. Megjegyzés: start() függvényt nem bántod, csak ha hívod a super.start() függvényt is!

Példa:

package threading;

class TestThread extends Thread { @Override public void run() { System.out.println("TestThread"); }}

public class Create1 { public static void main(String[] args) { TestThread test = new TestThread(); test.start(); }}

Névtelen osztállyal ugyanez:

new Thread() { @Override public void run() { System.out.println("TestThread"); }}.start();

1. Runnable interfész implementálása: ha a származtatás nem lehetséges (pl. a fő osztály egy JFrame, Applet, stb.). Egyetlen függvényt ír elő: run(), melyet meg kell valósítani. Indítani úgy lehet, ha egy Thread objektumnak megadod paraméterként, és arra meghívjuk a start() eljárást:

package threading;

class TestRunnable implements Runnable { @Override public void run() { System.out.println("TestRunnable"); }}

public class Create2 { public static void main(String[] args) { Thread thread = new Thread( new TestRunnable() ); thread.start(); }}

59 / 89

Page 60: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Ugyanez névtelen osztállyal:

new Thread( new Runnable() { @Override public void run() { System.out.println("TestRunnable"); }}).start();

Szálak függvényei start(): indítás stop(): megállítás (deprecated). Megjegyzés: utána érdemes a Thread referenciát null

értékre állítani. suspend(), resume(): felfüggesztés, majd újraindítás (deprecated) join(): másik szál befejezésének megvárása sleep( <milis> ): adott időnyi várakozás yield(): well, ehh... getName(): konstruktorban beállítható név lekérdezése (később már nem változtatható) getThreadGroup(): konstruktorban beállítható csoport (később már nem változtatható).

Egyszerre egyhez tartozhat, hierarchiába szervezhető (egy csoport más csoportokat is tartalmazhat).

setDaemon(): daemon szál készítése (akkor terminál, ha minden más, nem daemon szál is már terminált).

setPriority( <prior> ): prior lehet 1-10, fontosságot jelöl. OS függő, hogy pontosan milyen hatása van. Időosztásos (time slicing) rendszereken nincs gond vele, egyébként egy "önző" szál teljesen befoglalhatja a CPU-t.

Részletesen http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html

Megjegyzés Sok deprecated függvény, mert könnyen deadlockhoz vezethetnek (pl. erőforrás lefoglalásának megszüntetése). Mindig van kerülőút, pl. szál leállítására:

private volatile isRunning = true;

public void stopRunning() { isRunning = false;}

@Overridepublic void run() { while ( isRunning ) { ... }}

Felmerülő problémák Azon túl, hogy megbízhatóság \dots Holtpont kölcsönösen egymásra várakoznak a folyamatok, és egyik sem tud tovább

haladni Kiéheztetés több folyamat azonos erőforrást használ, és valamelyik ritkán fér csak

hozzá Versenyhelyzetek amikor egy számítás helyessége függ a végrehajtó folyamatok

sorrendjétől (pl. check-then-act blokkok) Nemdeterminisztikus végrehajtás kétszer ugyanazt a viselkedést produkálni

lehetetlen, debuggolás esélytelen60 / 89

Page 61: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

A szinkronizációt ezen problémák elkerülésével kell megoldani.

Kölcsönös kizárásJavaban ún. szinkronizációs burok van:

synchronized ( resource ) { ...}

Ez garantálja, hogy az azonos lockhoz tartozó blokkokban egyszerre egy szál lehet csak (gond - kódblokkot védünk, nem erőforrást). A synchronized használható példány-, és osztályfüggvény módosítószavaként, ekkor a jelentése:

public synchronized void f() { ...}

// Ekvivalens:public void f() { synchronized ( this ) { ... }}

Illetve osztályfüggvények esetén:

class MyClass { public static synchronized void s() { .... }

// Ekvivalens: public static void s() { synchronized ( MyClass.class ) { ... } }}

Megjegyzés ha csak egy szál változtathat egy változót, a többi csak olvassa, akkor jöhet jól a volatile kulcsszó, amely garantálja, hogy a szálak nem cache-elik az adott változó értékét, mindig a frissítik (ld. a stop() kiváltására írt példát feljebb!).

Megjegyzés Immutable osztályokhoz nem kell szinkronizálni!

Szinkronizáció üzenetekkelFeltételes beváráshoz: Object osztályban definiált wait(), notify() és notifyAll() függvények. A wait() hívásának hatására a szál elengedi a lockot és blokkolódik, amíg egy másik szál nem jelzi számára, hogy az adott feltétel teljesül (notify()).

Használatához mindig egy monitor szükséges, különben futásidejű hibát kapunk!

61 / 89

Page 62: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

synchronized (monitor) { monitor.wait();}

synchronized (monitor) { monitor.notify();}

Deadlockra példapackage threading;

public class Deadlock { public static void main(String[] args) { final Object res1 = new Object(); final Object res2 = new Object();

new Thread() { @Override public void run() { synchronized (res1) { System.out.println("1 - Got res1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (res2) { System.out.println("1 - Got res2"); } } } }.start();

new Thread() { @Override public void run() { synchronized (res2) { System.out.println("2 - Got res2"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (res1) { System.out.println("2 - Got res1"); } } } }.start(); }}

62 / 89

Page 63: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Szálak állapotaiLásd az alábbi ábrát.

Ábra - Szálak állapotai

KollekciókSzinkronizált vs. nem szinkronizált adatszerkezetek (pl. Vector vs. ArrayList). Az iterátorok ún. fail-fast iterátorok: ha bejárás közben módosítják az adatszerkezetet, reccsen egy java.util.ConcurrentModificationException kivétellel:

package threading;

import java.util.ArrayList;

public class FailFast { public static void main(final String[] args) throws InterruptedException { final ArrayList<String> list = new ArrayList<String>(); for (int i=0; i<100; ++i) list.add("" + i);

final Thread reader = new Thread() { @Override public void run() { try { for (final String act : list) { System.out.println(act); Thread.sleep(100); }

63 / 89

Page 64: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

} catch (final InterruptedException e) { e.printStackTrace(); } } };

reader.start(); Thread.sleep(500);

list.remove(50); }}

Szinkronizált adatszerkezetek készítése wrapperekkel, példa listára, másra analóg módon:

final List<T> list = Collections.synchronizedList(new ArrayList<T>(...));

Java Concurrency - Java 1.6A java.util.concurrent.*, java.util.concurrent.atomic.*, java.util.concurrent.lock.* csomagok változatos, hatékony eszközöket nyújtanak:

Barrier, Semaphor, FutureTask, ... Adatszerkezetek: ConcurrentHashMap, BlockingQueue, ... Lockok, pl. ReentrantLock, ... Atomi változók: AtomicLong, AtomicReference, ...

Feladatok1. Készíts egy 2 szállal működő programot, amelyek neve térjen el! A szálak tízszer

egymás után írják ki a képernyőre a nevüket, majd várjanak egy keveset (0-5 másodpercet, véletlenszerűen).

2. Készíts 5 szálat, amelyek a következő prioritás-szintekkel futnak: 3, 4, 5, 6, 7 (ez szerepeljen a szálak nevében is!). A szálak egy végtelen ciklusban írják ki a nevüket. Elemezd az eredményt!

3. Készíts egy 5 szállal dolgozó programot, amelyek ugyanazt a közös változót kiírják, majd csökkentik (100-ról 0-ra). Figyelj a szinkronizációra, és a végén ellenőrizd le, hogy valóban helyes outputot kaptál-e!

4. Készíts egy 3 szálú alkalmazást! Legyen egy termelő, és két fogyasztó szálunk. Az termelő szál induljon el, és töltsön fel egy kollekciót 10 db véletlen számmal (a másik két szál indulás után várjon)! Ezután jelezzen a másik két szálnak (wait(), notify()), hogy elkezdhetik a számok feldolgozását: adják össze őket. Az eredeti szál várja be a feldolgozást, majd írja ki a részösszegek összegét!

5. Kérdezd le egy új szálban az összes futó szálat, és írd ki azok neveit! Értékeld a látottakat egy grafikus alkalmazás indítása eseten (ehhez rekurzívan be kell járni a getParent()-eket)!

6. Készíts 2 szálat! Az első állítsa elő az első tíz hatványát a kettes számnak (majd várjon egy másodpercet), a másik legyen egy daemon szál, amely a nevét írja ki, majd vár egy másodpercet egy végtelen ciklusban.

7. Készíts 5 szálat, amelyek egy saját csoportban vannak! A szálak egy véletlen számot választanak az [1..100] intervallumból, és fél másodpercenként növelnek egy saját számlálót ezzel az értékkel, amíg az meg nem haladja az 1000-et.

64 / 89

Page 65: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

A szálak elindítása után a fő szálban várjunk 10 másodpercet, majd listázzuk ki az aktív szálakat, a maximális prioritást a szálak között, és írjunk ki egy listát a szálakról és azok tulajdonságairól! Ezután függesszük fel az összes szálat, írjuk ki a szülő ThreadGroup nevét, majd újra indítsuk el az összes szálat a saját csoportunkban. A végén pedig várjuk be az összes szálat! 8. Készíts egy egyszerű grafikus alkalmazást, amely egyetlen panelt tartalmaz, az aktuális idővel. A panelen található információt másodpercenként frissítsd! Az osztály definíciója nézzen ki a következőképpen:

public class ... extends JFrame implements Runnable { ...}

1. Egészítsd ki az előző feladatot úgy, hogy ha ráklikkel a felhasználó a megjelenített JLabel-re, akkor szüneteltesse a frissítést a program. Ha újra ráklikkel a felhasználó, akkor folytassa a számlálást!

ParallelPortScanner

Egészítsd ki a Networking gyakorlaton készített port scanner alkalmazást, hogy 2. parancssori argumentumként meg lehessen mondani hány szállal hajtsa végre párhuzamosan a vizsgálatot!

Parallel keresőmotor

Készítsünk egy saját WWW keresőmotort, amely egy cím → URL kereső adatbázist képes készíteni! A program 5 szál használatával keressen az interneten, minden szám max. 50 weboldalt járjon végig, és írják ki egy közös fájlba soronként a weboldal címét (a <meta name="title" content="xxx"> értékét), valamint az éppen vizsgált URL-t. Parancssori argumentumként kapjon egy URL címet, amelyet végigolvasva további URL címeket keressenek a szálak.

65 / 89

Page 66: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Threading - Kiegészítés StringBuilder vs. StringBuffer StringBuffer szinkronizált, a StringBuilder nem,

cserébe hatékonyabb (nincs szinkronizációs költség). Szál indítása Figyeljetek! Nem a run(), hanem a start() függvény használandó erre.

Előbbi hatására ugyanúgy szekvenciális programunk lesz. Deprecated függvények a Thread osztályban Erősen deadlock-prone függvények. Pl.

egy szál synchronized blokkban van, és suspendelik, akkor nem fogja elereszteni az erőforrásokat, így más nem juthat hozzá - így könnyen deadlock alakulhat ki. Részletes magyarázat, megoldások, workaroundok itt találhatók: http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

synchronized(this) Ez rossz! Nem a this miatt, hanem mert egy közös használatú változót különböző objektumokkal védesz le! A this minden esetben az aktuális példányt jelenti (ami példányonként nyilván különbözik), az i változó pedig mindnél ugyanaz.

static int i = 0;

class T extends Thread { public void run() { synchronized(this) { i++; }}

Feladat Adott v_1, v_2, ..., v_n vektorok, amelyen n szál dolgozik. A program parancssori argumentumként kap egy e értéket. Keressük meg az első olyan j indexet, ahol ez a szám megtalálható, vagyis v_i[j] = e, 1 <= j <= n. Az egyszerűség kedvéért feltételezzük, hogy minden vektorelem egyedi, valamelyik vektorban megtalálható a keresett e érték, és n=2.

'Nuff said, let's rock!

1. kísérletIndítsunk két szálat. Közös változó a found, lokális változó a v, i.

found = false; i = 0; // Awhile (!found) { // B found = v.get(i) == e; // C i++; // D}

FAIL

Tegyük fel, hogy az egyes szál elindult, az i. elem épp e, C végrehajtása után kapja meg a vezérlést a második szál. A inicializáló utasításával found ismét hamis lesz végtelen ciklus.

66 / 89

Page 67: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

2. kísérletJa, akkor nem a szálakban inicializálok. Kerüljük el, hogy minden szál külön-külön is inicializálja a közös változót, tegyük meg ezt a szálak indítása előtt!

found = false // Threadek inditasa elott

i = 0; // Awhile (!found) { // B found = v.get(i) == e; // C i++; // D}

FAIL

Tegyük fel, hogy az egyes szál C-hez ér, végrehajtja, és épp megtalálja az adott értéket! Így found értéke igaz lesz. De! Ha közben a másik szál is C-nél volt, és ezután hajtódik végre, found értéke ismét hamis lesz, az eredmény végtelen ciklus.

3. kísérletOuch, tényleg! Csak akkor adjunk új értéket a found változónak, ha megtaláltuk az elemet.

i = 0; // Awhile (!found) { // B if (e == v[i]) b = true; // C i++; // D}

FAIL

Tegyük fel hogy az első szál az első elemében rögtön fel is fedezi az e keresett értéket, és terminál (sérül a feltétlen pártatlan ütemezés elve, a szálak nem dolgoznak szinkronban). Ekkor a második szál soha nem terminál, az eredmény végtelen várakozás.

4. kísérletJó, akkor ütemezek én! Vezessünk be egy next flaget, amely jelölje, hogy melyik szál futhat a while ciklusba való belépés után! A feltételhez kötött várakozást await szimbólummal jelölve, az első szál definíciója:

i = 0; // Awhile (!found) { // B await (1 == next) { next = 2; } // C if (e == v[i]) b = true; // D i++; // E}

valamint a második szál definíciója legyen a következő:

j = 0; // Awhile (!found) { // B await (2 == next) { next = 1; } // C if (e == v[j]) b = true; // D j++; // E}

67 / 89

Page 68: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

FAIL

Tegyük fel, hogy az első szál eljut D végrehajtásáig, majd ezután a második szál is eljut ugyaneddig (next értékét 2-re állítva). Tegyük fel, hogy a második szál következő eleme nem a keresett e elem, így a C ponton tovább várakozik. Ha eközben az első szál megtalálja a keresett elemet, és terminál, az eredmény holtpont.

5. kísérletOoooh! És ha terminálásnál is jelzek?! A szálak terminálásánál is figyeljünk a next változóra! Az első szál kódját módosítsuk a következőképp:

i = 0; // Awhile (!found) { // B await (1 == next) { next = 2; } // C if (e == v[i]) b = true; // D i++; // E}next = 2; // F

a másodikét pedig az alábbi módon:

j = 0; // Awhile (!found) { // B await (2 == next) { next = 1; } // C if (e == v[j]) b = true; // D j++; // E}next = 1; // F

Na ez már menni fog.* :-)

Lásd mégPeterson-féle algoritmus kölcsönös kizárás megoldására, vektorértékadás atomicitása nélkül.

Irodalom1. Brian Goetz et al.: Java Concurrency in Practice, Addison-Wesley Professional, May

19, 2006.2. Kozma, L. és Varga, L.: A szoftvertechnológia elméleti kérdései, ELTE Eötvös Kiadó,

első kiadás 2003, második kiadás 2006.

Kliens-szerver architektúraA szerveroldali kód:// Raakaszkodas a portraServerSocket ss = new ServerSocket( port );// Fuss, amig...while (true) { // Egy bejovo kapcsolat elkapasa Socket newSocket = ss.accept(); // Kapcsolat kezelese // ...}

68 / 89

Page 69: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

FeladatKészítsetek egy többszálú chat szerveralkalmazást, valamint egy klienst hozzá! Ha valaki küld egy üzenetet a szervernek, a szerveralkalmazás broadcastolja azt mindenki másnak is. A szerver a 2442 számú porton figyeljen, és ide csatlakozzanak a kliensek is!

A szerveralkalmazás minden egyes bejövő kapcsolatot külön szállal kezeljen, a váza valahogy így nézzen ki:

ServerSocket socket = new ServerSocket(PORT);while (true) { new Handler(socket.accept()).start();}

A kliensek is legyenek többszálú alkalmazások: az egyik szál folyamatosan figyelje, hogy nem jön-e új üzenet a csatornán, miközben a másik szál írjon a csatornára, ha a felhasználó üzenetet írt a konzolra!

Linkek Socket példa http://www.oracle.com/technetwork/java/socket-140484.html Java Tutorial, All About Socket fejezete

http://download.oracle.com/javase/tutorial/networking/sockets/index.html

69 / 89

Page 70: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Kapcsolat az adatbázissalKliens-szerver architektúra kiváló különböző adatbázisok eléréséhez: Java DataBase Connectivity. Ez egy szabványos API, java.sql.* (Core API), javax.sql.* (Extension) csomagokban definiált osztályok (v.ö. ODBC).

A szolgáltatások három csoportba sorolhatók:

Kapcsolódás a DB-hez Utasítások végrehajtása Eredmény lekérdezése

A DB elérhető natívan is (kétrétegű modell), de az API három rétegű: egy absztrakt szint bevezetésével leválaszthatók a DB-specifikus dolgok, a kommunikáció a JDBC-n keresztül történik.

MeghajtóprogramokMinden kapcsolathoz szükséges a hozzá tartozó meghajtóprogram betöltése, amely kezeli a kapcsolatot, megoldja a hívások értelmezését és kiszolgálását (változó, hogy milyenek vannak, pl. Oracle fizetős, MySQL ingyenes). Minden ilyen osztály a Driver interfészt implementálja. A futtatáshoz kell a megfelelő meghajtó jar fájl is, pl.:

$ java -cp .;lib/mysql.jar MyMySQLTestClass

Nem kötelező kézzel betölteni, ha több DB-t is támogat a programunk, használhatjuk a DriverManager osztályt, amely megpróbálja betölteni az éppen aktuálisan használt DB-hez a megfelelő meghajtóprogramot.

A kapcsolat a DB-vel a Connection osztályon keresztül történik (egyszerre több kapcsolat is fenntartható, ez a DB beállításától függő érték). Ezt egy URL-ben kell megadni, amely a következő formátummal rendelkezik:

jdbc:alprotokoll:adatforrás_leírása

Ahol:

maga a protokoll a jdbc az alprotokoll megegyezik a forgalmazó nevével az adatforrás leírása pedig tartalmazhatja a DB szerver címét (host:port), az adattábla

nevét, és tartalmazhatja a felhasználó nevét, jelszavát

Itt a gyakon egy egyszerű, minimális DB kezelőt, a Derby-t fogjuk használni ("Java DB is a free, fast, robust, full-featured pure Java database that fits in a 2.5MB JAR file, blah-blah-buzzword-blah-blah)". Elérhető az alábbi címen: http://www.oracle.com/technetwork/java/javadb/overview/index.html. Ehhez a következő osztály dinamikus betöltésére van szükség (ő implementálja a Driver interfészt):

Class.forName("org.apache.derby.jdbc.EmbeddedDriver");

70 / 89

Page 71: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

A driverek specifikáció szerint osztálybetöltéskor egy statikus inicializátor blokkban bejegyzik magukat a DriverManager osztályban, így rendelkezésre állnak. A kapcsolat kiépítéséhez a következő URL-t használhatjuk:

jdbc:derby:[//host:port//]<dbName>[properties]

Ahol a properties tartalmazhatja a következő információkat (ezeket ; karakterekkel választhatjuk el):

create=true Megpróbálja létrehozni a DB-t, ha még nincs. Adattáblákat nem csinál. user=userName DB felhasználó neve. password=userPassword DB felhasználó jelszava. shutdown=true

Példa a használatára:

Connection dbConnection = null;String strUrl = "jdbc:derby:DefaultAddressBook;user=dbuser;password=dbuserpwd";try { dbConnection = DriverManager.getConnection(strUrl);} catch (SQLException e) { e.printStackTrace();}

Másik megoldás (kicsit biztonságosabb), ha property-kbe rakjuk a felhasználó nevét és jelszavát:

Connection dbConnection = null;String strUrl = "jdbc:derby:DefaultAddressBook";

Properties props = new Properties();props.put("user", "dbuser");props.put("password", "dbuserpwd");try { dbConnection = DriverManager.getConnection(strUrl, props);} catch(SQLException sqle) { sqle.printStackTrace();}

Hova kerül a DB? A derby.system.home system property által beállított érték határozza meg. Ezt vagy kódból lehet beállítani:

System.setProperty("derby.system.home", "/tmp");

vagy futtatásnál lehet megadni:

$ java -cp .;lib/mysql.jar -Dderby.system.home="/tmp" MyDerbyTestClass

Ezt a kapcsolatot is ugyanúgy le kell zárni, mint a streameket. És nem, nem a finalize() függvényben!! A kapcsolatról rengeteg hasznos információ elkérhető a getMetaData() függvényhívással.

71 / 89

Page 72: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

TranzakciókezelésTranzakciókezelés támogatott (csak olyan SQL utasítás hajtható végre, amelynek eredményét vagy véglegesítjük a DB-ben (commit), vagy visszavonunk minden változtatást (rollback)). Ez alapból be van kapcsolva, aki kikapcsolja vagy tudja, hogy mit csinál, vagy vessen magára.

JDBC - Java type mappingTODO: táblázat

Utasítások végrehajtásaHárom lehetőség:

Statement: egyszerű SQL utasításokhoz. Gyakon csak ez. PreparedStatement: bemenő paramétereket tartalmazó, előfordított SQL

utasításokhoz. CallableStatement: bemenő, kimenő paramétereket tartalmazó, tárolt eljárások

hívásához.

Statement végrehajtása execute(String): tetszőleges utasításhoz, pl. tábla létrehozása (az áttekinthetőség

érdekében a String literál lezáró " jeleket és a konkatenációt elhagytam):

String strCreateTable = "CREATE TABLE inventory ( id INT PRIMARY KEY, product VARCHAR(50), quantity INT, price DECIMAL )";

statement = dbConnection.createStatement();statement.execute(strCreateTable);

executeQuery(String): lekérdezéshez, az eredmény egy ResultSet objektum lesz. %Mindig olvassátok végig az eredményt, mert addig nem záródik. Pl.:

ResultSet rs = statement.executeQuery("SELECT * FROM inventory");while (rs.next()) { String p = rs.getString("product"); int q = rs.getInt("quantity"); double d = rs.getDouble("price"); ...}

executeUpdate(String): insert, update, delete, és adatdefiníciós utasításokhoz, az eredmény a módosított sorok száma (vagy 0). Pl.:

statement.executeUpdate("DELETE WHERE id=0");

72 / 89

Page 73: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Kötegelt végrehajtásVan rá lehetőség, hogy parancsokat összefogjunk, és egyszerre küldjünk el a szervernek feldolgozásra, így sok kis adatmódosító utasítás gyorsabban lefuthat, mintha külön-külön futtattatnánk le őket. Pl.:

statement.addBatch("Create TABLE ...");statement.addBatch("INSERT INTO ...");statement.addBatch("INSERT INTO ...");statement.addBatch("INSERT INTO ...");...statement.executeBatch();

Az executeBatch() egy tömbbel tér vissza, hogy az egyes utasítások hány sort változtattak a DB-ben (itt [0, 1, 1, 1, ...] lesz).

Részletesen

http://download.oracle.com/javase/tutorial/jdbc/index.html http://www.jdbc-tutorial.com/ http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javadb/

FeladatKészítsetek egy egyszerű adatbázis kezelő grafikus felületet, amely az alábbi ábrán látható! A program tartalmazzon egy JTextField komponenst, ahol a lekérdezést lehet megadni, egy JTextArea komponenst, ahol megjeleníti az eredményt, valamint egy gombot, amivel le lehet futtatni a megadott SQL utasítást.

Képernyőkép - A program grafikus szerkezete

A megvalósításhoz használjátok a következő címen elérhető derby.jar fájlt:

http://people.inf.elte.hu/legendi/resources/java/materials/derby.jar A program az aktuális könyvtár alá, egy derby könyvtárba tegye az adatbázis fájlokat! Egy statikus inicializáló blokkban próbáljuk meg betölteni a szükséges meghajtó

osztályt! Ha ez nem megy, termináljon a program. Az utasítás végrehajtásához használjátok az execute(String sql) függvényt!

73 / 89

Page 74: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Az eredmény objektum bejárásánál elég, ha az elemeket a getString(int) metódussal írjátok ki. Ehhez tudnotok kell, hogy hány oszlop található az eredményben, ezt a ResultSet#getMetaData() függvényen keresztül elért objektumtól tudjátok lekérdezni.

74 / 89

Page 75: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

SzerializációObjektumok "sorosítása", hogy túléljék a JVM-et: elmenthetők, Socketen átküldhetők, DB-ben tárolhatók, etc. Az objektum állapotát bájtokba toljuk ki.

Alapvető működésImplementálni kell a java.io.Serializable interfészt (ún. marker interfész). Ilyenkor a default szerializáció minden adattagot kiment (amennyiben az ős nem szerializálható, akkor abban lennie kell egy nullary konstruktornak, különben kézzel az adattagokat neked kell szerializálni; az Object ennek a kritériumnak megfelel):

package serialization;

import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.Date;

public class PersistentDate implements Serializable { private final Date date = new Date();

public Date getDate() { return date; }

@Override public String toString() { return "" + date; }

public static void save() throws IOException { final ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("date.dat")); oos.writeObject( new PersistentDate() ); oos.flush(); oos.close(); }

public static void load() throws IOException, ClassNotFoundException { final ObjectInputStream ios = new ObjectInputStream( new FileInputStream("date.dat")); final PersistentDate loaded = (PersistentDate) ios.readObject();

System.out.println(loaded); }}

Rekurzív adatszerkezeteknél (oda-vissza hivatkozások) ebből gond lehet.

75 / 89

Page 76: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

"Múlandó" adattagokA Java Core API-ban a legtöbb osztály szerializálható (így ha adattag, akkor ki is tudjuk menteni), azonban nem mind, például az oprendszer szintű osztályok (pl. thread + saját memóriakezelés).

Ha van egy adattagunk, amit nem szeretnénk szerializálni, használhatjuk a transient kulcsszót:

public class PersistentDate implements Serializable { private final Date date = new Date(); private transient Thread updater; ...}

A default protokoll módosításaÍrhatunk saját szerializációs módszert is (kézzel írva hatékonyabb - kényelem vs. hatékonyság), ehhez a következő két függvényeket lehet "felüldefiniálni":

private void writeObject(ObjectOutputStream out) throws IOException;private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;private void readObjectNoData() throws ObjectStreamException;

Nem biztos, hogy az alapértelmezett viselkedést akarjuk megváltoztatni (defaultReadObject(), defaultWriteObject(), ezek használhatók is!), de pl. így tranziens attribútumokat is kiírhatunk, vagy eseményeket köthetünk a szerializációhoz. Pl. ha a fenti szálat el szeretnénk indítani:

private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject();}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); updater.start();}

Megjegyzés Amennyiben teljesen mi szeretnénk felügyelni, használjuk a Externalizable interfészt, így semmit nem kapunk (ősosztályok szerializációját sem!).

Szerializáció letiltásaHa egy származtatott osztályban le akarjuk tiltani a sorosíthatóságot, nincs jobb módszer, mint kivételt dobni:

private void writeObject(ObjectOutputStream out) throws IOException { throw new NotSerializableException("Nem!"); }

76 / 89

Page 77: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new NotSerializableException("Nem!");}

Gotchas Az ObjectOutputStream cache-el! Amint kapott egy referenciát, azt megjegyzi, és a

többiről nem is akar tudni:

oos.writeObject( obj );obj.value = 1; // Hiaba allitjuk at, ha elotte nem 1 voltoos.writeObject(obj); // akkor itt az eredeti erteke lesz

Verziókezelés:

private static final long serialVersionUID = <ronda_nagy_generalt_szam>L;

Teljesítmény: a default Java szerializációnál vannak hatékonyabb frameworkök!

Feladatok Írjatok egy kör osztályt, ami a középpontjának x, y koordinátáit tartalmazza, valamint a

sugarát! Készítsétek fel az osztályt szerializációra! A kör legyen képes megmondani a kerületét! A kerületszámolás legyen lusta

kiértékelésű:

private Double c = null;

public double getCircumference() { if (null == c) { c = new Double(...); }

return c.doubleValue();}

A program a szerializáció során kezelje ezt az attribútumot nem perzisztens attribútumnak!

Készítsz egy egyszerű programot, amely egy tetszőleges String adatszerkezettel rendelkezik (tömb, lista, halmaz, etc.). Oldd meg az osztály szerializációját saját implementációval is! Készíts egy minimális benchmarkot a 2 implementáció teljesítményéről (a megvalósítás méréséhez használd a System.currentTimeMilis() függvényt)

Részletesen

http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html

http://download.oracle.com/javase/6/docs/api/java/io/Externalizable.html

77 / 89

Page 78: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Remote Method InvocationHálózatkezelés: eddig TCP/UDP és kliens-szerver architektúra. Ezt viszont sajnos sok tényező nehezíti:

Ha már egy létező alkalmazást kell felkészíteni hálózati kommunikációra, ahhoz az egészet újra részekre kell bontani (refactor)

Halom boilerplate kódot kell írni: a teljes hálózati protokollt újra kell implementálni az adatátvitelhez, ez elég error-prone feladat.

Megoldás: távoli eljáráshívás. Ez egy magasabb szintű absztrakciós eszköz, lehetővé teszi a procedurális programtervezést: távoli számítógépen lévő függvényeket tudunk hívni (ez persze mindenféle problémákkal járhat). A hívó folyamat felveszi a kapcsolatot a kiszolgáló számítógéppel, becsomagolva elküldi az adatokat, és felfüggesztődik, míg azokat vissza nem kapja.

Javaban ez Remote Method Invocation (RMI, v.ö. RPC) néven fut, hogy illeszkedjen a nyelv OO szemléletéhez (vannak magasabb szintű frameworkok, v.ö. CORBA). Segítségével egy távoli gépen lévő JVM objektumot tudok megszólítani.

ModellA távoli objektumoknak egy távoli interfészt kell megvalósítaniuk (java.rmi.Remote). Ehhez minden konstruktorának, és minden függvényének deklaráltan dobnia kell a java.rmi.RemoteException kivételt. Ami ebben az interfészben nincs definiálva, az a kliensek felé nem fog látszani.

import java.rmi.Remote;import java.rmi.RemoteException;

public interface IEchoRemote extends Remote { public abstract String hi() throws RemoteException;}

Paraméter átadásSzerializáció segítségével minden. Az elemi adattípusok JVM-ben történő ábrázolása rögzített (a típuskonstrukciókkal együtt), így a konverziókkal nem kell foglalkozni (v.ö. C). A szerializált objektum egy bájtsorozatként socketeken átmegy, a visszatérési érték hasonlóan jön vissza.

A kliens és szerver összekapcsolásaAlapvetően két módszer lehetséges:

"Bedrótozzuk" a szerver címét Használunk egy telefonkönyv-szerű szerverprogramot (registry). Ha a szerver elindul,

bejegyzi magát az elérhetőségével, a kliensek pedig innen kérdezhetik azt le. Ez hasznos lehet még, ha pl. terhelésmegosztást (load balancing) szeretnénk megvalósítani.

A java.rmi.Naming osztály műveletei használatának segítségével (lookup(), bind, etc.).

78 / 89

Page 79: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Felmerülő problémákA hálózati fejlesztés így ugyanolyan elvek alapján történhet, mint egy sima desktop alkalmazás fejlesztése, ugyanolyan szintaxissal. Mégis, felmerülhetnek speciális problémák:

A hálózati adatok elveszhetnek A hálózati végpontok leállhatnak Az adatátviteli vonal elromolhat

Probléma: nem tudhatjuk, hogy meddig jutott el a feldolgozásban a szerver, ha nem kapunk tőle választ. Az ilyen esetekre külön fel kell készülni (pl. nyugtázással). Elv: idempotens műveletek (ne legyen felesleges mellékhatása).

A távoli objektum implementációjaSzármaztassunk a java.rmi.server.UnicastRemoteObject osztályt, ez elérhetővé teszi az osztályunkat (megjegyzés: ez nem kötelező, de akkor kézzel kell mindent csinálni, pl. toString(), hashCode(), equals() megfelelő implementálása).

import java.io.File;import java.net.MalformedURLException;import java.rmi.AlreadyBoundException;import java.rmi.Naming;import java.rmi.RMISecurityManager;import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;

public class EchoServer extends UnicastRemoteObject implements IEchoRemote {

private static final long serialVersionUID = 1L; public static final String ADDRESS = "rmi://localhost:1099/echo";

protected EchoServer() throws RemoteException { super(); }

@Override public String hi() throws RemoteException { return "Hoi!"; }

public static void main(final String[] args) throws RemoteException, MalformedURLException { if (null == System.getSecurityManager() ) { System.setSecurityManager(new RMISecurityManager()); }

final EchoServer server = new EchoServer(); Naming.rebind(ADDRESS, server); }}

79 / 89

Page 80: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

A kliens implementációjaimport java.net.MalformedURLException;import java.rmi.Naming;import java.rmi.NotBoundException;import java.rmi.RemoteException;

public class EchoClient { public static void main(final String[] args) throws MalformedURLException, RemoteException, NotBoundException { final IEchoRemote remote = (IEchoRemote) Naming.lookup( EchoServer.ADDRESS ); System.out.println( remote.hi() ); }}

Futtatás1. El kell indítani egy registry szolgáltatást a szerver gépen:2. ::Windows3. start rmiregistry 4.5. # Unix6. rmiregistry &

7. Le kell fordítani a kliens és szerveralkalmazást8. Hozzuk létre a következő policy fájlt:9. grant {10. permission java.security.AllPermission;11. };

12. Futtatni kell a szervert, a következő paraméterekkel:13. -Djava.security.policy=server.policy14. -Djava.rmi.server.codebase=file:/<path_a_classfile_okhoz>

Megjegyzés Figyelni, itt nem file:// kell!

1. Futtassuk a klienst!

Feladatok Készítsetek egy egyszerű hálózati naplózó alkalmazást! A szerver tudjon lementeni

sztringeket egy dedikált fájlba, és a tartalmát is le lehessen kérdezni a kliensekből! A szerver szolgáltatásait RMI segítségével érd el!

Készíts egy egyszerű számológép szervert. Tudjon összeadni, kivonni, osztani, szorozni. A műveleteit RMI segítségével érd el!

Részletesen http://java.sun.com/developer/onlineTraining/rmi/RMI.html

Készítsetek egy alkalmazást, amely kilistázza a megadott registry szerver összes szolgáltatását!

A szerializációval kapcsolatos gyakorlaton létrehozott Circle osztályt adjátok át paraméterként egy RMI szervernek, amely legyen képes visszaadni annak területét!

Készítsetek egy remote shell alkalmazást! A kliens egy interaktív konzolos alkalmazás legyen. Ha a felhasználó beír egy parancsot, azt küldje el a szervernek, az hajtsa végre,

80 / 89

Page 81: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

és az outputot küldje vissza a kliensnek (a végrehajtáshoz használd a Runtime.exec(String cmd) függvényt)!

81 / 89

Page 82: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Környezet beállítása"Hello World!" Microsoft WindowsonMegjegyzés Az alábbi fejezetetek a Java Tutorial egy bevezető fejezetének (kissé átdolgozott) magyar fordítását tartalmazza. A fordítást köszönjük Szabó-Demény Balázsnak! http://download.oracle.com/javase/tutorial/getStarted/cupojava/win32.html

Itt az ideje, hogy megírd az első alkalmazásod! A most következő utasítások Windows XP Professional, Windows XP Home, Windows Server 2003, Windows 2000 Professional, és Windows Vista használóknak szól. Más platformokhoz leírást a "Hello World!" for Solaris OS and Linux és "Hello World!" for the NetBeans IDE cikkekben találsz.

Ha problémákba ütközöl, vess egy pillantást a következő fejezetre, ahol a gyakoribb hibákat és magyarázatukat találod.

Tartalom Szükséges szoftverek Első alkalmazás létrehozása

o Forrás fájl létrehozása o Fordítsd le a forrásfájlt .class formátumra o A program futtatása

Szükséges szoftverekHogy megírd az első programod, szükséged lesz az alábbiakra:

1. Java SE Development Kit 6 (JDK 6) Innen letöltheted a Windowsos verziót (a JDK-t töltsd le, ne a JRE-t): http://www.oracle.com/technetwork/java/javase/downloads/index.html. Kövesd a telepítési utasításokat: http://www.oracle.com/technetwork/java/javase/index-137561.html

2. Szövegszerkesztő Ebben a leírásban a Notepad alkalmazást fogjuk használni, amely minden Windows platformon megtalálható, de bármilyen más szövegszerkesztő is használható. Mindössze ennyi szükséges ahhoz, hogy megírd az első programod.

Első alkalmazás létrehozásaElső alkalmazásod HelloWorldApp névre hallgat, és annyit csinál, hogy kiírja a "Hello world!" üdvözlő szöveget a képernyőre. Ehhez az alábbiak szükségesek:

Hozz létre egy forrásfájlt A forrásfájl Java nyelven írott kódot tartalmaz, amit te és más programozók megértenek. Bármilyen szövegszerkesztőt használhatsz, hogy létrehozd, vagy szerkeszd.

A forrásfájl .class fordítása formátumra A fordító (javac, mint Java compiler) a forrásfájlban lévő szöveget a gép számára érthető utasításokra alakítja. Az így előállított fájl tartalma az ún. bytecode.

A program futtatása A futtató alkalmazás (java) indítja el a virtuális gépet, ami értelmezi a bytecode-ot, és futtatja az alkalmazást.

82 / 89

Page 83: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Forrásfájl létrehozása

Itt két lehetőséged van:

Elmented a HelloWorldApp.java a gépedre, ezzel sok gépelést megspórolsz: http://download.oracle.com/javase/tutorial/getStarted/application/examples/HelloWorldApp.java. Utána folytathatod a következő fejezettel.

Vagy követed az utasításokat :-)

Indítsd el a szövegszerkesztőt. A Notepad alkalmazást a Start menüből indíthatod el. Egy új dokumentumba írd be az alábbiakat:

/** * The HelloWorldApp class implements an application that * simply prints "Hello World!" to standard output. */class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); // Display the string. }}

Megjegyzés Minden kódot, utasítást és fájlnevet pontosan másolj le. Mind a futtató (java), mind a fordító alkalmazás (javac) megkülönbözteti a kis-, és nagybetűket. HelloWorldApp != helloworldapp

Mentsd el a kódot HelloWorldApp.java néven. Ehhez válaszd a Fájl → Mentés másként menüelemet, majd:

1. A Fájlnév mezőbe írd be, hogy "HelloWorldApp.java", az idézőjeleket is.2. A Fájl típusának állítsd be az egyszerű szöveges formátumot: Text Documents (.txt)*.3. A Kódolás legördülő menüben legyen ANSI kiválasztva.

Miután végeztél így kell kinéznie:

Ábra A Mentés másként dialógusablak, közvetlenül a Mentés gomb megnyomása előtt

Ments, és lépj ki a Notepad alkalmazásból!

83 / 89

Page 84: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

A forrásfájl .class fordítása formátumra

Indítsd el a parancsértelmezőt (cmd.exe), ehhez a Start menüben kattints a futtatásra, és írd be "cmd". Ennek az ablaknak így kell kinéznie.

Ábra Parancsértelmező ablak

A parancsértelmező mutatja az aktuális könyvtárat. Ez alapértelmezés szerint általában a felhasználó saját könyvtára (home directory), mint a képen is látható egy Windows XP esetén.

Hogy lefordítsd a forrásfájlt, lépj be abba a könyvtárba, ahova a fájlt mentetted. Például ha ez a könyvtár a C: meghajtón lévő java könyvtár, akkor a következő utasítással teheted ezt meg:

$ cd C:\java

Az aktuális könyvtárad most a C:\java, amelyet a parancsértelmező prompt is jelez.

Megjegyzés Ahhoz, hogy meghajtót válts, szükség van egy másik utasításra is: a meghajtó nevére. Például ha a D: meghajtón lévő java könyvtárba tudj váltani, írd be a megható nevét és egy ":" karaktert. Például:

Ábra Másik meghajtóra váltás

Ha beírod a dir parancsot, láthatod a forrás fájlt, ahogy azt az alábbi ábra is mutatja.

84 / 89

Page 85: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Ábra Mappa tartalmának listázása

Most már készen állsz a fordításra. Ehhez a következőt kell begépelned:

$ javac HelloWorldApp.java

A fordító létrehozta a bytecode állományt, egy HelloWorldApp.class fájlt. A dir paranccsal hatására látható is a megjelenő listán az állományok között.

Ábra Könyvtár lista, amely tartalmazza a generált class fájlt

Most már futtathatod a programot. Ha problémákba ütköztél, vess egy pillantást a következő fejezetre, ahol a gyakoribb hibákat és magyarázatukat találod.

A program futtatása

Gépeld be a következő parancsot abban a könyvtárban, ahol az alkalmazásod található:

$ java HelloWorldApp

A lenti képen találhatod az eredményt.

85 / 89

Page 86: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Ábra A program eredménye

A program kiírja a "Hello World!" üzenetet.

Gratulálunk! Működik a program!

Ha problémákba ütköztél, vess egy pillantást a következő fejezetre, ahol a gyakoribb hibákat és magyarázatukat találod.

Gyakran előforduló hibákFordítási hibák

Általános hiba üzenetek Microsoft Windows rendszeren

'javac' is not recognized as an internal or external command, operable program or batch file

Ha ezt a hibát kapod, a Windows nem találja a fordítót (javac).

Itt egy megoldás a problémára. Tegyük fel, hogy a telepített JDK a C:\jdk6 könyvtárban található. A konzolba írd be a következő parancsot: C:\jdk6\bin\javac HelloWorldApp.java. Így minden alkalommal be kell írni ezt a parancsot, ha fordítani vagy futtatni akarod az alkalmazást. A felesleges gépelés elkerülése végett, olvasd el a JDK telepítési útmutatót (vagy nézd meg az első gyak anyagát :P).

Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested

Elfelejtetted a .java postfixet a fordítás során. Ne feledd, a használandó parancs javac HelloWorldApp.java nem pedig javac HelloWorldApp.

Általános hibaüzenetek UNIX rendszeren

javac: Command not found

Ha ezt a hibát kapod, a UNIX nem találja a fordítót (javac).

Itt egy megoldás a problémára. Tegyük fel, hogy a telepített JDK a /usr/local/jdk6 könyvtárban található. A konzolba írd be a következő parancsot: /usr/local/jdk6/javac HelloWorldApp.java. Így minden alkalommal be kell írni ezt a parancsot, ha fordítani vagy futtatni akarod az alkalmazást. A felesleges gépelés elkerülése végett, olvasd el a JDK telepítési útmutatót (vagy nézd meg az első gyak anyagát :P).

Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested

86 / 89

Page 87: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Elfelejtetted a .java postfixet a fordítás során. Ne feledd, a használandó parancs javac HelloWorldApp.java nem pedig javac HelloWorldApp.

Szintaktikai hibák (minden platformon)

Akkor jelentkezik, mikor hiba van a program kódjában. A hiba üzenet leírja, hogy milyen típusú hiba lépett fel, és hol található a kódban. Így néz ki, ha elhagyod a sort záró jelet (;):

at the end of a statement: testing.java:14: `;` expected. System.out.println("Input has " + count + " chars.") ^ 1 error

Néha a fordító nem tudja kitalálni, hogy mi a szándékod, ezért megtévesztő hibaüzenetet adhat vissza. Például ebből a kód részletből hiányzik egy (;) a vastaggal szedett résznél:

while (System.in.read() != -1) { count++ System.out.println("Input has " + count + " chars.");}

Ebben az esetben a fordító két hibával tér vissza:

testing.java:13: Invalid type expression. count++ ^testing.java:14: Invalid declaration. System.out.println("Input has " + count + " chars."); ^2 errors

A fordító két hibaüzenetet ír ki, mert a count++ elérése után, a fordító azt hiszi, hogy ez egy kifejezés közepén van. A pontosvessző nélkül a fordító nem tudhatja, hogy az állítás teljes.

Ha compiler error-okat látsz, akkor a programodnak nem sikerült lefordulnia, és a fordító nem hozta létre a .class fájlt. Nézd át a kódot, javítsd ki a hibákat és próbáld újra.

Szemantikai Hibák

Azon felül, hogy ellenőrzi, hogy a programod szintaktikailag helyes, más alapvető hibák is jelentkezhetnek. Például a fordító minden alkalommal figyelmeztet, mikor olyan változó használsz ami nincs inicializálva:

testing.java:13: Variable count may not have been initialized. count++ ^testing.java:14: Variable count may not have been initialized. System.out.println("Input has " + count + " chars."); ^2 errors

Még egyszer, a program nem fordult le, nem jött létre a .class fájl. Javítsd ki a hibákat és próbáld újra.

Futási idejű hibák

Hibaüzenetek Microsoft Windows rendszeren

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp

A java nem találja a HelloWorldApp.class bájtkódot.

Az egyik hely, ahol a java keresi a .class fájlt, az a jelenlegi könyvtár. Tehát ha a .class a C:\java könyvtárban található, válts át a következő paranccsal: cd c:\java

87 / 89

Page 88: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

Ha most kiadod a dir parancsot, láthatod a .java és .class fájlokat. Most írd be újra a java HelloWorldApp parancsot.

Ha még mindig hibába ütközöl, lehet, hogy meg kell változtatnod a CLASSPATH változót. Hogy lásd, hogy ez valóban szükséges, üsd ki a CLASSPATH változót ezzel a paranccsal:

set CLASSPATH=

Most írd be újra a java HelloWorldApp parancsot. Ha a program most működik, meg kell változtatnod a CLASSPATH változót. Hogy átállítsd ezt a változót, olvasd el a JDK telepítési útmutatót.

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp/class

Általános hiba a kezdő programozók részéről, mikor a java futtató alkalmazást a fordító által létrehozott .class fájlon próbálják alkalmazni. Ezt a hibát akkor kapod, ha példálul java HelloWorldApp.class parancsot adsz ki be java HelloWorldApp helyett. Ne feledd, az argumentum az osztály neve, amit használni akarsz, és nem a fájl neve.

Exception in thread "main" java.lang.NoSuchMethodError: main

A Java VM-nek szüksége egy main metódusra, ahol elkezdheti az alkalmazásod végrehajtását. Biztos megfelel a szignatúra, nem írtad el a függvénydefiníciót?

Hibaüzenetek UNIX rendszeren

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp

A java nem találja a HelloWorldApp.class bájtkódot.

Az egyik hely, ahol a java keresi a .class fájlt, az a jelenlegi könyvtár. Tehát ha a .class a /home/jdoe/java könyvtárban található, válts át a következő paranccsal:

cd /home/jdoe/java

Ha most kiadod a pwd parancsot, láthatod a .java és .class fájlokat. Most írd be újra java HelloWorldApp parancsot.

Ha még mindig hibába ütközöl, lehet, hogy meg kell változtatnod a CLASSPATH változót. Hogy lásd, hogy ez valóban szükséges, üsd ki a CLASSPATH változót ezzel a paranccsal:

unset CLASSPATH

Most írd be újra a java HelloWorldApp parancsot. Ha a program most működik, meg kell változtatnod a CLASSPATH változót. Hogy átállítsd ezt a változót, olvasd el a JDK telepítési útmutatót.

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp/class

Általános hiba a kezdő programozók részéről, mikor a java futtató alkalmazást a fordító által létrehozott .class fájlon próbálják alkalmazni. Ezt a hibát akkor kapod, ha példálul java

88 / 89

Page 89: 01-bevezetes/01-bevezetes.md at master from … zh-ra... · Web viewElemek pozíció szerinti elérése, iteráció, részlista kezelés. A remove() az elem első előfordulását

HelloWorldApp.class parancsot adsz ki be java HelloWorldApp helyett. Ne feledd, az argumentum az osztály neve, amit használni akarsz, és nem a fájl neve.

Exception in thread "main" java.lang.NoSuchMethodError: main

A Java VM-nek szüksége egy main metódusra, ahol elkezdheti az alkalmazásod végrehajtását. Biztos megfelel a szignatúra, nem írtad el a függvénydefiníciót?

89 / 89