Megvolt az ötödik is. Kocka leírta hogy mi volt, az éppen építgetés alatt lévő Javafórumon pedig született egy-két topik a találkozó után. Egyik a JasperReports-ról, másik a Java 7 vitafórumról. A régi általános paláver topik pedig itt van.
A fórumon leírtakon kívül még szóba került, hogy a Windows (Vista?) eléggé .NET alapú, ami érdekes helyzetbe hozhatja a JVM-eket. Márminthogy .NET-re kell írni a JRE-t. Jobban belegondolva nem hiszem hogy ez akkora gond lesz.
Érdekes dolgok történnek mostanában, annak ellenére hogy a Java halott.
Ha jövőre véletlenül a Javapolis felé vetődnék: Sajnos elfelejtettem, hogy Antwerpenben drága vagy olcsó a tömegközlekedés és a belvárosban vagy a külvárosban érdemesebb szállást foglalni. Arra emlékszem, hogy nem szép hely, viszont jövőre is ugyanott lesz a JP.
A következő JUM március 19.-én lesz és elvileg GWT-re, SOA-ra már lehet számítani. Sörözés közben még súgtak izgalmas ötleteket a következő vagy az azutáni JUM-ra, de nem tudom mennyire publikus úgyhogy nem írom le.
2008-01-17
JUM V.
2008-01-13
Swing GUI trükkök
Éppen Swing-gel tolom. Íme néhány szépség, csak hogy látható legyen, hogy nemcsak a webes GUI készítésnek vannak meg a szépségei.
-A JFileChooser nagyon lassú Java 1.6_02-vel és 1.6_03-mal Windows-on, ha a megnyitott könyvtárban nagy zip fájlok vannak. Van róla bug report is. Több percig is eltarthat, mire megjelenik a dialógus ablak. Addig a hívás blokkolva van. 1.6_01-gyel nem lassú és ahogy nézem az 1.6_04 release notes-jában szerepel hogy javították.
-Swing komponens konstruktorába továbbra sem érdemes bepakolni a setVisible(true) hívást. Főleg modális dialógus konstruktorába, mert akkor a konstruktor hívása után már nem lehet semmit hozzádrótozni, mivel a setVisible(true); utáni kódrész csak a dialógus lezárása után hívódik meg. Modális dialógust átírni nem modálisra (és visszafelé) eléggé termékeny a hibalehetőségek szempontjából. Különben sem jó ötlet túl sok mindent bepakolni a konstruktorba, ez általános szabály két dolog miatt: 1. Biztos nem lenne hasznos valahol máshol a konstruktorba került inline funkcionalitás egy külön függvényként? 2. Öröklésnél a szuperosztály konstruktorának hívásánál még nincsenek beállítva a leszármazott osztályok mezői. Emiatt konstruktorban nem szerencsés a leszármazott osztályban (felül)definiált metódust hívni, főleg ha az a leszármazott osztály mezőit is használja.
-A JScrollPane-be ágyazott JPanel-eknek van egy rettentően kényelmetlen tulajdonságuk, mégpedig hogy amikor az egérrel görgetjük a külső scrollpane-t és ráfut az egér egy belső panelre, a görgetés hirtelen abbamarad. Erre lehet leleményes workaround-okat csinálni, kérdés hogy melyik Look and Feel-en hogyan működik.
-Look and Feel-eket cserélgetni programfutás közben -bár csábító a lehetőség- nem igazán ajánlatos. Nem mindig sikerül minden úgy ahogy kéne. Nálam néha beragadtak komponensek, azaz a GUI nagy része lecserélődött, de egy-két gomb megmaradt a jól megszokott metál stílusban. Különben -ahogy a JavaPosse-ben megmondták, a Swing Look and Feel-ek kicserélhetősége csak egy elméleti dolog, mert nem skin-ekről, hanem komponensekről van szó. Ha egyik készletben egy komponens így működik másikban meg úgy, az zavart okozhat. Említettek valami okosságot a témában, majd utánanézek. Egyelőre nem találtam meg, csak egy oldalt, ahonnan sokféle L&F letölthető. (JavaPosse 103)
-A JLabel és JButton kényelmetlen tulajdonsága, hogy többsoros szöveget csak HTML tag-ek segítségével tud megjeleníteni. Ez nem is lenne baj, viszont ilyen többsoros szövegnél már nem működik a setEnabled(false). Ajánlanak különféle megoldásokat, de egyik sem nagyon elegáns. Az alapprobléma az, hogy nem mindig elég egyszerűen kiszürkíteni a feliratot, mert némelyik look and feel-ben a bevésett halvány szöveg jelenti a letiltott label-t. Próbáltam azt is, hogy egy JEditorPane-t konfiguráltam úgy, hogy labelnek nézzen ki, de az meg a fókuszt kavarta el az oldalon és ezt nem is tudtam kiküszöbölni a setFocusable-vel és társaival. Végül úgy csináltam meg, hogy HTML-es labelt használtam, aminek setEnabled(false)-nál mondtam egy szürke színt és kész.
-A Swing komponensekhez a setClientProperty()-vel objektumokat lehet rendelni, amit aztán a getClientProperty()-vel vissza lehet olvasni.
-A Swing eseménykezelését továbbra is érdemes tanulmányozni. Legrosszabb megoldás ha egyáltalán nem foglalkozunk vele (eseménykezelőben, pl. actionPerformed semmi új szál, hanem csak az akciókód - ilyenkor hosszabb műveleteknél a GUI úgy néz ki mintha lefagyna), közepesen rossz megoldás ha mindig külön szálat indítunk az eseménykezelőkben. Jó megoldás az invokeAndWait és az invokeLater használata.
-A fest-tel nagyon jól lehet Swing-es GUI-kat tesztelni. Töltögeti a szövegmezőket, nyomogatja a gombokat szorgalmasan ahogy beprogramoztuk, csak legyen beállítva a Swing komponensek neve és legyen úgy görgetve a scrollbar, hogy látszódjon az ablakban amire klikkelni kell. Egyszerre egy klienst lehet tesztelni és jól lefogja az egész desktopot, úgyhogy ilyen jellegű tesztelésnél érdemes újságot, könyvet vagy másik számítógépet kéznél tartani, vagy elmenni kávézni.
-Ezt is beraktam a csőbe, majd valamikor elolvasom: WebCream 6.0 Swing alkalmazásokból AJAX-os webalkalmazásokat csináló medzsik (lásd még: Javaposse 137).
Amíg az embernek nincsenek túl nagy extra igényei egész jól el lehet lenni Swingben. Azonkívül ez még mindig igazán szórakoztató ahhoz képest, mint amikor JSF-ben (GWT-ben, Tapestry-ben vagy akármilyen webes GUI keretrendszerben) kell percenként aknákat kerülgetni.
2007-12-21
C# delegate-ek
Év vége előtti vincseszter-gyomtalanításnál találtam egy fájlot, amibe a C# delegate-jairól véstem fel pár gondolatot valamikor. Egyébként kicsit bánom hogy nem mentem a Javapolisra. Legközelebb -főleg ha ilyen lehetőség lesz- az asztalra csapok, félreteszem az aktuális (sz*rból kihúzandó) projektet és megcsinálom amit akarok.
A delegate a C-ben és C++-ban megszokott függvénypointerekre hasonlít legjobban.
Magának a szónak a jelentése: kiküldött követ, meghatalmazott, képviselő.
A delegate egy olyan adatstruktúra ami egy vagy több metódusra mutat, példánymetódusok esetében egyben az azokhoz tartozó objektumokra is. Mondhatnánk azt is, hogy a delegate, mint deklaráció egy metódus szignatúráját írja le. Azokkal a metódusokkal kompatibilis, amelyeknek a paraméterlistája és a visszatérési értéke megegyezik a delegate paraméterlistájával és visszatérési értékével.
Delegate-t így kell deklarálni:
delegate int op(int a, int b);
Ha osztályon kívül deklaráljuk akkor a namespace-n belül lehet elérni, de ha osztályon belül deklaráljuk (static kulcszó nem megengedett), akkor az osztály nevén keresztül kell hivatkozni rá. Ilyenkor tehát a delegate nem a példányhoz hanem az osztályhoz tartozik.
A delegate a System.Delegate osztályból származik, viszont ezt az öröklődést csak a rendszer és a compiler-ek használják, mert maga az osztály sealed, tehát a programozáskor mi csak a delegate kulcsszóval találkozunk.
Delegate példányosítása a következőképpen történik:
op x = new op(add);
Ahol az add metódusnak kompatibilisnak kell lennie a delegate-tel, különben fordítási hiba jelentkezik.
Egy delegate-hez újabb metódusokat is hozzá lehet adni:
x += new op(sub);
x = new op(add) + new op(sub);
stb. Ha új értéket rendelünk a delegate-hez, a régi elveszik, mint a referenciáknál megszokott.
A delegate meghívása egyszerűen így történik:
x(1, 2);
Ilyenkor az összes metódus végrehajtódik szépen sorban szinkronban ugyanazokkal a paraméterekkel. Ha egyik metódus változtat valamit, azt a változást a sorban utána következo metódusok mind látni fogják. A legutolsó visszatérési érték fogja képezni a delegate visszatérési értékét. Ha exception következik be a hívások során és az nincs elkapva a híváslistában meghívott metódusban, akkor ez az exception a delegate-et hívó kódban fog jelentkezni, mintha a delegate hívása során keletkezett volna. Az exception keletkezése után a híváslistában szereplő többi metódus nem kerül meghívásra.
A delegate-bol el is lehet venni metódusokat a - és a -= operátorral. Ha olyan metódust próbálunk elvenni belőle ami előzőleg nem volt benne, nem történik változás.
Delegate-ek összehasonlítása
A delegate-ekre alkalmazható az egyenlőséget ill. az egyenlőtlenséget vizsgáló összehasonlító operátor (==,!=). Két delegate példány egyenlőnek tekinthető, ha mindkettő értéke null, vagy egyenlő híváslistával bírnak, tehát a híváslistákban szereplő metódusok ugyanazokra a statikus metódusokra és ugyanazon objektumpéldányok ugyanazon metódusaira mutatnak ugyanabban a sorrendben a két delegate esetében. A delegate-ek típusa nem számít, tehát két különböző típusú delegate (amik persze ugyanazt a szignatúrát képviselik) lehet egyenlő.
Event-ek
A delegate int op(int a, int b) tehát egy delegate-nek a deklarációja és már látható volt, hogyan lehet lokális változóként létrehozni. (Miért van külön event, ezt nem értem...)
public event Click EventHandler;
Így néz ki tehát egy event deklarációja. Az event kulcsszó, aztán az esemény neve (érdemes valami igeként elnevezni) aztán a típusa. Így egy delegate típus könnyen hozzárendelhető többféle eseményhez.
A delegate-ek és event-ek kiválóan használhatóak eseménykezelésre, ahogy ez meg is van valósítva a System.EventHandler esetében. Egy gombhoz például a következőképpen rendelhetünk egy eseménykezelőt:
button.Click += new EventHandler(this.buttonClick);
Ahol a Click egy event amihez EventHandler típusú metódusokat lehet kapcsolni. Az osztályon belül így történik az eseménykezelő hívása:
Click(this, null);
A megfelelő paraméterekkel természetesen.
Java vs. .net
A java 1.4-gyel szemben gyakorlatilag beépítették a nyelvbe az eseménykezelést. A jávás megoldásnak több hátránya is van a C#-hoz képest:
- Meg kell írni vagy örökölni kell valahonnan a listenereket kezelő metódusokat. (add, remove, notify) Az örökléssel az a probléma hogy kizárja a máshonnan való öröklést, a logika megírása pedig a plusz hibalehetőségekkel járó ujjgyakorlat. Elvileg lehet írni egyedi implementációkat (pl. Chain of Responsibility), de az alkalmazott listener minta nem egy olyan dolog amit túlzottan meg lehetne fűszerezni.
- C#-ban meg lehet csinálni, hogy az eseménykezelő metódusok nem ugyanabban az osztályban foglalnak helyet. A java-ban a Listener interfészek csokorba gyűjtik a metódusokat, amiket egy adott osztálynak implementálnia kell. (Billentyűeseményeknél lehet hogy csak a leütésre akarok figyelni, de az alkalmazandó interfész miatt a felengedésre is meg kell csinálnom az üres metódust.) Erre be is vezették az Adapter-osztályokat, amikben eleve benne van az összes metódus üres törzzsel, de ezek szintén öröklődést igényelnek.
- Kissé antipattern az a megoldás, hogy egy meglévő -valamilyen célra már felhasznált osztályt- hirtelen kiegészítünk valami Listener logikával, mert éppen kell. Pl.
public class MyForm extends JPanel implements ActionListener. Így az osztályban definiáltpublic void actionPerformed(ActionEvent)metódust boldog boldogtalan hívogathatja. C#-ban egyszerűen lehet csinálni olyan eseménykezelő metódusokat amelyek az adott osztályon kívülről nem hozzáférhetőek. Ehhez jávában befoglalt osztályok kellenek, amik persze hosszabb távon egész jól megszokhatóak. - Már meglévő osztályok metódusait is fel lehet használni, anélkül hogy bele kellene nyúlnunk a kódjukba és implementálnunk kellene mégegy interfészt. Ezt java-ban wrapper osztállyal lehet megvalósítani, ami delegálja a metódushívást.
A fentiek ellenére nem hiányolom a delegate-eket a java-ból, főleg a hozzáadásos, összehasonlításos dolgait. Gyakorlatilag kis kerülőúttal mindent meg lehet oldani delegate-ek nélkül, ezenkívül több kérdést felvet, mint amennyit megold.
Mire jó még?
Kb. ugyanarra mint a C-s, függvénypointerek, tehát callback függvények megjelölésére, függvénytáblák létrehozására, stb. Egy példa függvénytábla létrehozására és használatára:
public op[] operations = new operations[10];
...
op[0] = new op(add);
...
operations[0](2, 3);2007-12-06
Bp nt mUp, December
Csak röviden tegnap estéről:
Simon - Humanoid Robot, Pécskai Balázs (logintsys)
A srác egy humanoid roboton dolgozgat pár éve. Először ablaktörlő motorokkal építette, majd szervómotorokkal, amik még mindig nem elég erősek (pl. nem triviális hogy a robot fel tud-e állni). Delphi-ben programozza és egy külső PC-ről irányítja. Egyelőre csak vezérlése van, nem beszélünk szabályozásról. (Nincs visszacsatolás.) A statikus járás az amikor előre minden ki van számolva, a dinamikus pedig amikor mozgás közben derülnek ki dolgok. Vagy talán a statikus járás az, amikor a mozgás minden pillanatában a robot statikus egyensúlyi helyzetben van? Ott ült a robot statikusan mikulás sapkában. Elvileg az előadások után mozgott is, de addigra már eljöttem.
Google Android, Kis Gergely (EU Edge)
Főleg a Linux szemszögéből foglalkoztak a témával. Annyival lettem okosabb, hogy az SDK-ban található emulátor hardvert emulál (biztos azért ilyen lassú) és emiatt viszonylag jó közelítést ad a valós hardverekhez. Láthattunk képen egy eszközt, amin valóban fut az Android.
Keressük a peer-t a szénakazalban, Tóth Benedek
A P2P hálózatok lelkivilágát érintette az előadó, de ennyibe nagyon kevés fér bele. Főleg a fájlcserélőkről volt szó. Vannak "node"-ok vagy pedig a szomszédaikat ismerik a kliensek.
Milenia Grafter - a 64 kilobyteos flash media server, Tóth Milán (milgra.com)
Flash animációk kiszolgálására alkalmas szerver jávában, 64k-ban. Megkérdeztem volna, hogy obfuszkálva-e ennyi és NIO-t használ-e, de végülis nem kérdeztem. A tippem: nem, igen. Közben elgondolkodtam hogy mennyivel fizetnék többet, hogy ha egy szerver alkalmazás 6.4mega helyett 64k lenne. Valószínűleg semennyivel. Továbbá nagy különbség, hogy valamit nem kell, vagy nem lehet konfigurálni. Megcsodálhattuk a MacBook grafikai lehetőségeit.
Bölcsészettudomány Informatikai Önálló Program, Vaskó Péter
Kicsit messziről indulva a szemantikus webnél kötöttünk ki. Dolgoznak egy megvalósításon, amivel január környékén fognak jelentkezni élőben, erről láthattunk egy 1 percet demót. Jó kis sodró előadás volt. (iGlue a projekt neve ha jól értelmeztem.)
A hacker kép alakulása Nick Haflingertől Neo-ig, Szedlák Ádám
Mielőtt napi 8-12 órát ültem gép előtt, már akkor is próbáltam úgy válogatni az elolvasandó könyveimet, hogy minél kevesebb szó legyen benne számítógépről, kibertérről, ezért igencsak műveletlen vagyok a műfajban. A srác szakdolgozatának ez a témája, úgyhogy ha egyszer publikus lesz, biztos sokan elolvassák majd.
A buzzword bingót nem követtem, de szépen csendben elvitték az 5 pólót.
Ikszelgetés helyett inkább forraltboroztam.
2007-12-02
JUnit 4
Haladni kell a korral (illetve nem szabad lemaradni), úgyhogy átnézegettem a JUnit 4 dolgait. Íme két hasznos olvasmány a témában -egyik az IBM-nél, másik DevX-en. A JUnit 4.X alapvetően a JUnit 3.X továbbgondolása olyan formában, ami a JDK5-ös új feature-jeit jól kihasználja. Jelenleg a 4.4-es verziónál tart, a www.junit.org -ról pedig letölthető (158kbyte a jar forrás nélkül). Mi változott?
- Legalább 5-ös Java kell hozzá (bármilyen meglepő).
- A package megváltozott
junit.framework-rőlorg.junit-ra. @Testannotációk használata névkonvenciók helyett. Továbbra is publicnak ill.void-nak kell lennie a visszatérési értékének és nem lehetnek paraméterei. Ha ezt nem tartjuk be, az alábbi kivételekre számíthatunk:java.lang.Exception: Method xxx should have no parameters
java.lang.Exception: Method xxx should be void- Statikus import használata:
import static org.junit.Assert.assertEquals;Így a kódbanAssert.assertEquals(...);helyett írhatunkassertEquals(...);-t. (Persze JUnit 3.8-nál is használhatjuk a statikus import funkciót, ha 5-ös Javank van.) - Nem kell kiterjeszteni a
TestCaseosztályt, így lehetőve válik a protected metódusok tesztelése azáltal, hogy a teszt-osztállyal a tesztelendő osztályt terjesztjük ki. setUp()metódus helyett a@Beforeannotációt használjuk, akár többet is. Kérdés hogy ezek milyen sorrendben hajtódnak végre - erre a sorrendre nincs explicit szabály, ezért véletlenszerűnek vehető.- A
tearDown()párja pedig az@After, amiből szintén lehet több. - Ősosztályokban nem kell explicite meghívni a
setUp()==@BeforeilletvetearDown()==@Aftermetódusokat, mert azok hívása automatikusan történik: Először az ősosztályban lévő@Before-k hívódnak, aztán a leszármazott osztályokon belüliek.@After-nél pont fordítva, először a leszármazottaké, majd az ősosztályban lévők. - A
@Beforeés@Afterminden teszteset előtt és után hívódik, akárcsak asetUp()éstearDown(). Lehetőség van@BeforeClassés@AfterClassmetódusok megadására, amelyek az osztályban lévő összes teszteset előtt illetve után hívódnak meg. Ilyen feature JUnit 3.X-ben nincs. - Ha egy osztályban nincs egyetlen
@Testannotáció sem, hibát fogunk kapni. - JUnit 3.X-ben a kivételek ellenőrzése úgy történt, hogy a
catchblokkba beírtunk egyassert-et. Itt az annotációba írhatjuk be, hogy milyen kivételt várunk:@Test(expected=ArithmeticException.class). Ha nem dobódik kivétel, vagy más kivétel dobódik, a teszt elbukik. Ha további ellenőrzésekre van szükség a kivétel paramétereivel és szövegével kapcsolatban, továbbra is atry-catchmódszert kell használni. - Ha valami tesztet mégsem akarunk futtatni,
@Ignoreannotációval kiüthetjük. (A@Testannotáció megmaradhat, elé és mögé is beírhatjuk az@Ignore-et.) Megadható neki egy String típusú paraméter, hogy miért hagyjuk ki. A teszt nem fog lefutni, viszont jelezve lesz hogy ki lett hagyva. Az egész osztályra is modhatunk@Ignore-t, de vigyázat, az nem ugyanaz mintha a metódusokra mondanánk, mert az utóbbi esetben még a@AfterClassés@BeforeClasslefut. - Általam nagyra értékelt feature, hogy a teszteseteknek timeout adható így:
@Test(timeout=500)Milliszekundummal. - Van új assert, ami objektum tömböket hasonlít össze, viszont sok (12) assert metódus eltűnt az autoboxing feature miatt. Mindegyik az
assertXXX(Object, Object)-et használja. Illetve a DevX szerint így történt, de én furcsa módon elérem ezeket a mindenféle paraméterű assert metódusokat továbbra is aTestCaseosztályban. - Lehet használni az 1.4-ben bevezetett
assertkulcsszót is, de akkor a tesztek futtatásánál meg kell adni az-eakapcsolót a JVM-nek, különben azassert-ek nem kerülnek kiértékelésre. Ekkor viszont a JUnit-osassertExceptionhelyett a nyelvijava.lang.AssertionError-t fogjuk megkapni adott esetben. - JUnit4-ben nincs
suite()
metódus. Ehelyett lehet csinálni egy üres osztályt, aminek annotációban adjuk meg, hogy milyen más osztályokat futtasson:@RunWith(Suite.class)
@Suite.SuiteClasses({My1Test.class, My2Test.class, My2Test.class})public class AllTests {
} @RunWithosztály annotáció megadásával saját futtatót is megadhatunk a tesztesetek futtatásához. Pl. aorg.junit.runners.Parameterized-et, ami általunk megadott paraméterekkel küldi meg a tesztet. Egy@Parametersannotációval felturbózott publikus statikus metódusra van még szükség, ami egyCollection-t ad vissza és egy publikus konstruktorra, ami a Collection-ben lévő elemeket tudja fogadni. Pl. ha a Collection integer párokat tartalmaz, akkor a konstruktornak is két integer-t kell fogadnia. A futtató végigyalogol a Collection-ön, minden egyes esetben meghívja a konstruktort, majd végig a@Test-tel ellátott metódusokat. A DevX-es cikk harmadik oldalán van erről egy példa. (Listing 2.)- Ha ezt adjuk meg:
@RunWith(TestClassRunner.class)ez nem okoz semmi különbséget ahhoz képest hogy nem adunk meg semmit, mivel aTestClassRunnera default runner. - JUnit4 nem különbözteti meg az előre várt hibákat a rosszul megírt tesztesetekből származő nem várt hibáktól -ez visszalépés! Ergó egy tesztesetnek a JUnit3.8 (passed/error/failure) eseteihez képest csak (passed/failure/(ignored)) esetei vannak.
java –ea org.junit.runner.JUnitCoreparanccsal lehet futtatni a teszteket. Tud futtatni 3.8-as teszteket is a DevX cikk szerint, de a gyakorlatban 3.8-as tesztekben kell egy kis módosítás:public static junit.framework.Test suite() {
return new JUnit4TestAdapter(MyTestClass.class);
4.0-ás tesztek természetesen nem mennek 3.8-on. Ha régi és új JUnit is van a classpath-on, akkor pedig lehet hogy összebalhéznak. Nekem legalábbis securityException-nel leállt.- Hallottam már egy úgynevezett
assertThatmetódusról, elvileg van ilyen 4.4 óta, de még a junit.org-on aktuálisan fenn lévő javadoc-ban nem láttam. - Eclipse 3.3-ban van JUnit4.4 és JUnit3.8 támogatás.
- Olyan szinten el*ja ez a szerkesztő a betűtípusokat és a formázást, hogy öröm nézni. Szörnyű. Update 2007.12.04: Megjavítottam direkt html szerkesztéssel.
