Kysymyksiä ja vastauksia

Julkaistu

1. Täytyykö Comparable<T>-rajapinta toteuttaa omassa listassa?

Ei. Toteutus tarvittaisiin, jos tavoitteena olisi verrata keskenään omia listoja. Comparable<T>-rajapinnan tehtävänä on mahdollistaa listan alkioiden vertailu. Rajapinta toteutetaan Dokumentti-luokassa, jotta oman listan lisää-metodissa voidaan vertailla keskenään listalle lisättävää dokumenttia ja listalle säilöttyjä dokumentteja.

2. Miten oman listan lisää-metodi toteutetaan?

Metodissa pitää hakea lisäyspaikka uudelle alkiolle. Lisäyspaikan päättely tehdään silmukkaa ja Comparable<T>-rajapinnan compareTo-metodia käyttäen. Silmukassa vertaillaan nykyistä listan alkiota lisättävään alkioon (tai päinvastoin) compareTo-metodilla, kunnes lisäyspaikka löytyy.

CompareTo-metodia ei voi kutsua suoraan metodin parametrin tai listan alkion kautta, koska ne ovat E-tyyppiä. Tästä syystä olioon, jonka kautta metodin kutsu tehdään, on lisättävä Comparable-tyyppinen viite:

int ind = 0;
while (...) {
   // Asetetaan nykyiseen alkioon compareTo-metodiin perustuvan
   // vertailun mahdollistava apuviite. Tämä on kääntäjän mielestä
   // vaarallista, koska kieliopillisesti ei voida päätellä onko
   // lisättävän olion luokalla Comparable-toteutus. Kääntäjän
   // mutinat estetään annotaatiolla.
   Comparable nykyinen = (Comparable)get(ind);
   ...
   if (nykyinen.compareTo(uusi)...) {
   ...
}

Lisäyksessä on erikoistapaus: lisäyspaikka on listan loppu, jos lisättävä alkio on kaikkia listan alkioita suurempi.

Uusi alkio lisätään kaikkien samanarvoisten alkioiden jälkeen. Näin ensimmäisenä listalle lisätty alkio on listalla ennen kaikkia muita samanarvoisia alkoita. Toisena lisätty samanarvoinen alkio on heti ensimmäisen samanarvoisen alkion jälkeen ja kaikki muut samanarvoiset alkiot seuraavat tätä alkiota ja niin edelleen. Kaikki aiemmin lisätyt samanarvoiset alkiot ovat ennen viimeisenä lisättyä samanarvoista alkiota.

3. Pitääkö oman listan lisää-metodissa lajitella?

Kyllä ja ei. Kyllä, koska lisää-metodi on itsessään lajittelualgoritmi. Ei, koska metodissa ei saa käyttää mitään muuta tapaa lajitteluun. Esimerkiksi Javan Collections-luokan lajittelumetodia ei saa kutsua.

4. Mitä tarkoittaa MALFORMED?

WETO tulostaa virheilmoituksen MALFORMED, jos zip-paketin purkaminen ei onnistu.

Harjoitustyössä näin voi tapahtua lähinnä, kun pakkaushakemiston tai jonkin tiedoston nimessä on skandinaavisen aakkosen tapainen perus-ASCII-merkistöön kuulumaton merkki ja paketti on luotu Windows-järjestelmässä. WETO pysäyttää tällöin testauksen jo ennen sen alkua käyttöjärjestelmätasoisen virheen vuoksi, koska Windowsissa harmiton merkki on ”räjähtänyt” zip-pakettia Linux-järjestelmässä purettaessa siten, että hakemiston tai tiedoston nimeen on tullut laiton merkki.

Zip-paketin tarkistus ennen sen purkua ei ole mahdollista opettajan toimesta.

5. Miksi ohjelmani kaatuu WETO-testissä?

Lue aluksi testin kuvaus; siitä voi päätellä paljon. Jos ongelma ei selviä koodia lukemalla, niin voit toistaa testin sen kuvauksen perusteella omassa testiluokassa. NetBeans tai vastaava ohjelma tarjoaa graafisen debuggerin, jolla on helpompaa seurata ohjelman toimintaa kuin tulostuslauseilla. Opettaja auttaa, jos ongelma ei selviä oman testauksen avulla. Ohjelmasi voi kaatua yllättävästi, jos palautat koodin testauskohtaan, jossa oletetaan edellisen kohdan testit onnistuneiksi.

Tavallista yllättävämpiä ongelmia on tapahtunut muun muassa seuraavista syistä: luokan otsikkoon on lisätty ylimääräisiä geneerisiä parametreja, abstraktin luokka on palautettu testausosioon, jossa kyseinen luokka oletetaan konkreettiseksi, versionhallinnan haara on nimetty skandinaavisia kirjaimia käyttäen.

6. Missä luokassa latauksen tulisi tapahtua?

Latausmetodin paras paikka on Kokoelma-luokka, koska myös reset-komento lataa. Voit välittää kokoelma- ja sulkusanatiedostojen nimet kokoelmalle rakentajan parametrien kautta.

7. Miksi siivoa-metodi ei toimi?

Tarkista aluksi, että siivous tehdään tehtävänannossa ja kommenteissa kerrotussa järjestyksessä.

String-luokan replaceAll-metodin ensimmäinen parametri on säännöllinen ilmaus. Käytä tätä metodia vain, jos tiedät mitä säännölliset ilmaukset ovat.

String-luokan replace-metodi korvaa osamerkkijonoja ”suoraan” eli ilman säännöllisenä ilmauksena määriteltyä ”hahmoa”. Metodi poistaa löytämänsä esiintymät, kun toisen parametrin arvoksi annetaan tyhjä merkkijono ””. Sulkusanaa on edellettävä ja seurattava yksi välilyönti, kun replace-metodia käytetään sulkusanojen poistoon, jotta ei poistettaisi vahingossa avainten osia. Tekstin alussa tai lopussa olevan sulkusanan voi poistaa vastaavasti startsWith– tai endsWith-metodeilla, joita käytettäessä on muistettava edelleen estää avainten osien poisto välilyönnin avulla. Huomaa, että välimerkit ja sulkusanat voi poistaa myös ilman edellä mainittuja metodeja tekemällä hieman enemmän oma koodia.

8. Miten poistan tiedoston versionhallinnasta?

Ota yhteyttä opettajaan, jos jonkin tiedoston poisto on ehdottoman tärkeää. Älä tee muussa tapauksessa mitään (99,9 % tapauksista). Versionhallinta osaa sopeutua itse tilanteeseen, kun jokin tiedosto poistetaan projektista tai nimetään uudelleen. Poistettua tiedostoa ei tarvitse eikä oikeastaan pidä poistaa versionhallinnasta manuaalisesti, koska versionhallinnan tehtävänä on muistaa myös poistetut tiedostot. Älä poista tiedostoja etävarastosta Tuni-Gitlabin kautta. Kaikki muutokset tehdään paikallisesti, versioidaan ja ladataan etävarastoon, jotta asiat eivät monimutkaistuisi turhaan.

9. Pitääkö päivämäärä muotoilla?

Päivämäärän tiedot voi tulostaa ilman muotoilijaluokkaa. Päivämäärän järjestysluvut saa luettua helposti LocalDate-luokan aksessoreilla getDayOfMonth, getMonthValue ja getYear.

10. Mikä on virhe 137?

WETOn virhekoodi 137 tarkoittaa, että WETO on pysäyttänyt ikuiseen silmukkaan joutuneen ohjelman suorituksen. Näin voi käydä esimerkiksi oman listan lisää-metodissa, kun lisäys tehdään silmukassa ja silmukkaa jatketaan lisäyksen jälkeen, jolloin listalle lisätään toistuvasti, kunnes aika loppu.

11. .git-hakemisto ei näy?

.git-hakemisto on aina kätketty versionhallinnan toimesta. Hakemisto ei näy graafisessa tiedostonhallinnassa eikä komentoikkunan listauksessa ilman eri toimia. Kaikki on siksi kunnossa, kun hakemisto on kätketty. Voit aina testata onko hakemistossa tai sen ylihakemistossa .git  antamalla jonkin Git-komennon. Jos esimerkiksi log-komento tulostaa versiohistorian, on versionhallinta ja sitä myötä .git-hakemisto kunnossa.

12. Miksi testi 4.7 ei onnistu, vaikka luon listaolion?

Tarkista, että liität olion attribuuttiin. Jos olio liitetään paikalliseen viitteeseen, katoaa viite ja samalla olio, kun rakentajasta poistutaan. Esimerkiksi lausetta:

OmaLista<Dokumentti> dokumentit = new OmaLista<Dokumentti>();

käytettäessä käy näin. Java-kääntäjä ei valita siitä, että paikallisen muuttujan tunnus on sama kuin attribuutin tunnus. Tunnuksen peittämiseen tutustuttiin edellisen kurssin materiaalissa ja myös harjoituksissa.

13. Ovatko tyyppimuunnokset sallittuja lajittele-metodia kutsuttaessa?

Kyllä. OmaLista-luokan lajittele-metodin on oltava sovellusriippumaton. Siinä ei saa käyttää esimerkiksi Dokumentti-tunnusta. Toisaalta tätä metodia kokoelman metodista kutsuttaessa voi olla pakko mainita tyyppejä. Kutsussa saa siten käyttää tyyppejä ja niiden muunnoksia täysin vapaasti.

14. Kuinka estää uutisen lisääminen vitsikokoelmaan?

Tarkista voiko add-komennon parametriksi annetusta merkkijonosta luoda uutisen, kun kokoelma koostuu vitseistä. Tulosta virheilmoitus ja keskeytä lisäys, jos uutisen luominen onnistuu.

15. Miksi ohjelmani kaatuu WETOssa, vaikka syötteiden lukeminen toimii omalla koneellani?

Tarkista ettei standardisyötevirtaan System.in ole liitetetty yhtä useampia Scanner-olioita. Java ei takaa mitä tapahtuu, kun tiettyyn tietovirtaan liitetään useampia lukijoita. Scanner-olio sekaantuu valitettavasti vasta, kun syötteitä tulee nopeampaan tahtiin esimerkiksi, kun ohjelmaa testataan uudelleenohjauksella WETOssa. Ongelman pitäisi ilmetä myös omalla koneella uudelleenohjausta käytettäessä. Esimerkiksi komennon:

java Oope2HT ..\esimerkit\jokes_oldies.txt ..\esimerkit\stop_words.txt < ..\esimerkit\input_brain_check.txt

pitäisi aiheuttaa poikkeus, kun syötevirrasta luetaan usealla lukijalla. Edellinen komento on annettu Windows järjestelmässä, jossa esimerkkitiedostot ovat ajohakemiston ylihakemiston esimerkit-alihakemistossa.

Ongelma on todennäköisesti helposti korjattavissa, jos luet syötteet pääsilmukassa. Tällöin riittää, että siirrät olion luonnin ennen silmukkaa. Esimerkiksi:

// Pääsilmukka.
do {
   // Tällä luetaan syötteet.
   Scanner lukija = new Scanner(System.in);

   // Tulostetaan kehote ja luetaan komentorivi.
   System.out.println(KEHOTE);
   String komentorivi = lukija.nextLine();

-->

// Tällä luetaan syötteet.
Scanner lukija = new Scanner(System.in);

// Pääsilmukka.
do {
   // Tulostetaan kehote ja luetaan komentorivi.
   System.out.println(KEHOTE);
   String komentorivi = lukija.nextLine();

Korvaa paikallinen Scanner-muuttuja kätketyllä attribuutilla, jos pääsilmukasta kutsutaan erillistä metodia, jossa syötteet luetaan.