01-bevezetes/01-bevezetes.md at master from rlegendi/ELTE ...



JAVA gyakorlatTartalomjegyzék TOC \o "1-1" \h \z \u Bevezetés PAGEREF _Toc306572501 \h 2Alapozás PAGEREF _Toc306572502 \h 9Csomagok PAGEREF _Toc306572503 \h 13Függvények PAGEREF _Toc306572504 \h 14Kivételek PAGEREF _Toc306572505 \h 14Objektumorientált alapok PAGEREF _Toc306572506 \h 17Absztrakt Adattípus PAGEREF _Toc306572507 \h 22OO gyakorló feladatok PAGEREF _Toc306572508 \h 27Streamek PAGEREF _Toc306572509 \h 30IO Gyakorlás PAGEREF _Toc306572510 \h 34Gy?jtemény keretrendszer PAGEREF _Toc306572511 \h 36Generic PAGEREF _Toc306572512 \h 40Reflection PAGEREF _Toc306572513 \h 43GUI PAGEREF _Toc306572514 \h 46GUI Kiegészítés PAGEREF _Toc306572515 \h 50Networking PAGEREF _Toc306572516 \h 54Threading PAGEREF _Toc306572517 \h 58Threading - Kiegészítés PAGEREF _Toc306572518 \h 66Kapcsolat az adatbázissal PAGEREF _Toc306572519 \h 70Szerializáció PAGEREF _Toc306572520 \h 74Remote Method Invocation PAGEREF _Toc306572521 \h 77K?rnyezet beállítása PAGEREF _Toc306572522 \h 80Gyakran el?forduló hibák PAGEREF _Toc306572523 \h 84BevezetésA Java nyelvr?l, általánosan.LinkekA tárgy honlapja Kozsik Tamás oldalán: Oracle Java oldala Java Development Kit (JDK) fejleszt?i k?rnyezet (fordító, stb.),Java Runtime Environment (JRE) csak futtatói k?rnyezetJava 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: Java referencia alapvet? fontosságú Java tutorial vagy Java 5.0 ?tikalauz programozóknak (Nyékyné)Java Language Specification Harmadik kiadás, rendes specifikáció, HTML, PDF formátumban. K?z?sségi oldalak, levlisták, fórumok, stb. Java levlista Javagrund (pillanatnyilag offline, amíg az Oracle-lel nem rendez?dnek a dolgok)Javaforum K?rnyezetek ízlés szerint Konzol (ld. a megfelel? mellékletet)Eclipse NetBeans Hello WorldHozzatok 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: Kilépés System.exit( 0 ); Egyéb függvények a System osztály leírásában: Konzol kezelése java.io.Console osztály segítségével: K?rnyezet beállításaWindows 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_21Ha 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.Fordításjavac HelloWorldApp.javaHasználható *.java a default package fordítására.Futtatásjava HelloWorldApp(.class nélkül!)Dokumentáció generálásjavadoc HelloWorldApp.javaRészletesen Ezen tutorial magyar fordítása megtalálható a feladatgy?jtemény mellékleteként.Kódolási konvenciókpackage 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 é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ípusokPrimití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? automatikussz?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ámokA 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!Az == operátorA 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ásIlyet 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 eseteA 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 GetCseles 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.1Ajjjaj! 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); // IgazPuff 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.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 §3.10.2 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átorokSzokásos operátorok (==, !=, &&, ||, %, ++, -- (prefix, postfix), ...), részletes táblázat itt található: 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"Mi az eredménye (v.?. C++)? java int i = 0; System.out.println("" + i++ + ++i); // C++: architektura fuggo Szintén, mi lesz az eredménye? java int i=0; i=i++; i=i++; i=++i; System.out.println(i); Objektumok ?sszehasonlításaAz equals() metódussal: az == operátor referencia szerinti ?sszehasonlítást végez csak, nem tartalom szerintit.Stringek ?sszehasonlításaMint 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ételekbenBaloldalra 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 szerkezetekA nyitó, záró {, } párok kirakása nem k?telez?, ellenben javallott.Elágazásokif ( ... ) { ...} else if (...) { ...} else if ( ... ) { ...} else { ...}Switchbyte, 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;}Ciklusokwhile ( 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ésekbreak, continue, returngoto van, de fenntartott szó, nem m?k?dik...+/- FeladatokFizz-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? élda:12Fizz4Buzz...1314FizzBuzzCollatz-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 1Részletesen: ó feladatokKé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):C = (F-32) * 5 / 9Készítsünk egy minimális konzolos számológépet! Olvassunk be három szám paramétert! Ha az els? szám:1, akkor adjuk ?ssze2, akkor vonjuk ki3, akkor szorozzuk ?ssze4, akkor osszuk el a másik két paramétert egymással!Minden egyéb esetben írjuk ki, hogy nem értelmezett m?velet!A megoldáshoz használjunk switch-case szerkezetet!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.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."AlapozásVáltozókDeklará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?kMinden T típushoz van T[] Referencia: null értéke lehet!Indexelés nullátólTú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étint 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ésekInicializá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ályjava.util.Arrays, hasznos pl. a toString(), binarySearch(), fill(), etc. Részletesen: ításAz == 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 szerintReferenciák? - Azok isT?mb?k, objektumokVararg 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--; }}StringekLé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 énti bejárás: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 )Immutable (megváltoztathatatlan) adatszerkezetString 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 mukodikRészletesen 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?kA 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!Készíts egy függvényt, amely kiszámítja egy t?mb elemeinek az ?sszegét!Készíts egy függvényt, amely kiszámítja egy t?mb elemeinek az átlagát!Készíts egy függvényt, amely normálja egy t?mb ?sszes elemeit (az elemek ?sszege legyen kb. 1)!Készíts egy függvényt, amely n?vekv? sorrendbe rendezi egy t?mb elemeit!Készíts egy függvényt, amely meghatározza egy t?mb minimális és maximális elemét!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!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!Készíts egy függvényt, amely képes meghatározni két paraméterként kapott t?mb skaláris szorzatát!(?) 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!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!).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!).T?bbdimenziós t?mb?kKé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.0Ké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 6Ké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!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!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!StringekIgyekezzetek 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!Készítsetek egy programot, amely egy parancssori argumentumként megadott Stringet átalakít a k?vetkez?képpen:Minden numerikus karaktert változatlanul hagyMinden bet?t kisbet?vé alakítMinden egyéb karaktert lecserél egy _ karakterreKészítsetek egy programot, amely minden ékezetes karaktert lecserél a megfelel?, ékezet nélküli változatára!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!Készítsétek el az el?z? függvény fordított változatát: az els? karaktert cserélje kisbet?re!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!).Emlékeztet?K?rnyezet beállításaEmlé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_12c:\tmp>javac HelloWorldApp.javac:\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 valikimport 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 utasitasokpublic 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/*.javaC:\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).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: Láthatóság: public, protected, private. Ha nem definiált, akkor ún. package-private láthatóság.Lehet abstract: ekkor nincs implementáció (mint a C++ pure virtual függvényei) leszármazottban k?telez?en felüldefiniálandóLehet final: felüldefiniálhatóság letiltásáraLehet static: osztály szint? függvény (Fontos: static kontextusból csak static módosítóval ellátott hivatkozás szerepelhet)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: void: eljárásMinden egyéb: függvényMetódusnév: lowerCamelCase formátumbanParamé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: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)Nem felügyelt kivételek: nem k?telez? sem difiniálni, sem lekezelni ?ket (?sosztály: java.lang.RuntimeException, pl. ArrayIndexOutOfBoundsException, NumberFormatException, DivisionByZeroException)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éldaEgyszer? kivételkezeléspublic 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 á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!+/- FeladatokA feladatokat a gyak2.f1 ill. gyak2.f2 csomagba rakjátok!EuclidKé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 aKészítsd el a függvény rekurzív változatát is!QuadraticKé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!Objektumorientált alapokHatók?r, ?lettartamAlapvet? 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álataTantárgyi ajánlás a java.util.Scanner használata - itt nem, de akit érdekel: . Helyette: java.io.Console#readLine() függvénye és String#split().Osztályok, ObjektumokMiért?Egységbe zárás, adatelrejtés, absztrakt adattípus = adatabsztrakció, adattípus és a rajta értelmezett m?veletek.Példaclass 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ószavakstatic: 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++; }}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: public Minden más osztályból elérhet? (függvény, adattag, vagy osztály)protected Adott csomagon belülr?l, valamint a származtatott osztályokból elérhet?private Kizárólag az adott osztályon belülr?l használható(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álytHa úgy logikusabb, akkor beágyazott statikus osztályHa 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ánybaHa általános osztályt készítünk, akkor saját fordítási egységbeHa bizonytalan vagy, tégy minden minden osztályt kül?n fordítási egységbe!SzármaztatásMiért?Kódmegosztás, kódkomplexitás cs?kkentése, karbantarthatóság, modularizáció, ...Példaabstract class Sikidom { public static final double PI = 3.1415; public abstract double kerulet(); public abstract double terulet();}class Kor extends Sikidom { 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ésFelüldefiniálás Ha a szignatúra megegyezikTúlterhelés Minden más esetbenA 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éseEnkapszulá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.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; }}KonstruktorokObjektum 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, életciklusObjektum létrehozása a new operátorral t?rténik:A a = new A(5); // KonstruktorhívásFelszabadí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) { ... }ObjectMinden 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:Ugyanarra az objektumra hívva konzisztens értéket ad (ha az objektum nem változik, ugyanazt az értéket adja).Ha két objektum az equals() szerint megegyezik, a hashCode() is egyezzen meg.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 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álataKé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!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 é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; 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 á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 {}K?rk?r?s kiterjesztés fordítási hibát eredményez.TagokMint 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 ); }}SummariumIt 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ésAbsztrakt osztály pedig megvalósítást is tartalmazhatInterfészpublic interface GroupedInterface extends Interface1, Interface2, Interface3 { ... }vagy például:class A extends B implements I1, I2 { ... }Részletesen osztályra példapublic 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 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észekKé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: ZEBRASCDFGHIJKLMNOPQTUVWXYTipp/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:transzponálásnyom kiszámítása (átló elemeinek ?sszege, ha négyzetes)mátrixok szorzása mátrixokkal (amennyiben lehetséges)OO gyakorló feladatokZH gyakorló feladatokA 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?zsdeKé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?sorokKé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áta film forgalmazójának azonosítójáta vetítés id?pontjátEzen felül készítsünk reprezentációs osztályokat a filmeknek és a forgalmazóknak! Filmek esetén tároljuk azok:azonosítóját (egyedi, tetsz?leges típus)a címéta rendez?jének nevétaz egységes jegyárata kiadás évétKé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étaz alapításuk évétA 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?rtDobunk 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áriumFarkas, tulajdonságok: Fizikum: 6Asztrál: 9Mentál: 8?leter?: 9Sebzés: 1Csontváz, tulajdonságok: Fizikum: 6Asztrál: 3Mentál: 3?leter?: 10Sebzés: 2Orgyilkos, tulajdonságok: Fizikum: 7Asztrál: 8Mentál: 6?leter?: 7Sebzés: 2Láncf?részes goblin, tulajdonságok: Fizikum: 5Asztrál: 6Mentál: 5?leter?: 7Sebzés: 3StreamekCsatornák, absztrakciós szint bemenet-kimenet kezelésére (hiext, lorem).Részletesen: éldapackage 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ásSzervezé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, FileOutputStreamFeladat 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?veletekMegnyitá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 streamekSorok 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: éldákFájl írásapackage 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ásapackage 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ésekOprendszer 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ájlokA 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átseek(), write(...) - nem tolódik tovább a stream, kézzel kell mindent odébbmásolniraf.seek(file.length()); - file végére ugrás, ahhoz hozzáf?zéswrite() - elfogad byte[] paramétert, de writeBytes() - csak Stringet EOFException - elindexelésnél (IOException leszármazottja)Részletesen: é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.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:10Har Monika:1956:5:6Git Aron:1992:11:23Tek Elek:2002:6:14A 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:Ha a szó vége: "s" helyett "z" "ck" helyett "x" "a" helyett "@" "e" helyett "3" "i" helyett `"1""o" helyett "0" "u" helyett "v" "f" helyett "ph" "s" helyett "$" "g" helyett `"9""y" helyett "j" "t" helyett "+" "!" helyett "1" 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 123456789234567891345678912456789123567891234678912345891234567891234567912345678Ké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:mb <pozíció> <byte>: az adott pozíción lév? byte érték módosításami <pozíció> <int>: az adott pozíción lév? int érték módosításai <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éppIO GyakorlásTreeKé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.xmlPwdKé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/belkarGrepA 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/bashK?nyvtárméretekKé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%CutAz 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?FindKé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!SortKé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!MergeKé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.Gy?jtemény keretrendszerGeneric - BevezetésEgyel?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-unboxingCsak 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 keretrendszerCollections 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 ListDequeSet SortedSetMap SortedMapNem megvalósított m?velet UnsupportedOperationException kivételt dob. Copy konstruktorok vannak (egyik a másikra konvertálható). M?veletek 3 csoportja:Alapvet? m?veletek: size(), isEmpty(), contains(), add(), remove() Elemek együttes kezelése: addAll(), containsAll(), removeAll(), clear(), retainAll() 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); }}HalmazDupliká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.FeladatKé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! -> 5ListaElemek 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).FeladatKé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.txtCthulhuPhngluiRlyehfhtagnmglwnafhwgahnaglLeképezésKulcs-é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.FeladatKé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ésBeé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ítvaImplementá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).FeladatKé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!Kényelmi lehet?ségekjava.util.Arrays#asList(): t?mbb?l listát csináljava.util.Collections nCopies(int n, Object o): két paraméter, amely n-szer tartalmazza o-tEgyelem?, üres, módosíthatatlan, szinkronizált listákAlgoritmusok: 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 olvasgatniSajá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 kezelesRészletesen: é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 WarcraftA # 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ételeEpizódlista mentése (kilépés után ezt t?ltse be)Adott epizód adatainak módosításaEpizódok listázása a képerny?reKilépésGenericEgyszer?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ágNem 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 castolasMagyarul 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)!WildcardokProblé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 hibaNem tudjuk, hogy mi van benne, lekérdezni viszont lehet (mert tudjuk, hogy minden objektum az Object leszármazottja).Bounded wildcardAmikor 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) {...}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ényekOsztá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: 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!TripleKé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())!ReverseKészíts egy generikus reverse() függvényt, amely egy tetsz?leges lista adatszerkezetet képes visszafelé kiírni a képerny?re!FillKé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!MiniMaxKé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>>).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ásaadattagok lekérdezése, módosításafüggvények lekérdezése, meghívásat?mbelemek lekérdezése, módosításaúj osztályok létrehozásaFontos osztályok: java.lang.reflect.* csomag:Field, Method, Constructor adattagok, függvények (invoke(...)), konstruktorok (newInstance(...)) lekérdezéséhezClass osztály-, ill. interfész információk eléréséhezPackage csomagok kezeléséhezProxy új osztályok létrehozásáhozArray t?mb?k dinamikus létrehozása, lekérdezéseModifier módosítók visszafejtésében segít (public, protected, final, etc.)ClassObjektumreferencia 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éldapackage 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 ); }}FeladatokKészíts egy programot, amely egyetlen parancssori argumentumot kap, egy osztály teljes hivatkozási nevét (fully qualified name), éseld?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 é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?kAz 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@42e816Ok: 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?mbFeladatKé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).FeladatKé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ényekFü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) ); }}FeladatKé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!FeladatokOsztályhierarchiaKé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.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): . C:/Program Files/Java/jdk1.6/demo/jfc alatt SwingSet2 és SwingSet3 példa alkalmazások.Példakódpackage 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(); }}?letciklusFelület felépítése. Egyszer? példa alkalmazáspackage 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(); }}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()); } }});Bezárásaframe.addWindowListener( new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); }});Adapterek, ListenerekXXXListener 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 objektumonpublic void actionPerformed(ActionEvent e) { ... }KeyListener: Billenty? leütésepublic 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ésepublic 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ákRészletesen KomponensekKonté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)LabelButtonRadioButtonTextArea, TextField etc.SwingAz 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?lSzabad forma?tlátszó felületekEgyszer?en módosítható megjelenésMenükframe.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);?zenetablakokJOptionPane.showXXXDialog(), pl.:JOptionPane.showMessageDialog(null, // ki az ose, ha van, akkor modalis "alert", // uzenet "alert", // title JOptionPane.ERROR_MESSAGE // tipus);Részletesen ó komponensekframe.add( new JScrollPane(textArea) );Linkeké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ósKé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!GUI KiegészítésListenerek egyéb megvalósításaiSajá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ületContainerekkel (Panel, JPanel).TODO: képJOptionPaneHa super != null, akkor modális, pl.:JFrame frame = ...;...JOptionPane.showMessageDialog( frame, "Modalis uzenet");MVCModel-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);BorderLayoutHaszná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 );CardLayoutPé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);JRadioButtonButtonGroup 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 );JFileChooserHaszná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 ) { ...}FeladatokHex editorKé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!Képerny?terv - Hex editorKvíz alkalmazásKé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(*) 33Kiválasztós, pl.:Mely országok határosak Magyarországgal?[x] Szerbia[x] Szlovénia[ ] JapánMinden 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ésA kérdés sz?vegeA lehetséges 3 válaszA válaszok helyességeA játék képerny?terve az alábbi ábrán található.Képerny?terv - Kvíz alkalmazásA program a k?vetkez? funkciókat biztosítsa:Egyszerre 5 kérdést adjonLehessen 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évelPontozá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 ábbi lehet?ségekJá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).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 .* csomag használható.?sszek?ttetés-alapú kapcsolatKliens-szerver modell, a szerver általában:Lefoglal egy TCP portotVárakozik egy kliens kapcsolódásáraHa kliens jelzi a kapcsolódási szándékát, felveszi vele a kapcsolatot, és kiszolgáljaFolytatja a 2. ponttólA kliens m?k?dése általában:Lefoglal egy TCP portot, ezen keresztül kommunikál a szerverrelKapcsolódik a másik végponton a szerverhez, azon a porton, amelyet az k?zzétettLezajlik a kommunikációA kliens bontja a kapcsolatot a szerverrelMegjegyzéseka kliens lokális portját nem kell ismernünka 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 kapcsolatMajd el?adáson ;]Címek kezeléseHasznunkra válik az InetAddress osztály:getByName(String): név → címgetByAddress(byte[]): IPv4/6 → címgetAllByName(): név → címek (attól függ, hogy van behegesztve a NS)getLocalHost(): → saját címRészletesen éldaSzerveralkalmazáspackage networking;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .ServerSocket;import .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 5000Kliens alkalmazáspackage networking;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .Socket;import .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$ java SimpleClient localhost 5000 mentegetnem$ java SimpleClient localhost 5000 ideseggesedi$ java SimpleClient localhost 5000 exitPalindromok, haha ájaInternet és a WWW-objektumok eléréseSocketek helyett [Http]URLConnection osztály használatával.Hasznos segédeszk?z?kping, netstat, netcat, telnet, tcpdump, etc. FeladatokKonzolos HTTP kliensKé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 scannerKé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: feladatokChat alkalmazásKé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ásaVá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 telnetThreadingMottó: "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 szerkezeteA program t?bb, fizikailag is független eszk?z?n futHaté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 szintjeiUtasításokTaskokFolyamatok (processes)Szálak (threads)Viselkedésük alapján lehetnek:FüggetlenekVerseng?kEgyüttm?k?d?kAlapproblémákKommunikáció: kommunikációs k?zeg: socket, signal handler, fájl, osztott memória, etc.Szinkronizáció: folyamatok ?sszehangolása, szinkron - aszinkronAlapdefiníciókSzinkronizáció Olyan folyamat, amellyel meghatározható a folyamatokban szerepl? utasítások relatív sorrendjeK?lcs?n?s kizárás osztott változók biztonságos használatáhozKritikus szakasz program azon része, ahol egy id?ben csak egyetlen folyamat tartózkodhatAtomi m?velet bármilyen k?zbees? állapota nem látható a t?bbi folyamat számáraMié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ásSzálak létrehozásaKét lehet?ség: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();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(); }}Ugyanez névtelen osztállyal:new Thread( new Runnable() { @Override public void run() { System.out.println("TestRunnable"); }}).start();Szálak függvényeistart(): indításstop(): 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ásasleep( <milis> ): adott id?nyi várakozásyield(): 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 é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ákAzon túl, hogy megbízhatóság \dotsHoltpont k?lcs?n?sen egymásra várakoznak a folyamatok, és egyik sem tud tovább haladniKié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élytelenA 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!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(); }}Szálak állapotaiLásd az alábbi ábrát.?bra - Szálak állapotaiKollekció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); } } 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, ...FeladatokKé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).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!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!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!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)!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.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.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 { ...}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!ParallelPortScannerEgé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?motorKé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.Threading - KiegészítésStringBuilder 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: 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}FAILTegyü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.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 elotti = 0; // Awhile (!found) { // B found = v.get(i) == e; // C i++; // D}FAILTegyü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}FAILTegyü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}FAILTegyü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; // Fa 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; // FNa 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.IrodalomBrian Goetz et al.: Java Concurrency in Practice, Addison-Wesley Professional, May 19, 2006.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 // ...}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!LinkekSocket példa Java Tutorial, All About Socket fejezete 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-hezUtasítások végrehajtásaEredmény lekérdezéseA 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 MyMySQLTestClassNem 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ásaAhol:maga a protokoll a jdbc az alprotokoll megegyezik a forgalmazó nevévelaz 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átItt 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: . 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");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=truePé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" MyDerbyTestClassEzt 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.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ázatUtasí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ásaexecute(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");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é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 szerkezeteA megvalósításhoz használjátok a k?vetkez? címen elérhet? derby.jar fájlt: 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!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.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."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!"); }private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new NotSerializableException("Nem!");}GotchasAz 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 leszVerzió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 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étHaszná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.).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 elveszhetnekA hálózati végpontok leállhatnakAz adatátviteli vonal elromolhatProblé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 .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); }}A kliens implementációjaimport .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ásEl kell indítani egy registry szolgáltatást a szerver gépen:::Windowsstart rmiregistry # Unixrmiregistry &Le kell fordítani a kliens és szerveralkalmazástHozzuk létre a k?vetkez? policy fájlt:grant { permission java.security.AllPermission;};Futtatni kell a szervert, a k?vetkez? paraméterekkel:-Djava.security.policy=server.policy-Djava.rmi.server.codebase=file:/<path_a_classfile_okhoz>Megjegyzés Figyelni, itt nem file:// kell!Futtassuk a klienst!FeladatokKé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 é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, és az outputot küldje vissza a kliensnek (a végrehajtáshoz használd a Runtime.exec(String cmd) függvényt)!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! 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.TartalomSzükséges szoftverek Els? alkalmazás létrehozása Forrás fájl létrehozása Fordítsd le a forrásfájlt .class formátumra A program futtatásaSzükséges szoftverekHogy megírd az els? programod, szükséged lesz az alábbiakra:Java SE Development Kit 6 (JDK 6) Innen let?ltheted a Windowsos verziót (a JDK-t t?ltsd le, ne a JRE-t): . K?vesd a telepítési utasításokat: 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.Forrásfájl létrehozásaItt két lehet?séged van:Elmented a HelloWorldApp.java a gépedre, ezzel sok gépelést megspórolsz: . 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 != helloworldappMentsd el a kódot HelloWorldApp.java néven. Ehhez válaszd a Fájl → Mentés másként menüelemet, majd:A Fájlnév mez?be írd be, hogy "HelloWorldApp.java", az idéz?jeleket is.A Fájl típusának állítsd be az egyszer? sz?veges formátumot: Text Documents (.txt)*.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?ttMents, és lépj ki a Notepad alkalmazásból!A forrásfájl .class fordítása formátumraIndí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? ablakA 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:\javaAz 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.?bra Mappa tartalmának listázásaMost már készen állsz a fordításra. Ehhez a k?vetkez?t kell begépelned: $ javac HelloWorldApp.javaA 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ájltMost 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ásaGépeld be a k?vetkez? parancsot abban a k?nyvtárban, ahol az alkalmazásod található:$ java HelloWorldAppA lenti képen találhatod az eredményt.?bra A program eredményeA 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 fileHa 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 rendszerenjavac: 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 requestedElfelejtetted 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ákAzon 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 errorsMé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ákHibaüzenetek Microsoft Windows rendszerenException in thread "main" java.lang.NoClassDefFoundError: HelloWorldAppA 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 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 rendszerenException 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 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? ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download