Hashmap, feilretting av programmer og repetisjon (kap. 9 i "Rett p? Java" 3. utg.)
M?l
Litt om debugging (feilretting) til Oblig 3, samt bruk av HashMap. For repetisjon av nyttige tema, se Ekstraoppgaver.
Oppgave merket med n?kkelsymbol er plukket ut som spesielt representativ for de viktigste temaene fra ukens forelesning, og alle b?r ha som minimumsm?l ? l?se denne selvstendig.
Oppgaver
-
- Vanlige feilmeldinger n?r du jobber med Oblig 4:
Finn feilene i f?lgende program og foresl? hvordan de kan rettes. Programmet best?r av to klasser: Student, som bare har én objektvariabel: navn; og Gruppe, som har en array med opptil 40 studenter og en konstrukt?r med programkode som illustrerer bruk av klasser og objekter.class Student { String navn; } class Gruppe { Student[] studenter = new Student[40]; // Array med Student-objekter int antStudenter; // Antall plasser i arrayen over som er i bruk public static void main(String[] args) { Gruppe g = new Gruppe(); skrivAntall(); /* Sp?rsm?l: * a) Hvorfor gir linjen over f?lgende feilmelding? Hvordan unng? det? * Gruppe.java:12: non-static method skrivAntall() cannot * be referenced from a static context * skrivAntall(); * ^ * Tips: Du kan lese mer om dette p? side 201 (og 157) i l?reboka. * Problemet skyldes at main-metoden er en "klassemetode", dvs. deklarert * med "static", og derfor kan man ikke referere til "objektvariabler" * eller "objektmetoder" (dvs. variabler og metoder som ikke er deklarert * me n?kkelordet static) direkte fra en static metode uten ? g? * via en peker, f.eks. pekeren g ovenfor. Dette illustrerer * hvorfor vi vanligvis bare har noen f? programsetninger i * main-metoden som bare setter programmet i gang, ved ? kalle * p? andre metoder i programmet. */ } Gruppe() { // b) Den vanligste feilmeldingen i Java er "cannot find symbol". // F?lgende linje gir feilmeldingen vist under. Hva er feil i dette // tilfellet, og hvordan kan vi rette det? antallStudenter = 0; /* Gruppe.java:32: cannot find symbol * symbol : variable antallStudenter * location: class Gruppe * antallStudenter = 0; * ^ * Tips: ?rsaken til feilmeldingen "cannot find symbol" er alltid * at noe ikke er deklarert riktig (f.eks. at det ikke er deklarert * p? riktig sted eller er stavet feil). Feilen er heldigvis * lett ? fikse: se i feilmeldingen hva det var som ikke var * deklarert, og sjekk at du har deklarert det riktig (p? riktig * sted i programmet, og stavet riktig). Du kan finne hva det er * som ikke var riktig deklarert p? 2. linje i feilmeldingen, der * det st?r "symbol". I eksemplet over er problem-symbolet * "variable antallStudenter". Legg ogs? merke til linjenummeret * og posisjonen p? linja som Java-kompilatoren ogs? gir deg. */ // c) F?lgende linje gir "NullPointerException" her. Hvilken setning // har vi glemt ? utf?re f?r dette? (Husk at studenter[] er en array) studenter[antStudenter].navn = "Trine"; antStudenter++; /* Tips: Feilmeldingen NullPointerException skyldes oftest at man har * fors?kt ? bruke prikk-notasjon p? en peker som hadde verdien null. * Det er ikke lov (det gir ingen mening ? si f.eks. null.navn). * * Slik fikser du NullPointerException-feil: * 1. Se i feilmeldingen hvilket linjenummer Java fant feilen i. * 2. Se hvilke pekere i den angitte linjen som kan ha v?rt null * under kj?ring av programmet, s?rlig blandt de som har prikk- * notasjon etter seg, f.eks. hvis linjen inneholder uttrykket: * hyblene[rad][kol].leietager.navn ...s? kan null-pekeren * v?re hyblene[rad][kol] eller hyblene[rad][kol].leietager * 3. Endre programmet slik at pekeren som for?rsaket feilen ikke * kan v?re null n?r programmet kommer til den aktuelle linjen. * Hvis problemet var en peker med prikknotasjon kan du legge * til en if-test p? at pekeren != null f?r den aktuelle linjen. * Det som st?r foran prikken m? alts? v?re noe som peker p? * et allerede-oppretet objekt av riktig klasse (og ikke null), p? * det tidspunktet under programutf?relsen n?r setningen blir utf?rt. * * 4. Hvis linjen har flere pekere og du ikke finner hvilken som ga * NullPointerException kan du legge inn en testutskrift rett f?r * linja, og skrive ut én av dem, f.eks. * System.out.println("test1:" + hyblene[rad][kol].leietager); * Med denne fremgangsm?ten vil du alltid kunne finne nullpekeren. */ // d) Skriv det som mangler for at studenter[1].navn skal bli "Martin". Student s1 = new Student(); s1 _________ = "Martin"; studenter[antStudenter++] = _________ ; // e) Hva mangler her for at if-testen skal kunne gi true? // Tips: Husk at tekster m? sammenlignes med andre tekster. if (studenter[1].equals("Martin")) { System.out.println(true); } // f) Hvorfor gir f?lgende l?kke NullPointerException p? linjen med // System.out..? (anta at eneste kode som er blitt utf?rt n?r // programmet kommer hit er det som st?r i linjene over, med feilene // rettet). Ogs?, hvordan kan betingelsen i f?rste linje endres for ? // unng? NullPointerException? Tips: Tenk arrayplasser og != null. for (int i = 0; i < studenter.length; i++) { Student s2 = studenter[i]; System.out.println(s2.navn); } // g) Finn en annen m?te ? unng? NullPointerException her uten ? endre // f?rste linje under, men ved ? legge til en if-setning inne i l?kka: for (int i = 0; i < studenter.length; i++) { Student s3 = studenter[i]; System.out.println(s3.navn); } // h) Hvorfor gir f?lgende linje i programkoden denne feilmeldingen: // ArrayIndexOutOfBoundsException: 40 studenter[40] = new Student(); // i) Hva vet vi om uttrykket merkert med "___" p? neste linje hvis // linjen gir feilmeldingen "ArrayIndexOutOfBoundsException: -1": s1 = studenter[ ___ ]; // j) Hva er feil her? Feilmeldingen dette gir er: // Gruppe.java:103: incompatible types // found : java.lang.String // required: Student studenter[2] = "Eva"; // k) Hva er feil her? Feilmeldingen er: cannot find symbol // symbol : constructor Student(java.lang.String) Student lars = new Student("Lars"); // l) Hva er feil her? Feilmeldingen dette gir er: // Gruppe.java:114: incompatible types // found : int // required: boolean if (antStudenter = 0) { system.out.println("Ingen student registrert!"); } // m) Hvorfor klager Java ogs? med: "package system does not exist"? // n) N?r vi har rettet alle feilene i a) til m) ovenfor, s? gir fortsatt // if-setningen under NullPointerException. Hvordan unng?r vi det? boolean funnet; for (int i = 0; i < studenter.length; i++) { Student stud = studenter[i]; if (stud.navn.equals("Eva")) { funnet = true; System.out.println(stud.navn); } } // o) L?kken ovenfor stopper ikke n?r navnet "Eva" blir funnet. // Hvordan kan vi f? l?kken til ? stoppe n?r navnet blir funnet? // p) L?kken ovenfor gir ingen melding til bruker n?r navnet ikke blir // funnet. Hvordan kan vi programmere utskrift av en slik melding? // Og hvordan kan vi unng? at Java da skal klage om at "variable // funnet might not have been initialized"? // q) Anta at navnet til studenter[2] er "Eva". Hvorfor endrer ikke // f?lgende kode navnet til studenter[2]? Hvordan kan det ordnes? // (slik at studentobjektet i "ny" overf?res til studenter[2]). Student ny = new Student(); Student studPeker; ny.navn = "Heidi"; studPeker = studenter[2]; studPeker = ny; } void skrivAntall() { System.out.println("Antall studenter: " + antStudenter); } // r) Hvorfor f?r vi feilmeldingen: "<identifier> expected" p? denne linjen: System.out.println("Slutt"); }
Flere debuggings-tips:
B?de feilmeldingene fra kompilatoren (javac) og kj?resystemet til Java (java) gir deg vanligvis linjenummeret der feilen oppsto, og navnet til feilen. Disse opplysningene er nyttige for ? finne og rette feilen. Start alltid med ? rette den f?rste feilen som Java fant.
Tips til kr?llparentes-feil:
En annen type feil som er lett ? gj?re i Java er kr?llparentes-feil, f.eks. ? glemme en kr?llparentes et sted, ha en for mye, en som "vender" feil vei, o.l. Disse problemene gir opphav til mange typer feilmeldinger, bl.a.:- ?class, interface, or enum expected?, ?<identifier> expected?
- ?reached end of file while parsing?, ?'}' expected?,
- ?illegal start of type?, ?illegal start of expression?, ?'else' without 'if'?, m.fl...
- Alltid holde programmet riktig formatert med "innrykk" underveis mens du skriver det: Start et nytt "niv?" med innrykk rett etter hver "{" (?pnings-kr?llparentes) du skriver, dvs. at alle linjene etter en slik kr?llparentes f?r f.eks. 4 flere mellomrom foran enn linjene over ...frem til f?rste "}", da du forminsker ett innrykk-niv?, osv. Alle programmer i disse ukeoppgavene er formatert p? denne m?ten.
- N?r et av de ovennevnte feilene dukker opp, bruk funksjonen i Emacs (eller Eclipse, e.l.) som setter inn riktig innrykk i hele programmet. I Emacs kan det gj?res ved ? markere hele programmet (Ctrl-x h) og velge "Java > Indent Line or Region" fra menyen ?verst i Emacs-vinduet. Da blir det satt riktig innrykk i hele programmet og det blir lett ? se hvor feilen er, ved ? starte fra toppen og fortsette nedover til du finner noe som har havnet p? feil innrykksniv?: Sjekke at alle klasser havnet i "f?rste innrykks-niv?" (dvs. at det ikke st?r noen mellomrom f?r n?kkelordet class), og at f?rste linje i alle metoder havnet i 2. niv? av innrykk (dvs. at det er 4 mellomrom rett f?r n?kkelordet void), og at selve innmaten i metodene er i 3. niv? (har 8 mellomrom foran), osv.
Flere tips til feils?king og -retting finner du i Marit Nybakkens feilmeldinger.pdf.
-
HashMap med akronymer: kap. 9, oppg. 2 (noe modifisert tekst) (side 195)
(a) Et akronym er et initialord (forkortelse) som blir lest og uttalt som et vanlig ord, alts? ikke bokstav for bokstav.Lag et program som leser inn en rekke akronymer og deres tolkning fra fil (du finner en fil med akronymer (og andre forkortelser) p? bokas hjemmeside: akronymer.txt). Legg akronymene og tolkningene i en HashMap med akronymet som n?kkel.Brukeren skal oppgi et akronym til programmet og f? tilbake en eller flere tolkninger av akronymet. Det kan maksimalt v?re 10 tolkninger til hvert akronym. Denne brukerdialogen skal g? i l?kke til brukeren svarer "-".
Tips: Lag en klasse der objekter har f?lgende attributter: akronymet og en String-array med tolkninger, samt antall tolkninger. Pekere til objekter av denne klassen legges i HashMap med akronymet som n?kkel. Det kan v?re lurt ? lage en metode i denne klassen som legger til en ny tolkning, og som holder orden p? hvor mange tolkninger det er i ?yeblikket.
API Application Programming Interface AV Audio/Video AV Authenticity Verification BASH Bourne Again Shell [Unix] EU Europaunionen FN Forente nasjoner ...osv...
(b) Utvid programmet slik at bruker f?r anledning til ? legge til en tolkning dersom den ikke finnes fra f?r.
- Vanlige feilmeldinger n?r du jobber med Oblig 4: