- Ohj2, luennot 15-16, 8.4.-9.4.2005
- Kertaus: taulukot ja merkkijonot
- Dynaamisuus
- Materiaali
- staattinen vs. dynaaminen muistinkäyttö
- staattista (tai pinomuistia) käytössä perustyyppejä olevilla muuttujilla ja viitteillä (mutta ei viitteiden osoittamilla olioilla!), muisti vapautetaan muuttujan lohkosta poistuttaessa
- kaikki oliot sijaitsevat dynaamisessa (tai keko) muistissa, varaus new:lla, vapautus muistinsiivouksessa, kun viitteitä olioon ei enää ole
- Muistinsiivous (roskienkeruu, garbage collection)
- Idea: kun johonkin olioon ei ole enää viitteitä (tai viitteet asetettu null-arvoon), se voidaan tuhota
- Ohjelmoija ei yleensä itse päätä muistinsiivouksen ajankohdasta, virtuaalikone vastaa (tosin System-luokka sisältää gc-metodin, jolla roskienkeruuta voi pyytää)
- Kun olio päätyy muistinsiivoukseen, ennen sen vapautusta kutsutaan finalize()-metodia
- Huom! Muistinsiivousta ei välttämättä ajeta ohjelman ollessa käynnissä, joten finalize()-metodiin ei yleensä voi luottaa. finalize()-metodia ei myöskään ole suositeltavaa kutsua itse, koska tällöin resursseja saatetaan vapauttaa moneen kertaan.
- Käytännössä finalizea tarvitaan, jos olio varaa muistia jonkin natiivimetodin kautta (esim. kutsuu C-kielistä aliohjelmaa)
- Lisätietoa: Antti-Juhani Kaijanaho: Muistinhallinta siivousmenetelmien avulla (LuK-tutkielma)
- [ http://www.mit.jyu.fi/opetus/opinnayte/LuK/Muistinsiivous/LuK.pdf ]
- dynaaminen muisti on välttämättömyys kaikille kehittyneemmille tietorakenteille!
- Varoituksia:
- Vaikka käytössä on roskienkeruu, mutkikkaassa oliohierarkiassa olevien viitteiden ylläpito voi olla yllättävän hankalaa
- Vaikka Java hoitaakin muistin vapautuksen automaattisesti, muiden järjestelmien resurssien (esim. tiedostokahvat, tietokantayhteydet, natiivikoodin varaama muisti) vapautuksesta on huolehdittava itse!
- Automatiikasta voi olla myös haittaa, koska ei ole standardia 'resurssien vapautinta', jota voisi kutsua turvallisesti itse.
- C++:ssa resurssit vapautetaan, kun olio tuhotaan, jolloin kaikki siivoustoimenpiteet kirjoitetaan destruktoriin - javassa vastaava toiminto riippuu aina luokan määrityksistä
- Javan tietorakenteet
- ks. java collections framework guide
- [ http://java.sun.com/j2se/1.4.2/docs/guide/collections/ ]
- Perustietorakenteista
- Lista, jono, pino, puu, verkko
- Huom. ovat abstrakteja tietotyyppejä, eli sisältävät vaatimukset operaatioista, joilla niitä voidaan käyttää
- Toteutustapoja on monia. Esim lista, jono ja pino voidaan kaikki toteuttaa 2-suuntaisena linkitettynä listana.
- Huom. muista, että tietorakenteet (taulukot mukaanlukien) ei luo automaattisesti sisätöä rakenteeseen. Ne sisältävät vain viitteitä, joiden arvo on alussa null.
- Vanhat: Vector ja Hashtable (säieturvallisia)
- Uudet (java 1.2:sta alkaen, java collections framework)
- ArrayList, Set, Map ym...
- Yhtenäiset rajapinnat lähes kaikille javan tietorakenteille
- Java 1.4:ssä ja vanhemmassa sisältävät Object-viitteitä
- Mahdollistaa "minkä tahansa" olioiden tallettamisen taulukkoon
- Seuraus: PALJON typecasteja, kun taulukon alkioita halutaan käsitellä
- Erityisen hankalaa on, jos taulukko sisältää lukuja tai muita perustyyppejä: täytyy tallettaa oliokääreiden avulla (Integer ym)
- Java 1.5:ssä käsittely huomattavasti suoraviivaisempaa, mutta suurin osa Java-koodista lienee edelleen kirjoitettu vanhalla tavalla.
- Perusrajapintoja: Iteraattorit, luettelijat ja vertailijat
- huom. olioiden kopiointi (clone)
- Object-luokassa määritellään suojattuna clone-metodi, joka vastaa olion kopioinnista
- clone-metodin oletustoteutus tekee 'pintakopioinnin': luo uuden olion, jonka attribuutit osoittavat samoihin olioihin kuin alkuperäisellä
- Jos luokka on merkitty toteuttamaan Cloneable-rajapinta, se 'lupaa' vastata kloonauksesta
- Kopioitaessa olio on yleensä tehtävä kopiot myös sen attribuuteista (tätä kutsutaan myös syväkopioinniksi)
- Poikkeus: immutable-oliot (arvo ei voi muuttua), kuten String, Integer...
- Toinen poikkeus: kun oliot osoittavat loogisesti _samaan_ (ei samanlaiseen) olioon
- Collections-luokassa apufunktioita kokoelmien käsittelyyn (vrt. Arrays)
- Esimerkit:
- gko: eroamistehtävä
- [ http://people.cc.jyu.fi/~minurmin/gko/nayta.php?type=demo&num=5 ]
- monisteen dyna-hakemisto
- Dynaaminen taulukko
- Käyttäjän kannalta taulukko "muuttaa kokoaan", koska vain osa siitä on kerrallaan käytössä
- Huom. entä dynaaminen koon kasvatus? tässä vaiheessa kurssia kierretään ongelma esim. Vectorin käytöllä
- VectorMalli
- Huom. iteraattorin käyttö alkioiden läpikäyntiin
- ArrayListMalli
- AlgoritmiMalli
- Asunnon "kloonaus" ja iterointi
- Java (1.)5
- Ks. wiklan javakurssi ja Sunin tutoriaaliit
- [ http://www.cs.helsinki.fi/u/wikla/OTJ/K05/Sisalto/ ]
- Java 5:n uudet ominaisuudet
- Geneeriset tyypit
- Ei enää typecasteja kokoelmien käsittelyssä!
- Käännösaikainen tyyppitarkistus
- Kuitenkin: oleellisesti C++:n templateja yksinkertaisempia (ei omaa 'funktionaalista alikieltä', kuten C++:ssa)
- foreach
- Yksinkertaistaa iteraattorien käsittelyä
- autoboxing
- läpinäkyvä muunnos Integer <-> int yms
- luetellut tyypit
- kuten c++:n enum
- Myös Javan lueteltu tyyppi on luokka, joten siihen voidaan lisätä attribuutteja ja metodeja kuten muihinkin luokkiin
- vaihteleva määrä funktion parametreja
- mahdollistaa c-tyylisen printf:n määrittelyn
- staattiset importit
- Mahdollistaa vakioiden "importoinnin" luokista samaan tapaan kuin aiemmissa versiossa on voinut "importoida" luokkia paketeista
- Esim. Math.PI:n sijaan voidaan kirjoitaa pelkästään PI, kun luokan alussa merkitään import Math.PI;
- annotoinnit
- metadataa koodiin, mahdollistaa yhteistoiminnen CASE-välineiden kanssa
- esim. koodin generoinnin ohjausta tai graafisen käyttöliittymän suunnittelua varten
- Esimerkit:
- geneeriset versiot dyna-tietorakenteista