•@Override -- markerer at metoden overstyrer superklassens versjon
•instanceof -- sjekker om et objekt er av en bestemt type
Grensesnitt (interface)
•Comparable: int compareTo(T other) -- negativt/0/positivt
Generics
•class Navn { T felt; ... } -- generisk klasse
•> -- begrenset typeparameter
•Prioritetskø -- generisk kø der T er elementtypen
•Type erasure: T erstattes med Object ved kompilering
•Kan IKKE skrive: new T[10] eller T instanceof ...
Lenkede lister
•Enveis: Node { T data; Node neste; }
•Toveis: Node { T data; Node neste; Node forrige; }
Vanlige feil å unngå
Arv og polymorfisme
•Glemme å kalle super() i subklassens konstruktor når superklassen ikke har parameterlos konstruktor.
•Deklarere instansvariabler som private i superklassen og sa prove å aksessere dem direkte i subklassen -- bruk protected eller get-metoder.
•Forveksle abstrakt klasse med grensesnitt. Abstrakte klasser kan ha tilstand (instansvariabler) og implementerte metoder.
•Glemme @Override-annotasjonen. Den er ikke pabudt, men fanger skrivefeil i metodenavn ved kompilering.
Grensesnitt (interface)
•Glemme å implementere alle metoder fra grensesnittet -- da kompilerer ikke klassen (med mindre den er abstrakt).
•Forveksle interface med abstrakt klasse. Interface kan ikke ha instansvariabler (kun konstanter).
•Skrive 'extends' i stedet for 'implements' når en klasse skal implementere et grensesnitt.
•Glemme å deklarere metoder i grensesnittet som public (de er implisitt public, men det er god praksis å skrive det).
Generics
•Prove å opprette array med generisk type: new T[10] er ikke lovlig i Java. Bruk Object-array og cast, eller bruk ArrayList.
•Glemme typeparameteren når du instansierer: Prioritetskø ko = new Prioritetskø<>(); (ikke bare new Prioritetskø()).
Eksamenstips
Arv og polymorfisme
•Eksamen starter nesten alltid med 'tegn klassehierarkiet'. Bruk piler fra subklasse til superklasse, og stiplet linje til interface.
•Når oppgaven sier 'det er ingen forskjell på klassene annet enn navnet' (som V2021), betyr det at subklassene er tomme bortsett fra konstruktoren.
•Vis at du forstår polymorfisme ved å bruke superklassetypen i parametere og returtyper.
•function function function toString() { [native code] }() { [native code] }() { [native code] }() kreves ofte i ALLE klasser (V2022). Bruk super.function function function toString() { [native code] }() { [native code] }() { [native code] }() i subklassene for å få med arvede felt -- og marker den konkrete typen, f.eks. 'Suite: ...'.
•Felt som skal være konstante får modifikatoren final og settes i konstruktoren. Liste-pekere (neste/forrige) er IKKE final.
Grensesnitt (interface)
•Oppgaven beskriver ofte en egenskap som 'noen klasser har' -- dette signaliserer et interface (f.eks. 'god utsikt' i V2021, 'MidtgangSete' i V2018).
•Comparable dukker opp nesten hvert år. Skriv compareTo riktig: returner this.felt - annen.felt for stigende rekkefølge.
•Når du tegner klassehierarki, bruk stiplet linje med pil for interface-implementering og heltrukket for arv.
Generics
•V2018 ba eksplisitt om generisk prioritetskø. Skriv Node som indre klasse med data av type T og en int prioritet.
•Comparable: int compareTo(T other) -> negativt/0/positivt
•Iterable: Iterator iterator()
•Iterator: boolean hasNext(), T next()
•Runnable: void run()
Flertrading
•implements Runnable -> public void run() -> new Thread(r).start()
•Lock laas = new ReentrantLock(); Condition c = laas.newCondition();
•Inorder: venstre -> rot -> høyre (gir sortert for BST)
•
Bruke == i stedet for compareTo() for å sammenligne generiske objekter.
•Blande primitiv type (int, double) med generics. Bruk wrapper-klasser (Integer, Double) i stedet.
Lenkede lister
•Glemme å oppdatere både neste- og forrige-peker i toveis lenket liste. Alle fire pekere må settes riktig ved innsetting.
•Glemme spesialtilfellet: innsetting i tom liste, innsetting først, eller innsetting sist.
•Ikke nullstille neste/forrige-pekerne på noder som tas ut av listen. Dette kan forårsake uventede effekter.
•Miste referansen til resten av listen ved innsetting (glemme å sette ny.neste for du overtar p.neste).
•Bruke egne Node-objekter når oppgaven sier at dataobjektene SELV har neste/forrige-pekere. Da trekker sensor.
•Glemme å telle antall treff for du oppretter en typet array -- du må vite lengden for new T[antall].
Rekursjon
•Glemme basistilfellet -- fører til uendelig rekursjon og StackOverflowError.
•I graftraversering: glemme å holde styr på besøkte noder, slik at rekursjonen går i sirkel.
•Returnere feil verdi fra det rekursive kallet. Test med enkle eksempler for å verifisere logikken.
•I V2021 oppgave 4: glemme at komFra-parameteren er nødvendig for å stoppe uendelig rekursjon i trestrukturer.
Unntakshandtering
•Arve fra Exception når oppgaven ber om RuntimeException-subklasse. Les oppgaveteksten nøyaktig.
•Glemme å kalle super(melding) i konstruktoren til det egendefinerte unntaket.
•Fange for brede unntak (catch Exception) i stedet for den spesifikke unntakstypen.
•Ikke validere input i konstruktorer og set-metoder -- dette er nettopp det oppgave 2f i V2021 handler om.
Flertrading og synkronisering
•Bruke synchronized/wait/notify når oppgaven eksplisitt ber om ReentrantLock og Condition (V2024).
•Glemme finally-blokken: lås.unlock() må ligge i finally slik at lasen alltid slippes.
•Bruke if i stedet for while rundt await(): betingelsen må sjekkes på nytt etter at traden vekkes.
•Kalle run() direkte i stedet for start()/new Thread(...).start(). Da får du ingen parallellitet.
•Glemme try-catch rundt await() og Thread.sleep() -- begge kaster sjekket InterruptedException.
Simulering og hovedprogram
•Glemme at simulatoren må sette globaltid for handling() kalles -- ellers er tidsberegningen feil.
•Ikke sette aktiviteten tilbake i køn etter handling(). Da simuleres den bare en gang.
•I Skog-konstruktoren: glemme å legge stiene til i kryssenes datalister når de opprettes.
•Bruke Trekk.trekkInt feil: husk at begge grensene er inklusive.
Datastrukturer: stakker, køer og trær
•Forveksle stakk (LIFO) og ko (FIFO). Stakk: inn og ut fra toppen. Ko: inn bak, ut foran.
•Glemme å oppdatere 'siste'-pekeren i ko ved innsetting og uttak.
•I binært søketre: glemme å returnere node-referansen etter rekursivt kall (nødvendig for å koble treet riktig).
•Blande preorder, inorder og postorder. Husk: 'in' betyr at roten besookes mellom barna.
•Når oppgaven sier 'uten bruk av Javas bibliotek', må du implementere alt fra bunnen av -- ingen ArrayList, HashMap osv.
•Generics kombineres ofte med Comparable: du trenger T extends Comparable for å sortere/prioritere elementer.
Lenkede lister
•Den største oppgaven (30-40%) er en beholderklasse med dobbeltlenket liste: leggTil (bak), taUt (gitt referanse), finnOgTaUt (gitt id), leggTilForan og en iterator. Oev på alle disse.
•Sensor krever at du IKKE bruker egne Node-objekter: liste-pekerne (neste/forrige) ligger i selve dataobjektene (f.eks. Fly/Vogn/Rom). Bruk disse direkte.
•En egen metode skal ofte returnere en typet array (f.eks. PassasjerFly[]): tell først antall treff med instanceof i en runde, opprett arrayen, og fyll den i en ny runde med cast.
•Sensor advarer mot løsninger som 'bærer preg av å være hentet fra andre programmer'. Tilpass koden til akkurat denne listen og vis at du forstår referansemanipuleringen.
•Prioritetskøn (sortert innsetting) kommer også. Både innsetting fremfra og bakfra er gyldig -- folg oppgaveteksten. Tegn alltid datastrukturen for du koder.
Rekursjon
•Identifiser basistilfellet først. For rekursjon langs en lenket liste er basistilfellet typisk at neste-pekeren er null (eller at gjeldende node er null).
•Når oppgaven ber om rekursiv metode, er det ALLTID en grunn. Bruk ikke løkker som erstatning -- sensor sjekker akkurat dette.
•Det er som regel lov med en rekursiv HJELPEMETODE: en offentlig metode starter rekursjonen i første objekt og håndterer tom liste, en privat metode gjør selve rekursjonen.
•Rekursjon gir mange poeng for relativt kort kode (8-20%). Oev på de tre variantene: gjennom liste, i graf (med komFra), og i tre.
Unntakshandtering
•Et eget unntak (f.eks. FeilSporvidde) bes om nesten hvert år i oppgave 4: en kort klasse som arver RuntimeException (eller Exception) med konstruktor som tar String og kaller super(). Ofte bare 3-5 linjer.
•Et vanlig mønster: skriv først en ITERATIV metode som går gjennom listen og kaster unntaket ved avvik, og deretter en REKURSIV versjon av samme sjekk (egen deloppgave). Begge gir poeng.
•En 'leggTilSikker'-variant kombinerer leggTil med validering: sjekk at det nye objektet passer (samme sporvidde e.l.), ellers kast unntaket.
•try-catch rundt Thread.sleep() og await()/wait() er obligatorisk -- de kaster sjekket InterruptedException.
Flertrading og synkronisering
•Trad-oppgaven er alltid siste oppgave og gir 20-36% av poengene. Den bygger på beholderen og klassene fra oppgave 3.
•Fast oppskrift: to Runnable-tråder (produsent + konsument) + en monitor med ArrayList, Lock og Condition. Oev på denne malen.
•Skriv ALLE monitor-metoder etter samme mål: lock() først, finally { unlock() } sist, await() i while-løkke, signal() ved endring.
•hentNeste() skal returnere null når alle produsenter er ferdige OG beholderen er tom -- da kan konsumenten terminere.
•Oppgaven sier nesten alltid at du IKKE skal skrive hovedprogrammet som starter tradene -- bare trådklassene og monitoren.
Simulering og hovedprogram
•Main-metoden (V2021 oppgave 2e, 9%) er enkel å skrive og gir mange poeng. Ikke hopp over den!
•Folg oppgavetekstens oppskrift punkt for punkt. Den beskriver nøyaktig hva main skal gjøre.
•Simulatoren fra V2021 er et elegant designmonster. Forstå det, for det kan komme lignende mønstre i fremtiden.
Datastrukturer: stakker, køer og trær
•Prioritetskøn på eksamen er egentlig en sortert ko. Forstår du ko-operasjoner, klarer du også prioritetskøn.
•Tegn alltid datastrukturen for du implementerer. Spesielt for lenkede strukturer er det lett å miste pekere.
•Stakk og ko implementeres ofte som indre del av større oppgaver. Vit hvordan de fungerer, sa kan du bruke dem som byggeklosser.