A Sun Certified Web Component Developer vizsga hasonló volt, mint az SCJP. Lentebb a múltkorihoz hasonló jegyzet néhány dologról, ami eszembe jutott tanulás közben, kérdezték valamelyik tesztkérdésben, érdemes megjegyezni, vagy épp elrontottam a valamelyik feladatban. Az angol szövegek többnyire javadoc-ból származnak, a gyakorlatiasabb dolgok pedig Tomcat 6 alatt kipróbált tesztek eredményeként.
A lista pontjait az általam használt Charles Lyons-féle SCWCD Study Companion (2nd Edition) c. könyv fejezetei alapján csoportosítottam. A web.xml-es és TLD-s részeknél néhol az XML elemek neveivel egybeírtam az előfordulásaiknak lehetséges számát is (?; 1; +; *).
Az előbbi könyvön kívül érdemes belenézni a Head First Servlets and JSP-be is, mert volt pár apróság, amiről az egyik könyv biztosan állította, hogy nem lesz vizsgán, miközben azt a másik úgy tárgyalta, mint rendes vizsgaanyag - és fordítva is. A Head First utolsó száz oldala ráadásul egy teljes tesztvizsga. Ehhez viszont ajánlott a webes hibajegyzéket is átvezetni a könyvbe, mert sajnos elég sok elírás van benne.
Egy érdekes probléma: hogyan döntsük el egy fájlról, hogy milyen karakterkódolással készült? Igazából algoritmus kellene rá, a Total Commander F3-as nézőkéje nem mindig jó megoldás. Főleg a bemenet gépi ellenőrzésekor nem.
Kis keresgélés után a Mozilla-féle karakterkódolás-detektáló algoritmus java verziójára akadtam. Kipróbáltam, de nem jött be. A latin2 és ASCII kódolást felismerte, az UTF-8-at és a latin1-et nem. Pedig az UTF-8 lenne a legérdekesebb. Igazából egy boolean isUtf8(byte[]) metódus is elegendő lehet a legtöbb feladatra.
Aztán találtam belőle egy fejlettebb változatot, ami már az UTF-8-cal is megbirkózik.
Egy másik jó választás a GuessEncoding. Ez ugyan csak az UTF-8 kódolást ismeri (meg néhány másikat a BOM-ból képes kitalálni), de cserébe viszonylag egyszerű, könnyen módosítható.
Kipróbáltam a Java API idevágó osztályait is, hátha jelzik a hibát, ha UTF-8 helyett valami mást találnak. Fájlok beolvasásával kapcsolatban három módszert nézegettem. Az első a FileReader volt, de a dokumentációja szerint az alapértelmezett karakterkódolással dolgozik, ha nem erre van szükségünk, akkor az InputStreamReader és a FileInputStream kombinációját kell alkalmaznunk. A harmadik jelölt pedig a Scanner osztály volt.
Mivel a FileReader-nek nincs olyan konstruktora, amelynek meg lehetne adni a karakterkódolást, így ezzel nem is foglalkoztam tovább. A rendszer alapértelmezett karakterkódolása biztos, hogy rendszerről-rendszerre változhat, úgyhogy erre nem érdemes építeni. Az InputStreamReader és Scanner osztályok rendelkeznek olyan konstruktorral, ami karakterkészletet vár. Ezeknek mindig UTF-8-at adtam meg.
A Scanner nem jelzi, ha hibát talál az UTF-8 fájlban. Egyszerűen csak onnantól kezdve nem ad vissza semmit. Az InputStreamReader visszaad valamit, de nem az igazi. A Scanner reakciója szimpatikusabb, legalább utalni fog valami a hibára, ami lehet, hogy egyébként észrevehetetlen lenne. Például ha egy nagyobb adatfájl belsejében fordul elő egy hibás kódolású karakter.
Az eddigiek miatt tanácsos lehet a tényleges adatfeldolgozás megkezdése előtt az egész fájl UTF-8 megfelelőségét ellenőrizni. Erre a GuessEncoding váza tökéletes, csupán néhány módosítás szükséges hozzá:
A magyar ékezetes karakterekhez egyébként egy reguláris kifejezés is elegendő lehet. (Csak ne Scannerrel olvassuk be a fájlt, mert akkor csak az első hibás karakter előtti tartalmat kapjuk meg, amire valószínűleg illeszkedni fog a kifejezés.)
Néhány dolog ami eszembe jutott a Sun Certified Java Programmer (SCJP) vizsgára való tanulás közben, kérdezték valamelyik tesztkérdésben, érdemes megjegyezni, vagy épp elrontottam a valamelyik feladatban.
Ma túlestem a régóta halogatott SCJP vizsgán. Számalk, Etele út. Korrektek voltak. A cég megszokásból 310-055-re vett vouchert, amit szerencsére módosítottak 310-065-re, ami már Java 6 SCJP, nem Java 5. Könyvem is már a Java 6-hoz van. Kimaradt a System.gc(), volt helyette NavigableSet és NavigableMap. Legalábbis ez a két változás tűnt fel.
A vizsga egész könnyűnek tűnt a könyvben, CD mellékleten, vagy a netről pluszban letölthető feladatsorokhoz képest. A hibákat nem mutatják meg sajna, bár talán jobb is, mert biztos csak felhúztam volna magam rajta.
A netről letölthető feladatsoron már sikerült kiakadnom a hétvégén. Nem igazán élvezem a többoldalas kódban a fordítási hibák keresgélését. Keresse meg a javac, azért van. A „fejből javadoc-ot” feladatokat sem szeretem, de élesben kevés ilyen volt, azok is egyszerűek.
A netes tesztnél az tette be a kaput, amikor a végén közölte, hogy „failed”. A CD-sek előtte simán megvoltak. Aztán jobban megnéztem, itt 80 százalék a minimum, nem 65. Para ezerrel: akkor most mennyi is kell? A netes frissebb lenne? A 80 azért kicsit izgulós. Könyv elő, abban 65 százalékot írnak, meg azt, hogy ez változhat, pontos infó a suned.sun.com-on. Ott 65-öt írnak. Huhh...
A 65 százalék pedig ennél a próbatesztnél is simán megvolt, ráadásul pár hosszabb forráskódot egyszerűen kihagytam, mert nem volt már kedvem végigolvasni sem őket. (Aztán persze fordítási hibás volt egyik-másik...)
A legjobban az a megoldókulcsbeli hiba tetszett (volt pár...), amikor a „Compilation fails due to a single error in the code” és ugyanez „multiple errors”-szal is igaz volt egyszerre. Legalábbis szerintük.
A vizsgán emberi méretű forráskódok voltak, nem egy 800x600 pixeles ablakban kellett görgetni (egérgörgő nélkül) a forrást, mint a CD-ről felrakható MasterExam-ban. Teljes képernyő, rendes betűtípus a forráskódok alatt, stb. Volt drag&drop is. A feladatok negyede talán nem (mint ahogy a könyv írja), de mondjuk 10-12 kérdés volt ilyen a 72-ből. Egyszer próbáltam újra megnézni egy ilyen kérdést, de szólt a progi, hogy ha megteszem, akkor elvesznek a korábbi válaszok (ha jól értelmeztem), úgyhogy inkább hagytam az eredeti verziót.
Eredményt csak a nyomtató mutat a végén, a képernyőre már nem írják ki. Gondolom így izgalmasabb.
Kapunk fordítási hibát a kommentelt soroknál a Java fordítótól?
class A { private int a; class InnerA { private int b; void m2() { a = 9; // #1 } } void m1() { InnerA innerA = new InnerA(); innerA.b = 8; // #2 } }
Válasz hajtás után.
Nemrég összefutottam a következőhöz erősen hasonlító kódrészlettel:
} catch (final Exception e) { if (e != null) e.printStackTrace(); }
Tipikus „mitírki”-t lehet belőle készíteni, mondjuk egy ilyet:
try { throw null; } catch (final Exception e) { if (e == null) { System.out.println("null"); } else { System.out.println("nemnull"); } System.out.println("e: " + e); }
Eredmény hajtás után.
import javax.jcr.Node; final Node child = ...; if (child != null) { child.remove(); log.debug("Removing child [path = " + child.getPath() + "]"); }
Mi a hiba a fenti kódban? Válasz hajtás után.
A múltkor JAXB-vel kellett átvinnem egy InputStream-et is tartalmazó osztályt. Neten nem találtam rá semmi értelmeset, így lásd lentebb az én megoldásom.
Az InputStream szerializálásához egy adapterosztályt írtam, ami bájttömbbé alakítja az InputStream-et, illetve ugyanezt megteszi a másik irányba is. A bájttömböt pedig már tudja a JAXB is kezelni. Ezután már csak a szerializálandó osztály InputStream mezőjét kell a következőképp annotálni:
@XmlJavaTypeAdapter(InputStreamAdapter.class) private InputStream data;
Az adapterosztály pedig a következő:
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.xml.bind.annotation.adapters.XmlAdapter; /** * JAXB Adapterosztály InputStream-ek szerializálásához. * * @author palacsint */ public class InputStreamAdapter extends XmlAdapter<byte[], InputStream> { @Override public byte[] marshal(final InputStream inputStream) throws Exception { return inputStreamToByteArray(inputStream); } @Override public InputStream unmarshal(byte[] byteArray) throws Exception { return new ByteArrayInputStream(byteArray); } public static byte[] inputStreamToByteArray(final InputStream inputStream) throws IOException { final ByteArrayOutputStream out = new ByteArrayOutputStream(4096); try { final byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) >= 0) { out.write(buffer, 0, len); } } finally { inputStream.close(); out.close(); } return out.toByteArray(); } }
Persze ilyenkor a kiolvasás miatt elvész az adat az InputStream-ből.
Adott a következő Java fájl:
package package2; public class Callee { public InnerClass m1() { return new InnerClass(); } public void m2(final InnerClass innerClass) { } } class InnerClass { public void m3() { } }
Vegyük észre, hogy az InnerClass default elérési módosítóval rendelkezik, így csak a package2 csomagon belül látható.
És egy másik csomagban lévő kódrészlet, ami az előbbieket használja:
final Callee callee = new Callee(); callee.m1(); callee.m1().m3(); callee.m2(null);
A fenti három metódushívásból van-e olyan, amelyik fordítási hibát okozni? Ha igen, akkor mely, illetve melyek azok?
Válasz hajtás után.
Legutóbbi hozzászólások
9 év 16 hét
10 év 5 hét
10 év 9 hét
10 év 27 hét
11 év 29 hét
11 év 34 hét
11 év 35 hét
11 év 36 hét
11 év 46 hét
12 év 16 hét