Helsingin yliopisto > Tietojenkäsittelytieteen laitos > Ohjelmointitekniikka (Java) -opintojakso keväällä 2005
public class Esimerkki<E> { //Jotain koodia... }Tässä esimerkissä E on tyyppiparametri. Kun tälläisestä geneerisestä luokasta luodaan instassi määritellään samalla konkreettisesti tyyppiparametrin arvo. Tätä tyyppiparametriä voidaan käyttää esimerkiksi metodikutsujen argumenteissa ja paluuarvoissa, vaikkapa tähän tapaan:
public E metodi(E parametri) { //Jotain Koodia... return parametri; }Geneerisyyden etu on koodin siisteytymisessä ja lisääntyneessä turvallisuudessa. Esimerkiksi Javan kokoelmaluokkia käytettäessä oli ennen tavanomaista joutua tekemään eksplisiittinen tyyppimuunnos koska kokoelmissa saattoi olla minkä tyyppisiä olioita tahansa eikä kääntäjä voinut tietää mitä:
String merkkijono = (String)iteraattori.next();Paitsi että tyyppimuunnosten kirjoittaminen joka kerta on kankeaa se on myös virhealtista, koska virheellinen tyyppimuunnos huomataan vasta ajon aikana. Geneerisiä luokkia käytettäessä kääntäjä tietää mitä tyyppiä palautusarvo on eikä sitä tarvitse siksi erikseen mainita. Lisäksi kääntäjä pystyy varoittamaan virheistä jo ohjelmaa käännettäessä. Uusi versio geneerisyyttä käytettäessä näyttäisi tältä:
String merkkijono = iteraattori.next();Myös muutamat muut Javan uuden version ominaisuudet tukevat geneeristen luokkien käyttöä. Esimerkiksi uusi for-each-silmukka helpottaa kokoelmien läpikäyntiä:
for (String merkkijono : jokinKokoelma) { //Jotain koodia... }Toinen geneerisyyden yhteydessä usein käytetty uusi ominaisuus on Autoboxing, mikä tarkoittaa sitä että alkeistyyppiset muuttujat muutetaan automaattisesti vastaaviksi luokiksi tarvittaessa ja toisinpäin. Esimerkiksi näin:
int i = new Integer(1);Javan geneerisyys on puhtaasti käännöaikainen ominaisuus. Ne virheet mitä havaitaan havaitaan kääntämisen aikana eikä tyyppitietoutta säilytetä enää ajon aikana.
import java.util.*; public class Sanalaskin { public static void main(String[] args) { Scanner sc = new Scanner(System.in); TreeMap<String,Integer> tm = new TreeMap<String,Integer>(); while (sc.hasNext()) { String word = sc.next(); Integer oldValue = tm.get(word); tm.put(word,oldValue == null ? 1 : ++oldValue); } for (String word : tm.keySet()) System.out.printf("%s %d\n",word,tm.get(word)); } }
Tässä ratkaisussa java.util-paketin työkaluja ja Javan uusia ominaisuuksia on käytetty seuraavasti:
Syöte luetaan Scanner
-luokan avulla.
Sanat ja niiden esiintymistiheys talletetaan TreeMap
-luokan avulla,
jolloin sanat ovat automaattisesti aakkosjärjestyksessä.
Käytetään uutta geneeristä TreeMap
-luokkaa.
Käytetään Autoboxing-ominaisuutta.
Käytetään uutta tulostuksen muotoilua.
Käytetään for-each-silmukkaa sanojen läpikäyntiin lopussa.
Eri kohdista sai pisteitä seuraavasti:
1 piste: Selitettiin mitä geneerisyys on ja geneerisyyden keskeiset piirteet.
1 piste: Selitettiin miksi ja miten geneerisyyttä käytetään.
1 piste: Esiteltiin geneerisyyteen liittyviä muita Javan ominaisuuksia.
1 piste: Käytettiin apuna edellämainittujen kohtien selittämisessä koodiesimerkkejä.
Jokerimerkkien käsittelyä ei vaadittu eikä siitä saanut pisteitä.
Jokaisesta näistä kohdista saadun pisteen saattoi menettää kokonaan tai osittain seuraavin perustein:
-0 pistettä: Kohdan selityksessä on vain pieniä ja suhteellisen merkityksettömiä tai kysymykseen liittymättömiä epätarkkuuksia tai puutteita.
-½ pistettä: Kohdan selityksessä on joitain kohtia jotka ovat väärin tai ilmaistu puutteellisesti tai epäselvästi. Perusajatus on kuitenkin ymmärretty.
-1 piste: Kohtaa ei käsitelty tai käsiteltiin väärin.
Pyöristykset tehtiin ylöspäin.
Itse kysytynlaisen ohjelman laatimisen tulisi tässä vaiheessa olla triviaalia, joten siitä ei itsessään saanut pisteitä. Jos kuvattu algoritmi oli kuitenkin väärin tai mitään siihen viittaavaakaan ei esitetty siitä menetti 1 pisteen.
Tehtävässä sai pisteitä java.util-paketin työkalujen ja Javan uusien ominaisuuksien käytöstä tehtävän ratkaisuun. Sekä työkalun tai ominaisuuden käytön selittäminen että koodi tai pseudokoodi hyväksyttiin. Syntaksivirheistä tai metodien ja luokkien nimien väärin muistamisesta ei pisteitä vähennetty jos vastauksesta ilmeni että asia oltiin ymmärretty oikein.
Pisteitä sai työkalujen tai tekniikoiden käytöstä seuraavasti:
1 piste:Käytettiin jotain Map
-rajapinnan
toteuttavaa kokoelmaluokkaa esiintyneiden sanojen ja vastaavan
esiintymistiheyden tallentamiseen.
½ pistettä:Käytettiin Vector
-luokkaa tai vastaavaa
esiintyneiden sanojen tallennukseen. Tästä ei saanut pisteitä jos sai jo pisteen
edellisestä kohdasta.
½ pistettä:Käytettiin Collections
-
tai Arrays
-luokan välineitä järjestämiseen.
½ pistettä:Käytettiin kokoelmaluokkaa joka säilyttää järjestyksen automaattisesti.
½ pistettä:Käytettiin soveltuvissa kohdin luokkien uusia geneerisiä versioita.
½ pistettä:Käytettiin Scanner
-luokkaa syötteen
lukemiseen.
½ pistettä:Käytettiin muotoiltua tulostamista.
½ pistettä:Käytettiin for-each-rakennetta silmukassa.
½ pistettä:Käytettiin Autoboxing-ominaisuutta.
Huomaa, että listan pisteiden summa on enemmän kuin 3. Ylijäävät pisteet jätettiin huomioimatta. Kaikkia listan tekniikoita ei siis tarvinnut käyttää yltääkseen täysiin pisteisiin. Pyöristykset tehtiin alaspäin.
Pisteet jäivät saamatta kohdasta, jossa tekniikkaa oli käytetty väärin tai sen käyttö oli selitetty epäselvästi tai puutteellisesti. Pelkästä tekniikan mainitsemisesta ei saanut pisteitä vaan siihen vaadittiin tekniikan kytkemistä ratkaisuun.
Yhteispisteiden keskiarvoksi muodostui 4,4.
yhteispisteet | vastausten lukumäärä |
---|---|
7 | 6 |
6 | 13 |
5 | 9 |
4 | 13 |
3 | 8 |
2 | 6 |
1 | 2 |
0 | 1 |