informaatioverkostot studio 1 luentomateriaali n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Informaatioverkostot: Studio 1 Luentomateriaali PowerPoint Presentation
Download Presentation
Informaatioverkostot: Studio 1 Luentomateriaali

Loading in 2 Seconds...

play fullscreen
1 / 75

Informaatioverkostot: Studio 1 Luentomateriaali - PowerPoint PPT Presentation


  • 94 Views
  • Uploaded on

SWING. JAVADOC. UML-KAAVIOT. SÄIKEET JA SWING. 2D-GRAFIIKKA. SOVELMAT. TIETOVIRRAT. JAVA-API. PAKKAUKSET. POLYMORFISMI. SILMUKAT. MERKKIJONOT. TAULUKOT. MUUTTUJAT. SUUNNITTELUSTA. POIKKEUKSET. Informaatioverkostot: Studio 1 Luentomateriaali. 5 11 17 23. 40 45 50 60.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Informaatioverkostot: Studio 1 Luentomateriaali' - abe


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
informaatioverkostot studio 1 luentomateriaali

SWING

JAVADOC

UML-KAAVIOT

SÄIKEET JA SWING

2D-GRAFIIKKA

SOVELMAT

TIETOVIRRAT

JAVA-API

PAKKAUKSET

POLYMORFISMI

SILMUKAT

MERKKIJONOT

TAULUKOT

MUUTTUJAT

SUUNNITTELUSTA

POIKKEUKSET

Informaatioverkostot: Studio 1Luentomateriaali

5

11

17

23

40

45

50

60

Janne Käki

2006

28

33

35

37

63

64

66

70

muutama perusasia
Muutama perusasia
  • Tietokone tekee juuri (ja vain) sen, mitä käsketään.
  • Tietokone ymmärtää vain syntaksia (sanojen kirjoitusasua), ei semantiikkaa (sanojen merkitystä).
    • Muuttujat ja metodit voi tietokoneen puolesta nimetä (melkein) ”ihan miten vaan”, olennaista on vain, että samasta muuttujasta tai metodista käytetään johdonmukaisesti samaa nimeä.
    • Java-kielessä on kuitenkin joitakin kymmeniä avainsanoja (public, private, int, void, true, null, return, . . .), jotka on varattu tiettyyn käyttöön. Näitä ei siis voi valita muuttujien nimiksi.
    • Se, että muuttujat ja metodit nimetään fiksusti ja käyttötarkoitusta kuvaavasti, on tärkeää nimenomaan (ja vain) koodia lukevan ihmisen kannalta.
  • Ohjelman suoritus on normaalisti (virheettömänä) täysin näkymätöntä.
    • Siksi tarvitaan tulostuksia, jotta saisimme käsityksen siitä, mitä ohjelmassa tapahtuu – mitä paremmat tulostukset, sitä parempi käsitys.
sijoituslause
Sijoituslause

sijoitusoperaattori (ei yhtäsuuruusmerkki!)

int luku = (5 + 4) * 8 - 7;

laskuri = laskuri + 1;

1. Selvitetään oikeanpuoleisen lausekkeen arvo.

2. Määritellään uusi kokonaislukutyyppinen muuttuja nimeltä luku.

3. Sijoitetaan kohdassa 1 laskettu arvo kohdassa 2 määriteltyyn muuttujaan.

1. Lasketaan yhteen laskurin nykyinen arvo ja yksi.

2. Sijoitetaan tämä arvo laskurin uudeksi arvoksi.

(Koska laskurimuuttuja on jo entuudestaan olemassa, sitä ei siis ole syytä määritellä uudelleen, joten emme käytä sanaa int.)

palauttaminen vs tulostaminen
Palauttaminen vs. tulostaminen

Metodi, joka palauttaa tekstin ”böö”:

public String palautaBöö() {

return ”böö”;

}

Metodi, joka tulostaa tekstin ”böö”:

public void tulostaBöö() {

System.out.println(”böö”);

}

paluuarvon tyyppi

”ei palauta mitään”

antaa palautettavan arvon käyttöön sille, joka metodia kutsui

tuottaa tekstin näytölle

String bööTeksti = palautaBöö();

System.out.println(bööTeksti);

böö

tiedon abstraktiotasoja

MUUTTUJAT

Tiedon abstraktiotasoja

kokoelmatnimetty joukko olioita

oliotnimetty joukko muuttujia (ja operaatioita)

Javan fokus

muuttujatnimetty tietyntyyppisen tiedon muistipaikka

muistipaikatjoukko bittejä, joilla on yksi osoite

bititnollia tai ykkösiä

erilaisia muuttujia

MUUTTUJAT

Erilaisia muuttujia

public class Mursu {

private String nimi;

private int nopeus;

public Mursu(String nimi, int nopeus) {

this.nimi = nimi;

this.nopeus = nopeus;

}

public double liiku(double aika) {

double matka = aika * this.nopeus;

System.out.println(nimi + ” lyllersi ” + matka + ” km.”);

return matka;

}

}

muuttujista

MUUTTUJAT

Muuttujista
  • Muuttujan määrittely (eli esittely): nimetään tietolokero ja kerrotaan, minkä tyyppistä tietoa se voi sisältää.
    • String brutaaliSolvaus;
    • int vihreidenPingviinienLukumaara;
  • Muuttujan alustus: sijoitetaan muuttujaan (sen historian ensimmäinen) arvo.
    • brutaaliSolvaus = ”hähä mogari”;
    • Voidaan tehdä myös suoraan määrittelyn yhteydessä:String brutaalimpiSolvaus = ”luetaan sitä API:a”;
  • Muuttujan arvon lukeminen: käytetään muuttujaa missä tahansa muualla kuin sijoituslauseen vasemmalla puolella.
    • System.out.println(brutaalimpiSolvaus);
    • if (vihreidenPingviinienLukumaara > 1) {
    • Ei saa tehdä alustamattomalle muuttujalle, muuten kääntäjää alkaa pelottaa. (”Variable might not have been initialized.”)
    • Attribuuteilla on aina tietty alkuarvo automaattisesti (numeromuuttujilla nolla, booleaneilla false, oliomuuttujilla null), joten niiden alustaminen ei ole välttämätöntä ennen muuttujan käyttämistä – yleensä toki suositeltavaa.
viittaustyyppiset muuttujat

MUUTTUJAT

Viittaustyyppiset muuttujat
  • Olio on kuin ilmapallo.
  • Oliomuuttujat ovat viittauksia – kuin naruja, joiden päässä se ilmapallo on.
  • Sama olioilmapallo voi olla useamman narun päässä. Siihen voidaan vaikuttaa (eli sen metodeita kutsua) kaikkia naruja pitkin, ja kaikki kutsut muokkaavat yhtä ja samaa oliota.
  • Kun oliomuuttuja lakkaa olemasta tai saa uuden arvon, yksi naru katkeaa.
  • Kun olio ei ole enää yhdenkään narun päässä kiinni, se karkaa stratosfääriin (eli Javan automaattinen roskienkerääjä tulee ja syö sen).
klassinen for lause

SILMUKAT

Klassinen for-lause

for (int i = 0; i < 3; i++) {

...

}

ei

onkoehtotosi?

for-lauseen jälkeinen elämä

alustus-lause

suoritettavatlauseet

kyllä

kasvatus-lause

slide12

SILMUKAT

Tällainen for-lause...

for (int i = 0; i < 3; i++) {

...

}

...vastaa while-lauseella toteutettua rakennetta

{

int i = 0;

while (i < 3) {

...

i++;

}

}

Mikä merkityson ulommillaaaltosuluilla?

iteroiva for lause

SILMUKAT

Iteroiva for-lause

public void tulostaNimet(Set<Olento> olennot) {

for (Olento o : olennot) {

System.out.println(o.annaNimi());

}

}

  • Käy läpi kaikki tiettyyn kokoelmaan sisältyvät oliot.
  • Kukin kokoelman olio sijoitetaan siis vuorollaan for-lauseen määrittelemään muuttujaan ja siihen sovelletaan aaltosulkujen sisällä olevia lauseita.
  • Läpikäyntijärjestys riippuu kokoelmasta. Listoilla se on määrätty, joukoilla (Set) yleensä määrittelemätön, mutta ei kuitenkaan aidosti satunnainen.
  • Kokoelman sisältöä ei saa muuttaa (lisätä tai poistaa olioita) kesken iteroinnin, muuten seuraa virhe nimeltä ConcurrentModificationException.
slide14

SILMUKAT

public void tulostaNimet(Set<Olento> olennot) {

String nimet = ””;

for (Olento o : olennot) {

nimet += o.annaNimi() + ”, ”;

}

System.out.println(nimet);

}

Miten pääsemme eroon ylimääräisestä pilkusta?

Arska, Pena, Mats, Rauski,

Tulostaa:

public void tulostaNimet(Set<Olento> olennot) {

String nimet = ””;

int otuslaskuri = 0;

for (Olento o : olennot) {

nimet += o.annaNimi();

if (otuslaskuri < olennot.size()-1) {

nimet += ”, ”;

}

otuslaskuri++;

}

System.out.println(nimet);

}

iteraattori

SILMUKAT

Iteraattori

Vanha tuttu iteroiva for-looppi...

Kokoelman on toteutettava rajapintaIterable<T>, joka määrittelee metodin

public Iterator<T> iterator().

for (Olio o : kokoelma) {

System.out.println(o);

}

...toimii pinnan alla itse asiassa iteraattoriolion avulla.Sama looppi hieman toisin kirjoitettuna:

Iterator<Olio> iter = kokoelma.iterator();

while (iter.hasNext()) {

Olio o = iter.next();

System.out.println(o);

}

Myös Iterator<T> on itse asiassa rajapinta.Iteraattorin metodi next() palauttaa ja

poistaa – iteraattorista, ei iteroitavastakokoelmasta – järjestyksessä seuraavanelementin. Metodi hasNext() kertoo,vieläkö elementtejä on jäljellä.

iteraattori1

SILMUKAT

Iteraattori
  • Iteroimisessa on vaaransa. Metodi next() voi heittää poikkeuksia...
    • NoSuchElementException, jos elementtejä ei enää ole. Vältettävissä huolellisella hasNext()-metodin käytöllä.
    • ConcurrentModificationException, jos iteroitava kokoelma on muuttunut iteraattorin luomisen jälkeen. Uusia elementtejä ei siis voi kesken iteroinnin lisätä, ellei iterointia tämän jälkeen keskeytä.Elementtien poistaminen on luvallista iteroinnin lomassa vain iteraattori-olion metodilla remove(), joka poistaa viimeisimmän next()-metodin palauttaman elementin, myös iteroitavasta kokoelmasta.
    • Iteraattori siis antaa luvan myös elementtien poistamiseen kokoelmasta (periaatteessa – oma iteraattoriluokka voidaan kuitenkin toteuttaa myös niin, ettei remove()-metodi tee mitään). Aina ulkopuoliselle käyttäjälle ei haluta jättää tällaista mahdollisuutta, jolloin voi olla syytä harkita toisenlaisen rajapinnan tarjoamista kokoelman läpikäyntiin.
taulukko

TAULUKOT

Taulukko

Taulukkomuuttujan määrittely ja alustaminen ns. taulukon alustajalla:

int[] taulu = { 9, 14, 2, 7, 2, 0, 22 };

Taulukon indeksointi ja sen alkioiden arvojen asettaminen:

taulu[0] = 1;taulu[2] = 100;taulu[taulu.length-1] = 8;

Uuden, tyhjän taulukon luonti new-operaattorilla:

taulu = new int[5];

Taulukotkin ovat olioita. Huomaa, että taulukon koko on taulukko-olion, ei taulukkomuuttujan ominaisuus. (Samaan muuttujaan voi sijoittaa minkä kokoisen taulukon tahansa.)

Taulukon tietotyyppi on sen sijaan myös taulukkomuuttujan ominaisuus.

slide18

TAULUKOT

Laskurilla varustettu for-silmukka on kuin luotu taulukon läpikäymiseen, esimerkiksi seuraavassa fiktiivisessä Olento-luokan metodissa:

public void kauhistuHirviolaumaa(Olento[] hirviot) {

for (int i = 0; i < hirviot.length; i++) {

hirviot[i].pelottele(this);

}

}

this viittaaaina siihen olioon, jonkametodista on kyse.Sitä voi käyttää myössellaisenaan, esimerkiksiparametrina jollekintoiselle metodille.

Muista, ettätaulukon indeksitalkavat nollasta japäättyvät yhtäpienempään kuintaulukon koko.

hirviot[i] viittaavuorollaan aina yhteentaulukon alkioon,siis Olento-tyyppiseenolioon (ellei kyseinenalkio ole null).

slide19

TAULUKOT

Variable tauluA might not have been initialized.

java.lang.NullPointerException

java.lang.ArrayIndexOutOfBoundsException

Possible loss of precision. Found: double. Required: int.

Incompatible types. Found: double[ ]. Required: int[ ].

Variable tauluA might not have been initialized.

java.lang.NullPointerException

Jos määrittelemme seuraavasti

int[] tauluA;

int[] tauluB = null;

int[] tauluC = new int[5];

Pelotteluesine[] tauluD = new Pelotteluesine[1000];

ja sen jälkeen yritämme seuraavia asioita, mikään niistä ei onnistu. Miksi?

tauluA[0] = 49;

tauluB[0] = 88;

tauluC[5] = 31;

tauluC[2] = 4.86;

tauluA = new double[10];

tauluB = tauluA;

tauluD[666].annaPelottavuus();

Inspired by: http://www.cs.helsinki.fi/u/wikla/Ohjelmointi/Sisalto/3/Taulukot.html#2

kaksiulotteinen taulukko eli taulukoita taulukossa

TAULUKOT

Kaksiulotteinen taulukkoeli taulukoita taulukossa

Luodaan 2D-taulukko eli matriisi, jossa on neljä riviä ja viisi saraketta:

Olento[][] otusruudukko = new Olento[4][5];

otusruudukko[2][1] = new Olento(”Rauski”, 100);

Itse asiassa loimme yhden nelipaikkaisen taulukon, jonka alkioiden tietotyyppi on Olento[]. Se sisältää siis neljä yksiulotteista, viisipaikkaista olentotaulukkoa. Nämä taulukot ovat aluksi tyhjiä, eli niiden jokainen alkio on null.

Voimme sijoittaa ruudukkoon uusia arvoja kertomalla, mihin alitaulukkoon ja mihin lokeroon siellä kyseinen arvo sijoitetaan:

slide21

TAULUKOT

2D-taulukon rivien ei välttämättä tarvitse olla samanpituisia – jokainen alitaulukkohan on yksilöllinen olio, jonka pituus voi olla mitä vain:

Olento[][] otusruudukko = new Olento[4][];

Huomaa tyhjät jälkimmäiset hakasulut. Tässä luotiin tyhjä nelipaikkainen taulukko, johon voi sijoittaaOlento[]-taulukoita.

Näitä alitaulukkoja ei kuitenkaan vielä ole olemassa, ne on luotava nyt erikseen.

otusruudukko[0] = new Olento[5];

otusruudukko[1] = new Olento[3];

otusruudukko[2] = new Olento[1];

otusruudukko[3] = new Olento[4];

otusruudukko[3][3] = new Olento(”Rauski”, 100);

slide22

TAULUKOT

for-lauseita voi käyttää myös sisäkkäin.

Kaksiulotteisen taulukon läpikäynnissä tämä on usein tarpeen:

String[][] ruudut = new String[5][5];

for (int i = 0; i < ruudut.length; i++) {

for (int j = 0; j < ruudut[i].length; j++) {

ruudut[i][j] = i + ”, ” + j;

}

}

merkkijonojen vertailu

MERKKIJONOT

Merkkijonojen vertailu

String a = "kaikki on mahdollista";

String b = "kaikki on mahdollista";

System.out.println(a == b);

b = new String("kaikki on mahdollista");

System.out.println(a == b);

System.out.println(a.equals(b));

System.out.println(a == b.intern());

true

false

true

true

Esimerkit: Ville Sundberg

slide24

MERKKIJONOT

EI NÄIN

if (nimi == ”Rauski”) {

VAAN NÄIN

if (nimi.equals(”Rauski”)) {

TAI JOS KIRJAIN-KOOLLA EI OLE MERKITYSTÄ

if (nimi.equalsIgnoreCase(”RAUSKI”)) {

merkkijonon paloittelu

MERKKIJONOT

Merkkijonon paloittelu

String lause = ”Kivet on tosi jänniä.”;

String[] sanat = lause.split(” ”);

merkkijonon tulkinta luvuksi

MERKKIJONOT

Merkkijonon tulkinta luvuksi

Integer.parseInt(String merkkijono)

  • Integer-luokan staattinen metodi
  • yrittää tulkita merkkijonon kokonaisluvuksi
  • heittää poikkeuksen NumberFormatException, jos merkkijono ei esitä puhdasta kokonaislukua (varauduttava aina tähän mahdollisuuteen)

Double.parseDouble(String merkkijono)

  • Double-luokan staattinen metodi, muuten sama kuin yllä mutta tulkitsee merkkijonoja desimaaliluvuiksi (desimaali-erottimena oletusarvoisesti piste)
slide27

MERKKIJONOT

String-luokassa lisäksi mm. metodit:

  • String substring(int alku, int loppu)
    • palauttaa osamerkkijonon väliltä alku … loppu-1
  • int indexOf(String osamerkkijono)
    • palauttaa indeksin, josta etsittävä osamerkkijono (ensimmäinen löytynyt) alkaa
    • jos osamerkkijonoa ei löydy, palauttaa arvon –1
  • String trim()
    • palauttaa merkkijonon kopion, jonka alusta ja lopusta on poistettu mahdolliset välilyönnit
  • String toLowerCase()
    • palauttaa merkkijonon kopion, jonka kaikki ISOT KIRJAIMET on muutettu pieniksi kirjaimiksi (toUpperCase() tekee saman toisinpäin)
  • String toString()
    • :D

Luokka String on arvo-keskeinen: String-olion metodit eivät muuta kysei-sen olion tilaa mitenkään. Jos metodi tekee muutoksia, se palauttaa kopion alku-peräisestä – uuden olion.

slide28

POLYMORFISMI

Halutaan luoda uusi Pelotteluesine...

Kun luodaan uutta Pelotteluesinettä, on sille ensin rakennettava yläluokkien määrittelemä perusta – alustettava ne ominaisuudet, jotka sille kuuluvat 1) Objectina ja 2) Esineenä.

public Pelotteluesine(String nimi, double paino, int pelottavuus) {

super(nimi, paino);

this.pelottavuus = pelottavuus;

}

public Esine(String nimi, double paino) {

super();

this.nimi = nimi; this.paino = paino;

}

public Object() {

...

}

...mutta ennen pelotteluesineen oman pelottavuus-ominaisuuden alustusta on varmistettava, että perustana on oikeaoppinen Esine. Siksi ihan aluksi kutsutaan Esine-luokan luontimetodia...

Pelotteluesine

private int pelottavuus

public Pelotteluesine(String nimi,double paino, int pelottavuus)

Esine

private String nimiprivate double paino

public Esine(String nimi, double paino)

...jonka aluksi puolestaan kutsutaan vielä Object-luokan konstruktoria. (Tässä super();ia ei olisi pakko kirjoittaa, koska nyt yläluokan luontimetodille ei tarvitse antaa parametreja. Esineelle sen sijaan täytyi.)

ominaisuuksien määrä

Object

public Object()

metodin kuormittaminen overloading

POLYMORFISMI

Metodin kuormittaminen(overloading)
  • Samannimisestä metodista on määritelty samassa luokassa (tai samassa yli- ja aliluokkien jatkumossa) useita versioita, joista valitaan suoritettavaksi yksi sen perusteella, mitä parametreja metodikutsussa on annettu.
  • Metodikutsu sidotaan suoritettavaan metodiin metodin nimen sekä parametrien tyyppien ja järjestyksen perusteella. (Sen sijaan esimerkiksi parametrimuuttujien nimillä ei ole mitään merkitystä.Ei myöskään sillä, minkä tyyppisiä arvoja metodin eri versiot palauttavat.)
  • Metodikutsujen on oltava yksiselitteisiä, eli ei saa olla epäselvää, mikä vaihtoehtoisista tietynnimisen metodin versioista nyt suoritetaan:

public void metodi(Object o, String s) { ...}

public void metodi(String s, Object o) { ...}

metodi(”nuuh”, ”nuuh”);

metodi(”nuuh”, (Object) ”nuuh”);

metodin korvaaminen overriding

POLYMORFISMI

Metodin korvaaminen(overriding)
  • Aliluokka määrittelee yliluokassa määritellyn metodin toteutuksen kokonaan uudelleen. Korvaavan metodin puumerkki on täsmälleen sama kuin alkuperäisen, eli metodeilla on sama nimi, samanlainen parametrilista (tyypit ja järjestys) ja sama paluuarvon tyyppi.
  • Voidaan merkitä aliluokkaan kirjoittamalla metodin yläpuolelle erityinen @Override-tägi. Ei pakollista, mutta parantaa luettavuutta.
  • Metodin uusi versio EI saa
    • muuttaa paluuarvon tyyppiä,
    • rajata näkyvyyttä alkuperäistä suppeammaksi (laajentaa sen sijaan saa),
    • heittää sellaisia poikkeuksia joita alkuperäinen ei määritellyt heittävänsä (sen sijaan uusi versio voi mainiosti olla heittämättä joitakin poikkeuksia joita alkuperäinen metodi heitti).
  • Kun luokan A metodi x() on korvattu aliluokassa B metodilla x(), niin alkuperäistä metodia voi kutsua luokan B oliolle vain olio itse notaatiolla super.x(). Muut kutsut johtavat aina luokassa B määritellyn metodin suorittamiseen.
metodien staattinen ja dynaaminen sidonta

POLYMORFISMI

Metodien staattinen ja dynaaminen sidonta

Otus eka = new Otus();

Otus toka = new PäheäOtus();

PäheäOtus kolmas = new PäheäOtus();

Olkoon PäheäOtus luokan Otus aliluokka. Otus-luokassa on määritelty tylsä metodi eksistoi(), jonka PäheäOtus on korvannut uudella päheämmällä versiolla. Lisäksi PäheäOtus-luokassa on täysin uusi, ennen näkemätön metodi kelaaSunLaatuas().

PäheälleOtukselle, joka on sijoitettu Otus-tyyppiseen muuttujaan, voidaan kutsua ainoastaan Otus-luokan metodeja. Sanotaan, että kyseisen olion staattinen tyyppi on Otus. Vaikka olio siis osaisi myös kelata laatuaan, sitä ei voi tuon muuttujan kautta käskeä niin tekemään. Sopivalla tyyppimuunnoksella staattinen tyyppi voidaan kuitenkin saattaa sellaiseksi, että tuokin metodi on käytössä.

Sen sijaan muuttujan staattinen tyyppi Otus antaa toki meille luvan kutsua oliollemme metodia eksistoi(). Tällöin metodikutsu sidotaan kuitenkin aina olion todelliseen, dynaamiseen tyyppiin, joka tässä tapauksessa on PäheäOtus. Hämmästykseksemme tylsässä Otus-laatikossa piileksinyt olio alkaakin siis eksistoida hyvin päheästi, kun käskytämme sitä tuollaisella metodikutsulla. Mitenkään emme pysty käskemään tuota oliota käyttäytymään siten kuin puhdas Otus käyttäytyisi, ellei se sitten itse päätä suorittaa tuota metodia kutsulla super.eksistoi().

Staattinen tyyppi siis sanelee sen, mitkä metodikutsut muuttujaan sijoitetulle oliolle ovat ylipäänsä luvallisia. Dynaaminen tyyppi (joka ei olion elinaikana muutu) taas määrää, mitä koodia oliolle tehtyjen metodikutsujen seurauksena todella suoritetaan.

:)

:D

eka

toka

:D

kolmas

rajapinnat

POLYMORFISMI

Rajapinnat

Rajapinta eli liittymä (engl. interface) 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 toteuttami-sesta 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

POIKKEUKSET

Poikkeukset

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 Paaryna varastaPaaryna() throws KaameaPoikkeus {

if (vartija.onVahdissa() && !vartija.nukkuu()) {

KaameaPoikkeus poikkeus = new KaameaPoikkeus("Kiinni jäit, hähä!");

throw poikkeus;

} else {

return paarynapuu.annaPaaryna();

}

}

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

POIKKEUKSET

Exception

Error

Erilaisia poikkeusluokkia

RuntimeException

...näitä ei tarvitse käsitellä.

Tarvitsee käsitellä, paitsi...

Throwable

Kaikkien poikkeus-luokkien yläluokka. (Nimestään huolimatta ei siis rajapinta.)

Ei tarvitse käsitellä.

keskeisimm t java api n pakkaukset
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 Writer-luokat)

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

JAVA-API

Keskeisimmät Java-API:n pakkaukset

API = Application Programming Interface eli sovellusohjelmointirajapinta (!)

pakkaus (engl. package) = tapa koota samaan asiaan liittyviä luokkia yhteen

luetaan sit api a mutta miten

JAVA-API

Luetaan sitä API:a!Mutta miten?

Java-ohjelmoinnissa monien ongelmien ratkaisu käy seuraavaan tapaan:

  • Etsi API:sta oikea luokka haluamasi asian tekemiseen.
  • Etsi luokasta metodi, jolla sen saa tekemään tuon asian.
  • 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 suora-viivaisempia käyttää, toiset tarjoavat mahdollisuuden hyvinkin monimutkaisiin säätöihin. Valitse oikea metodi tarpeesi mukaan, säästyt turhalta säätämiseltä. :)
n pp imist n lukeminen

TIETOVIRRAT

InputStream

(System.in)

näppäimistö

BufferedReader

InputStreamReader

Näppäimistön lukeminen

tavut

11101011

merkit

01001110

b

r

merkkijonot

ö

m

mene avantoon

katso olentoa 4

slide39

TIETOVIRRAT

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

BufferedReader

InputStreamReader

InputStream

(System.in)

IOException (tietovirtahepo) vaanii kaikissa tietovirroissa

tapahtumapohjainen ohjelmointi

SWING

käyttäjä tekee jotain…

Tapahtuma

Tapahtuman-käsittelysäie(event dispatching thread)

tapahtumaanreagointi(”ohjelmatekee jotain”)

Työläissäie(worker thread)

ohjelman sulkeminen

Tapahtumapohjainen ohjelmointi

ohjelman käynnistys

käyttöliittymän alustus

Tapahtuman kuuntelija(t)

tapahtuman odottelu…

gridbagconstraints

SWING

GridBagConstraints

anchor:komponentin sijainti solunsisällä (CENTER, NORTH,EAST, SOUTHWEST, jne.)

GridBagConstraints c = new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 2, 5, 2), 0, 0);

gridx ja gridy:komponentin sijainti-koordinaatit ”gridissä”(vasemmalta ylhäältä luettuna)

fill:kuinka komponentti täyttääsolunsa (HORIZONTAL,VERTICAL, BOTH tai NONE)

gridwidth ja gridheight:komponentin leveys ja korkeus(riveissä ja sarakkeissa)

insets:montako pikseliätyhjää tilaakomponentinympärille jätetään(ylös, vasemmalle,alas, oikealle)

ipadx ja ipady:paljonko tyhjää reunusta(”paddingia”) kompo-nentin sisään jätetäänsen minimikoossa

weightx ja weighty:komponentin suhteellinenpainoarvo (0.0–1.0)säiliötä täytettäessä

gridbaglayout

SWING

GridBagLayout

JPanel paneeli = new JPanel( new GridBagLayout());

JTextField kenttä = new JTextField();

GridBagConstraints c = new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 2, 5, 2), 0, 0);

paneeli.add(kenttä, c);

  • Luodaan paneeli.
  • Asetetaan paneelin asettelijaksi uusi GridBagLayout.
  • Luodaan käyttöliittymä-komponentti.
  • Luodaan GridBagConstraints-olio, jolle asetetaan sopivat attribuuttien arvot.
  • Lisätään komponentti paneeliin GridBagConstraints:ia käyttäen.
  • Palataan tarvittaessa kohtaan 3.
gridbaglayout toinen tapa

SWING

GridBagLayout, toinen tapa

JPanel paneeli = new JPanel( new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();

JTextField kenttä = new JTextField();

c.gridx = 0;c.gridy = 0;c.anchor = GridBagConstraints.SOUTH;c.insets = new Insets(5, 2, 5, 2);

paneeli.add(kenttä, c);

JButton namiska = new JButton(”pl”);

c.gridy = 1;

paneeli.add(namiska, c);

  • Luodaan paneeli.
  • Asetetaan paneelin asettelijaksi uusi GridBagLayout.
  • Luodaan GridBagConstraints-olio oletusarvoisilla attribuuteilla.
  • Luodaan käyttöliittymä-komponentti.
  • Muutetaan GridBag-Constraints:in attribuuttien arvoja, mikäli tarpeen.
  • Lisätään komponentti paneeliin GridBagConstraints:ia käyttäen.
  • Palataan tarvittaessa kohtaan 4.
sovelman ajaminen

SOVELMAT

Sovelman ajaminen

<html>

<head> <title>Kolee appletti</title></head>

<body> <table width=”100%” height=”100%” border=”0”> <tr> <td align=”center” valign=”middle”>

<applet code=”KoleeAppletti.class” width=”400” height=”300”> </applet>

</td> </tr> </table></body>

</html>

sovelma vs sovellus

SOVELMAT

Sovelma vs. sovellus
  • Sovelmalla kiinteä ikkunan koko, sovelluksella joustava
  • Sovelma ei saa kirjoittaa mihinkään tiedostoon, sovellus saa
    • ns. servletit (palvelinsovelmat eli ”palvelmat”) saavat temmeltää jossain määrin vapaammin
  • Jotkin asiat on tehtävä sovelmissa hieman monimutkaisemmin, esimerkkinä kuvan lataaminen javax.swing.ImageIcon-olioksi:

ImageIcon kuva = new ImageIcon(”mursu.png”);

ImageIcon kuva = null; try { kuva = new ImageIcon(this.getImage( new java.net.URL(this.getCodeBase(), ”mursu.png”))); } catch (java.net.MalformedURLException e) { e.printStackTrace(); }

sovellus

sovelma

swing komponentin piirt minen

2D-GRAFIIKKA

komponentti.repaint()

kutsu tätä tarvittaessa

korvaa tämä tarvittaessa omalla toteutuksella

Swing-komponentin piirtäminen
  • Jokainen komponentti vastaa siitä, miten se piirretään ruudulle
  • Piirtojärjestelmä vastaa siitä, milloin tämä tapahtuu

Piirtojärjestelmä

paintComponent(Graphics g)

komponentti.paint(Graphics g)

paintBorder(Graphics g)

paintChildren(Graphics g)

grafiikkakonteksti

2D-GRAFIIKKA

Grafiikkakonteksti

java.awt.Graphics

Mahdollistaa piirtämisen tiettyyn kontekstiin, esimerkiksi näytöllä olevaan paneeliin tai koneen muistissa olevaan kuvaan.

paintComponent-metodi saa tällaisen piirtojärjestelmältä valmiina.

Sisältää metodeja, joiden avulla voidaan piirtää mm. viivoja, ovaaleja, monikulmioita, tekstiä sekä muistiin ladattuja kuvia.

java.awt.Graphics2D

Edellisen aliluokka, jossa uusina ominaisuuksina mm. erityisten kuvio-olioiden piirtäminen sekä affiinit koordinaatistonmuunnokset.

Jokainen Graphics-olio on yleensä pohjimmiltaan myös Graphics2D-olio.

piirt minen

2D-GRAFIIKKA

Piirtäminen…

… tapahtuu Graphics-luokan metodien avulla:

… perustuu komponentin omaan koordinaatistoon:

(0, 0)

x

public void paintComponent(Graphics g) {

super.paintComponent(g);

g.setColor(this.koleeVäri); g.drawOval(-20, -40, 100, 50);

g.fillRect(80, 35, 20, 200);

g.setColor(this.getForeground()); g.setFont(this.päheeFontti); g.drawString(”hähä”, 10, 150);

g.drawImage(this.kuva, 100, 100, null);

}

hähä

(width-1, height-1)

y

Myös komponentin rajojen ulkopuolelle voi ”piirtää”, mutta nämä osat eivät näy ruudulla.

kaksoispuskurointi

2D-GRAFIIKKA

Kaksoispuskurointi

java.awt.Image

javax.swing.JPanel

Jos komponentti piirretään osissa, piirtämistä ei kannata tehdä suoraan näytölle, vaan koneen muistissa näkymättömissä olevaan kuvaan (“bufferiin”). Valmis kuva piirretään sitten ruudulla näkyvään komponenttiin yhtenä kokonaisuutena, jolloin vältetään kuvan välkkyminen ja eri osien eriaikainen piirtyminen.

Swing-komponentit ovat kuitenkin oletusarvoisesti valmiiksi kaksoispuskuroituja.On siis turvallista piirtää suoraan niihin.

kuvan piirt minen

2D-GRAFIIKKA

Kuvan piirtäminen

g.drawImage(Image img, int x, int y, ImageObserver obs);

Mitäs laitan koordinaateiksi?

Mikä kumma tää nyt sit on?

Mistä se kuva saadaan?

  • Helpoin tapa:
  • Luo ImageIcon-olio haluamastasi kuvatiedostosta.
  • Kysy Image-olio siltä.

Komponentin sen pisteen, johon haluat sijoittaa kuvan vasemman yläkulman.

Joku, joka odottelee (tarvittaessa) kuvan latautumista muistiin.

Jos käytät ImageIcon:ia kuvan hakemiseen, tämä voi hyvin olla null.

Saavat olla myös negatiivisia.

On myös muita, vaikeampia tapoja.

kuvan piirt minen graphics2d ll

2D-GRAFIIKKA

Kuvan piirtäminen Graphics2D:llä

g2.drawImage(Image img, AffineTransform xform, ImageObserver obs);

Mahdollistaa ns. affiinien muunnosten tekemisen piirrettävälle kuvalle.Kuvaa voi esimerkiksi pyöritellä vapaasti.

Muunnokset esitetään 3 x 3 -matriisina, java.awt.geom.AffineTransform.

Ohjelmoijan ei kuitenkaan välttämättä tarvitse juuri vaivata päätään matriisialgebralla – riittää, että tietää mitä haluaa (siirtää, kääntää, skaalata, vääntää) ja kuinka paljon :)

geometriset muunnokset

2D-GRAFIIKKA

Geometriset muunnokset

Siirto (translation)

Viistoutus (shearing)

Kierto (rotation)

Peilaus (mirroring)

Skaalaus (scaling)

mvc arkkitehtuurimalli

2D-GRAFIIKKA

MVC-arkkitehtuurimalli

MODEL

ohjelman tila visualisoidaan käyttäjälle

käyttäjän toimenpiteet muuttavat ohjelman tilaa

VIEW

CONTROLLER

käyttäjä reagoi näkemäänsä käyttöliittymän välityksellä

graafinen vuorovaikutteinen peli

2D-GRAFIIKKA

dsfa

x

y

Graafinen vuorovaikutteinen peli

ohjelman tila visualisoidaan käyttäjälle

MODEL

käyttäjän toimenpiteet muuttavat ohjelman tilaa

VIEW

CONTROLLER

käyttäjä reagoi näkemäänsä käyttöliittymän välityksellä

slide59

2D-GRAFIIKKA

dsfa

x

y

MODEL

VIEW

CONTROLLER

Pelimaailman malli: paikat, olennot, esineet

Pelimaailman (tai sen tietyn osan) visualisaatio

Muutoksen aiheuttaja, ”pelimoottori”

Kuuntelee pelaajan

antamia komentoja ja

reagoi niihin

Muistaa kuka missäkin on,mitä tekemässä, millaisessakunnossa, ja niin edelleen

Piirtää pelin grafiikan(ja toistaa musiikin, ääni-tehosteet, yms.)

Pitää yllä pelaajastariippumattomiapelitapahtumia

s ikeet ja swing

SÄIKEET JA SWING

Säikeet ja Swing
  • Swingissä on ”yhden säikeen sääntö”: realisoituneita käyttöliittymäkomponentteja tulee käsitellä ainoastaan yhdestä säikeestä, Swingin tapahtumankäsittelijäsäikeestä (event dispatching thread).
    • Tapahtumankäsittelijäsäie on siis se, joka suorittaa kuuntelijoiden sopivien metodien kutsumisen vastaavien tapahtumien yhteydessä sekä kaikkien Swing-komponenttien piirtämisen ruudulle.
    • Realisoitunut tarkoittaa sitä, että komponentti on tehty näkyväksi ruudulla. Ylimmän tason säiliöille (kuten JFrame) tämän tekee jokin metodikutsuista setVisible(true), show() tai pack().
    • Alemman tason komponentit realisoituvat, kun ne lisätään näkyvään säiliöön tai ne sisältävä säiliö tulee näkyväksi.
    • Toisin sanoen vielä näkymättömän käyttöliittymän alustus voi periaatteessa tapahtua missä säikeessä tahansa, näkyvien komponenttien tilan tutkiminen ja muuttaminen sen sijaan vain tapahtumankäsittelysäikeessä. Yleensä on tyylikkäintä rajata kaikki GUI-toiminta tuon säikeen vastuulle. Joskus raskaiden uusien käyttöliittymäosakokonaisuuksien alustus voidaan kuitenkin tehdä omassa säikeessään, jottei tapahtumankäsittely hidastu tarpeettomasti.
ent s sit ku oikeesti tarviin swingiss muitaki s ikeit vai tarviinks

SÄIKEET JA SWING

Entäs sit ku oikeesti tarviin Swingissä muitaki säikeitä? Vai tarviinks?

Case 1: Ajasta riippuvat tapahtumat ja javax.swing.Timer

  • Usein haluamme Swing-ohjelmaan myös käyttäjän tekemisistä riippumatonta toimintaa, esimerkiksi tietyin aikavälein toistuvia tapahtumia. Tällaiseen oma säie olisi luonteva ratkaisu, mutta hankala, koska se ei saisi käsitellä GUI-komponentteja suoraan.
  • Toimiva ratkaisu on käyttää Swingin Timer-luokkaa. Se siirtää vastuun ajastetuista tapahtumista suoraan tapahtumankäsittelijäsäikeelle, joka toteuttaa ne uusina ActionEvent-tapahtumina määrätylle kuuntelijalle. Vähän kuin tapahtuman käynnistykseen olisi olemassa oma nappi, jota joku kävisi klikkaamassa vaikkapa sekunnin välein.
ent s sit ku oikeesti tarviin swingiss muitaki s ikeit vai tarviinks1

SÄIKEET JA SWING

Entäs sit ku oikeesti tarviin Swingissä muitaki säikeitä? Vai tarviinks?

Case 2: Työläissäie ja SwingUtilities.invokeLater()-metodi

  • Raskaita ja aikaavieviä työtehtäviä, kuten vaativaa laskentaa tai suurten oliokokonaisuuksien alustusta, ei kannata suorittaa tapahtumankäsittelysäikeessä, koska tämä näkyisi suoraan käyttäjälle vuorovaikutuksen hidastumisena. Nämä kannattaa delegoida erityisille työläissäikeille, jotka rouskuttelevat omaa urakkaansa huomaamattomasti taustalla.
  • Usein työläissäikeenkin on tarpeen saada aikaan jotakin näkyvää, esimerkiksi ilmoittaa työnsä tuloksista käyttöliittymän kautta. Tätä se ei kuitenkaan saa tehdä suoraan, vaan työläissäikeen pitäisi jotenkin saada vihjattua tapahtumankäsittelysäikeelle, että tämän olisi aika tehdä jotakin.
  • Ratkaisu tähän kommunikaatio-ongelmaan on SwingUtilities-luokan metodi invokeLater(Runnable r), joka ottaa parametrinaan jotakin suoritettavaa (siis olion, jolla on metodi run()) ja siirtää sen suoritettavaksi tapahtumankäsittelysäikeessä ”myöhemmin”, käytännössä hyvinkin pian. run()-metodissa on tyypillisesti koodia, joka yhdistää työläissäikeen työn tulokset ja graafisten käyttöliittymäkomponenttien käsittelyn sopivalla tavalla.
uml p hkin nkuoressa unified modeling language

UML-KAAVIOT

UML pähkinänkuoressa(Unified Modeling Language)

0 .. 1

*

attribuutit

kaksisuuntainen viittaus: olento tuntee sijaintinsa ja karttaruutu siinä sijaitsevat olennot; olennolla on vain (enintään) yksi sijainti, mutta karttaruudussa voi olla useita olentoja

metodit

*

kursiivi: abstrakti luokka tai metodi

alleviivaus: staattinen attribuutti tai metodi

ISOT_KIRJAIMET: vakioarvo (final)

yksisuuntainen viittaus: Karttaruutu-luokan ilmentymillä saattaa olla attribuuttinaan viittauksia Ruuduntarkkailijoihin

perintä (extends)

*

rajapinnan toteuttaminen (implements)

rajapinnan metodit

javadoc kommentointi

JAVADOC

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 {

...

}

slide65

JAVADOC

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

pakkaukset

PAKKAUKSET

Pakkaukset
  • Pieni Java-projekti: kaikki luokat kiltisti samassa hakemistossa, ei ongelmaa.
  • Iso Java-projekti: luokkien määrän kasvaessa kovin suureksi yksi kansio ei enää riitä.
    • Ongelma ihmiselle, ei tietokoneelle. Muista ihmisen tiedonkäsittelyn rajat, enintään 4±2 hahmotettavaa yksikköä kerrallaan tietoisessa tarkastelussa.
  • Luokkakokonaisuus pysyy hallittavana jakamalla se osakokonaisuuksiin, pakkauksiin (engl. package).
    • Yhdessä pakkauksessa yhteen asiaan liittyvät luokat. Toimintalogiikan malli omassa pakkauksessaan, käyttöliittymä omassaan, jne. Nämä voidaan puolestaan edelleen jakaa useaan erikoistuneeseen pakkaukseen.
    • Käytännössä saman pakkauksen luokat sijoitetaan aina samaan hakemistoon.
pakkausten nime minen ja nimihierarkiat

PAKKAUKSET

Pakkausten nimeäminen ja nimihierarkiat

virallinen Java (by Sun Microsystems)

java.awt.event

javax.swing.border

org.w3c.dom

org.omg.CORBA.portable

fi.tkk.inf.studio1.turnaus.labyrintti

järjestöt (W3C, OMG, ...)

Egoboosti- ja brändäysprefiksit.

(Huomaa päinvastainen logiikka kuin www-palvelinten osoitteissa: maa  organisaatio  osasto jne.)

+ Asettavat ohjelmiston suurempaan kontekstiin, luovat tunnistettavuutta.

- Syventävät (muutenkin jo syvää) hakemistohierarkiaa.

Robottiturnaussoftan labyrinttien esittämiseen käytetyt luokat voisivat sijaita tällaisessa pakkauksessa.

Käytännössäkin luokat sijaitsisivat tuollaisen hakemistopolun päässä, esimerkiksi:

C:\Javaproggikset\fi\tkk\inf\studio1\turnaus\labyrintti\Labyrinttiruutu.java

pakkausten k ytt 1

PAKKAUKSET

Pakkausten käyttö 1

Pakkaus, johon luokka sijoittuu, määritellään:

  • Avainsanalla package aivan luokan lähdekoodin alussa: package fi.tkk.inf.studio1.turnaus.labyrintti; import java.util.ArrayList; public class Labyrinttiruutu {
  • Tallentamalla luokkatiedosto oikeaan paikkaan hakemistohierarkiassa.

Pakkaus rajaa luokkien näkyvyyttä niin, että vain samaan pakkaukseen kuuluvat luokat nähdään suoraan – muiden pakkausten luokat on importoitava kuten Javan valmiit luokatkin.

pakkausten k ytt 2

PAKKAUKSET

Pakkausten käyttö 2
  • Eclipsessä pakkausten käyttö on helppoa ja visuaalista.
    • Uusia pakkauksia luodaan samasta valikosta kuin uusia luokkiakin. Oletuksena kaikille projekteille luodaan oletuspakkaus (default package), mutta Eclipse ei arvosta, jos käytät sitä.
    • Luokkia voi myöhemmin siirtää pakkauksesta toiseen Refactor-valikon Move-toiminnolla. Tämä päivittää automaattisesti kaikki viittaukset kyseiseen luokkaan ja lisää tarvittavat importit.
  • Komentoriviympäristössä pakkaukset tuovat hieman enemmän haastetta. Kääntäminen ja ajaminen vaativat nyt ensin ns. classpathin määrittelemisen.
    • set CLASSPATH=path1;path2;path3(Windows)
    • setenv CLASSPATH path1:path2:path3(Unix)
    • Näissä path1 jne. ovat hakemistopolkuja, joista (ja joiden alta) luokkia etsitään. Usein riittää nykyiseen hakemistoon osoittava polku eli pelkkä piste. Se on suhteellinen polku, eli muuttuu valitun hakemiston mukaan.
  • Lisäksi luokkia ajaessa täytyy kertoa, mistä pakkauksesta (määritellyn classpath-hakemiston alta) kyseinen luokka löytyy:
    • esim. java fi.tkk.inf.studio1.turnaus.Turnaus &
oliopohjaisessa suunnittelussa mietitt v

SUUNNITTELUSTA

Oliopohjaisessa suunnittelussa mietittävää...
  • Käytänkö Javan valmista luokkaa sellaisenaan vai kirjoitanko sille aliluokan?
    • Mieti, tarvitseeko luokan ilmentymien osata jotain erityistä, jota valmiista luokasta ei löydy, vai riittääkö, että luot valmiista luokasta olion tietyillä ominaisuuksilla. Usein Swingin säiliöille kannattaa laatia omia aliluokkia, muille Swing-komponenteille tämä taas on harvemmin tarpeen.
  • Korkea koheesio eli (luokkien sisäinen) yhtenäisyys: GOOD!
    • Yhden luokan vastuut muodostavat selkeän kokonaisuuden. Mitään olennaista ei ole piilotettu jonnekin muualle, eikä toisaalta mukana ole mitään kovin epärelevanttiakaan.
  • Korkea luokkien välinen kytkeytyneisyys: BAD!
    • Jokainen luokkien välinen riippuvuussuhde tekee kokonaisuudesta vaikeammin hallittavan ja muutettavan. Tietysti luokkien välinen yhteistyö on välttämätöntä kaikissa vähänkin monimutkaisemmissa ohjelmissa, mutta kytkentöjen kannattaa olla selkeitä ja niitä kannattaa olla mahdollisimman vähän.
    • Harmittomin kytkennän muoto on Swingissä yleensä tapahtumankuuntelu: luokan A olio rekisteröityy tiettyä rajapintaa C edustavana kuuntelijana luokan B oliolle ja odottaa, että B ilmoittaa A:lle uusista tätä kiinnostavista tapahtumista.
    • Kun B joutuu kutsumaan suoraan luokan A metodia, kytkentä on vahvempi ja vähemmän joustava.
  • Käyttöliittymä on hyvä pitää erillään varsinaisesta sovelluslogiikasta, ”ongelmadomainin mallinnuksesta”.
suunnittelumallit design patterns

SUUNNITTELUSTA

Suunnittelumallit(design patterns)
  • Hyväksi havaittuja konsepteja siitä, millainen olioyhteisö soveltuu tietynlaisen ongelman ratkaisuun. (Kuvailevat yleensä muutamia oliota, joilla selkeä vastuunjako. Eivät sinänsä ota kantaa siihen, miten olioita kuvaavat luokat toteutetaan, eivätkä riipu tietystä ohjelmointikielestä.)
    • MVC (Model-View-Controller): sovelluksen datamalli, sen esittäminen käyttäjälle sekä datamallin muokkaaminen on jaettu eri osien vastuulle.
    • Observer: yksi olio ilmoittautuu tarkkailemaan muutoksia toisen olion tilassa. Tarkkailtava (observable) olio ilmoittaa, kun muutoksia tapahtuu.
    • Singleton: luokka, josta voidaan luoda vain yksi olio. Luontimetodi piilotettu, ilmentymän luonti (ja luonnin jälkeen tuon ainoan ilmentymän hakeminen) tapahtuu jollakin staattisella metodilla, kuten getInstance().
    • Factory: luokka, jonka metodien avulla voidaan luoda usean muun luokan ilmentymiä. Paluuarvon tyyppi voi olla jokin rajapinta, jolloin käyttäjä voi luoda erilaisia olioita välittämättä niiden todellisesta luokasta.
    • Composite: suurempi kokonaisuus rakennetaan tietynlaisista rakennus-palikkaolioista, jotka jälleen voivat edustaa jotakin ”palikkarajapintaa” (ja näin ollen olla todelliselta luokaltaan hyvin erilaisia keskenään).
    • ja onhan näitä vielä muitakin
tulostusvirrat

SUUNNITTELUSTA

Tulostusvirrat

perintä

aggregaatio(ohuessa päässä oleva luokka toimii salmiakkikuviopään luokan rakenteellisena osana)

PrintWriter

OutputStream

Writer

BufferedWriter

OutputStreamWriter

FilterOutputStream

Korkeimman tason virroissa ns. decorator-suunnittelumalli. Virrat ovat perusmerkkivirta Writerin aliluokkia (eli lupaavat saman toiminnallisuuden), mutta niiden toiminta perustuu johonkin toiseen, matalamman tason merkkivirta-olioon. Ne lisäävät sen ympärille uutta toiminnallisuutta, ”koristeita”. Nämä virrat luodaan siis aina jonkin olemassa olevan virran pohjalle.

FileOutputStream

FileWriter

tavuvirrat

merkkivirrat

sovelluskehykset software frameworks

SUUNNITTELUSTA

Sovelluskehykset(software frameworks)
  • Valmiiden luokkien (ja lopulta pakkausten) muodostamia kokonaisuuksia, joiden varaan voi rakentaa uusia ohjelmistoja, sekä käyttämällä valmiita komponentteja sellaisenaan että laatimalla niille tarpeen mukaan omia aliluokkia.
  • Tutuin esimerkki sovelluskehyksestä: Swing.
  • Usein sovelluskehysten luokkakokonaisuudet on suunniteltu hyvin, ja niissä nähdään monien suunnittelumallien soveltamista käytäntöön:
    • MVC: jokaisen hiemankin monimutkaisemman Swing-komponentin perustana nämä kolme osaa.
    • Observer: tapahtumankuuntelijat ja kuunneltavat komponentit.
    • Singleton: tietyt Swing-sovelluksen hallintaan ja asetuksiin käytetyt luokat, joilla on aina vain yksi ilmentymä.
    • Factory: esimerkiksi erilaisten reunusten (border) luonti.
    • Composite: komponenttien lisääminen säiliöihin asettelijoiden avulla.
slide74

liikenne ______ jono

para _____ laku

psyki _____ buutti

pelottelu _____ ellistäminen

runsauden _____ kuono

kusi ___ assistentti

slide75

MERKKI

METRI

MOGARI

ATRI

ESINE

SARVI

TUNTI

liikenne ______ jono

para _____ laku

psyki _____ buutti

pelottelu _____ ellistäminen

runsauden _____ kuono

kusi ___ assistentti