Java-API, rajapinnat, r poikkeukset, UML,... Janne Käki 12.10.2006
Keskeisimmät Java-API:n pakkaukset API = Application Programming Interface eli sovellusohjelmointirajapinta (!) pakkaus (engl. package) = tapa koota samaan asiaan liittyviä luokkia yhteen java.lang pari aivan keskeistä luokkaa, kuten Object, String ja Math alkeistyyppien kääreluokat (Integer, Double, Boolean, Character,...) useimmat poikkeus- (Exception) ja virheluokat (Error) aina käytössä, ei tarvitse importoida! java.util kokoelmarajapinnat (Collection, Set, List, Map) ja niiden toteutukset (HashSet, Vector, ArrayList, HashMap,...) kirjastoluokat Arrays ja Collections välineitä päiväysten ja kellonaikojen käsittelyyn: Date, Calendar, TimeZone pari muuta hyödyllistä: Random, Timer, Scanner java.io välineet näppäimistön ja tiedostojen lukemiseen (erilaiset InputStream- ja Reader-luokat) sekä näytölle ja tiedostoon kirjoittamiseen (OutputStream- ja Writerluokat) java.net välineet verkkoyhteyksien muodostamiseen java.awt AWT-luokkakirjasto (Abstract Windowing Toolkit), Javan vanhempi kalusto graafisten käyttöliittymien toteutukseen javax.swing Swing-luokkakirjasto, uudemmat välineet graafisten käyttöliittymien tekemiseen
Luetaan sitä API:a! Mutta miten? Java-ohjelmoinnissa monien ongelmien ratkaisu käy seuraavaan tapaan: 1. Etsi API:sta oikea luokka haluamasi asian tekemiseen. 2. Etsi luokasta metodi, jolla sen saa tekemään tuon asian. 3. Selvitä, miten kyseistä metodia käytetään. API:n lukemisessa on kuitenkin muutama sudenkuoppa, joita kannattaa varoa: Varmista, että olet tekemisissä oikean luokan kanssa (tsekkaa myös, missä pakkauksessa se on). Esimerkiksi java.util.list ja java.awt.list ovat kaksi täysin erilaista luokkaa, jotka menevät helposti sekaisin. Katso, mistä tutkimasi luokka periytyy. Yläluokista voi päätellä paljon siitä, mitä luokka osaa omien metodiensa lisäksi tehdä. Luokan omassa Method Summary -listassa ei mainita yläluokilta perittyjä metodeja, mutta luokalla on luonnollisesti myös ne käytettävissään. (Ne luetellaan lyhyesti tuon listan alapuolella.) Joistakin metodeista on tarjolla useampi kuormitettu (engl. overloaded) versio, eli samanniminen metodi erilaisilla parametrivaihtoehdoilla. Osa näistä on suoraviivaisempia käyttää, toiset tarjoavat mahdollisuuden hyvinkin monimutkaisiin säätöihin. Valitse oikea metodi tarpeesi mukaan, säästyt turhalta säätämiseltä. :)
Rajapinnat Rajapinta on luokka, joka määrittelee olion käyttöliittymän (tai jonkin osa-alueen siitä). Rajapinta toisin sanoen määrittelee yhden tai useamman metodin, jotka tarjoavat tietyn toiminnallisuuden. Ja tarkemmin sanoen se vain määrittelee nämä metodit, ei toteuta niitä (eikä ota kantaa siihen, millaisten teknisten yksityiskohtien avulla niiden toiminnallisuus toteutetaan). Rajapinta on toisin sanoen kuin abstrakti luokka, joka sisältää vain abstrakteja metodeja (siis metodeja ilman toteutusta, eli tavallaan vaatimuksia aliluokille tietynlaisten metodien toteuttamisesta). Mutta siinä missä Java-luokalla voi olla aina vain yksi suoranainen yläluokka (abstrakti tai ei), voi sama luokka toteuttaa yhden, kaksi, kolme tai miljoona rajapintaa. Toteuttaminen tarkoittaa sitä, että luokkaan on laadittu käytännön toteutus kaikille näissä rajapinnoissa määritellyille metodeille ja lisäksi toteuttamisesta on kerrottu avainsanan implements avulla. 1. Rajapintaluokka määrittelee tietyn toiminnallisuuden. 2. Konkreettiset luokat toteuttavat rajapinnan, kukin omalla tavallaan. 3. Toinen luokka voi käyttää kaikkia näitä luokkia rajapinnan edustajina, yhteisten ominaisuuksien pohjalta.
Poikkeukset public Paaryna varastapaaryna() throws KaameaPoikkeus { if (vartija.onvahdissa() &&!vartija.nukkuu()) { KaameaPoikkeus poikkeus = new KaameaPoikkeus("Kiinni jäit, hähä!"); throw poikkeus; else { return paarynapuu.annapaaryna(); Tähän asti olemme tottuneet siihen, että metodin paluuarvo (true tai false, olio tai null) riittää kertomaan, onnistuiko metodi tehtävässään vai ei. Mutta millainen paluuarvo pystyisi ilmaisemaan, että jäimme kiinni varastaessamme päärynää? Javan poikkeukset (engl. exceptions) ovat ikään kuin vaihtoehtoja metodien normaaleille paluuarvoille. Tyypillisesti ne kertovat, että metodissa tapahtui odottamaton virhe. Poikkeusten yhteydessä ei puhuta palauttamisesta, vaan heittämisestä. public void elelevaarallistaelamaa() { try { // VOI HEITTÄÄ POIKKEUKSEN: Paaryna saalis = this.varastapaaryna(); this.syo(saalis); catch (KaameaPoikkeus poikkeus) { System.out.println(poikkeus); this.karsirangaistus(); finally { this.jatkaelamaaentiseentapaan(); Monet Javan valmiit poikkeukset (ja tyypillisesti kaikki itse laaditut) täytyy käsitellä. Toisin sanoen jos on olemassa vaara (todellinen tai edes teoreettinen), että tietyn metodin kutsusta aiheutuu poikkeus, tämän poikkeuksen mahdollisuuteen tulee varautua ns. try-catch-rakenteen avulla. Try-osioon sijoitetaan se metodikutsu, josta potentiaalisesti voi aiheutua poikkeus, sekä kaikki se mitä onnistuneesta yrityksestä suoraan seuraa. Catch-osiossa puolestaan yleensä reagoidaan jollain tapaa yrityksen epäonnistumiseen. Finally-osio ei ole pakollinen. Se suoritetaan sekä onnistuneen että epäonnistuneen kokeilun lopuksi.
Erilaisia poikkeusluokkia RuntimeException Exception...näitä ei tarvitse käsitellä. Tarvitsee käsitellä, paitsi... Throwable Kaikkien poikkeusluokkien yläluokka. (Nimestään huolimatta ei siis rajapinta.) Error Ei tarvitse käsitellä.
UML pähkinänkuoressa (Unified Modeling Language) Olento Karttaruutu attribuutit metodit - nimi : String - elinvoima : int - sijainti : Karttaruutu + Olento(nimi : String, elinvoima : int) : Olento + annanimi() : String + annaelinvoima() : int + muutaelinvoimaa(muutos : int) : void # kuole() : void + annasijainti() : Karttaruutu + asetasijainti(ruutu : Karttaruutu) : void + teesiirto() : void perintä (extends) Basiliski 0.. 1 kaksisuuntainen viittaus: olento tuntee sijaintinsa ja karttaruutu siinä sijaitsevat olennot; olennolla on vain (enintään) yksi sijainti, mutta karttaruudussa voi olla useita olentoja kursiivi: abstrakti luokka tai metodi alleviivaus: staattinen attribuutti tai metodi ISOT_KIRJAIMET: vakioarvo (final) - nimi : String - olennot : List<Olento> - ruuduntarkkailijat : List<Ruuduntarkkailija> + Karttaruutu(nimi : String) : Karttaruutu + annanimi() : String + lisaaolento(o : Olento) : boolean + poistaolento(o : Olento) : boolean + sisaltaaolennon(o : Olento) : boolean + lisaaruuduntarkkailija(rt : Ruuduntarkkailija) : void + poistaruuduntarkkailija(rt : Ruuduntarkkailija) : void yksisuuntainen viittaus: Karttaruutu-luokan ilmentymillä saattaa olla attribuuttinaan viittauksia Ruuduntarkkailijoihin - # + private protected public - BASILISKIN_KATSE : Pelotteluesine + Basiliski(nimi : String) : Basiliski + teesiirto() : void + olentosaapunut(r : Karttaruutu, o : Olento) : void + olentopoistunut(r : Karttaruutu, o : Olento) : void rajapinnan toteuttaminen (implements) <<interface>> Ruuduntarkkailija + olentosaapunut(r : Karttaruutu, o : Olento) : void + olentopoistunut(r : Karttaruutu, o : Olento) : void rajapinnan metodit
Javadoc-kommentointi / Luokka, joka kuvaa maailmaa. Maailma koostuu kaksiulotteiseen taulukkoon järjestetyistä Karttaruutu-olioista. @author Veijo Vesisika / public class Maailma { / Ilmansuunta pohjoinen, lukuarvoltaan 0. / public static final int POHJOINEN = 0; / Metodi, jonka avulla voi selvittää tässä maailmassa tietyissä koordinaateissa sijaitsevan karttaruudun. @param x karttaruudun x-koordinaatti @param y karttaruudun y-koordinaatti @return annetuissa koordinaateissa sijaitseva karttaruutu tai null, jos paikassa ei ole karttaruutua @throws PahaPoikkeus jos koordinaatit osoittavat maailman ulkopuolelle / public Karttaruutu annakarttaruutu(int x, int y) throws PahaPoikkeus {... vaaditaan neljännestä tehtävästä alkaen
Javadoc-kommentointi On hyvä tapa Javadoc-kommentoida: luokat käyttötarkoitus sanallisesti mahdollisesti myös versionumero (@version) ja tekijän nimi (@author) sekä viittaukset (@see) muihin luokkiin, joihin on hyvä tutustua tätä luokkaa käytettäessä attribuutit (ainakin public- ja protected-tyyppiset) käyttötarkoitus sanallisesti metodit (ainakin public- ja protected-tyyppiset) käyttötarkoitus sanallisesti parametrien selitykset (@param) kuvaus siitä, mitä metodi voi palauttaa (@return) kuvaukset metodin mahdollisesti heittämistä poikkeuksista ja niihin johtavista tilanteista (@throws) Huomaa pieni mutta tärkeä notaatioero Javadocin ja muiden useampirivisten kommenttien välillä: / / Tämä on Javadocia. Käytä tätä Tämä on tavallinen kommentti, jollaisia vain sille varatuissa paikoissa. voi laittaa myös metodien koodin sekaan. / / Javadoc-kommenteista voidaan muodostaa itse laadituille luokille automaattisesti vastaavanlaiset dokumentaatiosivut kuin mitä Java-API:sta löytyy Javan valmiille luokille. Tämä tapahtuu esimerkiksi komennolla: javadoc -d docs -link http://java.sun.com/j2se/1.5.0/docs/api/.java