OOPfk-tentaplugg

From wiki.3h.se

Jump to: navigation, search

Chalmers Tekniska Högskola, Informationsteknik årskurs 1, Objektorienterad programvaruutveckling fk.


Wiki ämnad att genom en kollektiv insats sammanfatta, förklara, utveckla och diskutera kursens innehåll, med panikpräglade förhoppningar om författarnas välgång på den nalkande tentan.

Innehållet redigeras med fördel så att resultatet bibehåller en lättläslig struktur, med fokus på effektivt och tidsoptimalt intagande av kunskap för teknologen.

Om du med rent samvete vill ta del av denna ständigt expanderande källa till visdom, ombeds du även bidra med kunskap. Vi ber dig därför att registrera dig, så att vi på lättast möjliga vis kan förfölja dig och ifrågasätta dina värdelösa tillägg. Eller enbart för en broderlig diskussion utan några som helst baktankar.


Vid förvirring hänvisas du med solskensleenden till vår dedikerade help-desk.


För kärleksproblem hänvisas du till: #OOPfk-tentaplugg @ quakenet


Med förhoppningar om en framtid tillsammans,

/Eder Mac-ninja



Contents

[edit] Kursinnehåll

Kurshemsidan

Föreläsningsinnehåll, läsanvisningar

Övningar

studentportalen står det att kursen innehåller: Arv, polymorfism och dynamisk bindning, abstrakta klasser och interface, grundläggande koncept inom objektorienterad design, designmönster, applikationsramverk, parallellism och strömmar för filhantering.

[edit] Felhantering. kap 4.6 Widaaaar

kasta fel fånga fel mm.
try-catch-final sats vad göra alla delar vilka är ett måste? 

[edit] Varför exceptions?

  • När ett fel uppkommer i java är det oftast inte på ett ställe, där det är vettigt att hantera det.
  • Att blanda logik från felhantering med logik från själva programmet leder till onödigt komplicerade och stora program.
  • Metoder speciellt designande för felhantering är oftast inte plattformsoberoende.

[edit] Exceptions ursprung 4.6.1

När ett fel i ett javaprogram uppstår, avbryts programmets flöde och man säger att ett exception kastas (thrown). Exceptions kastas av två olika orsaker:

  • När JVM utför en förbjuden operation, såsom att försöka hantera en null-referens eller få tillgång till ett fält med ett icke-existerande index.
  • I ett javaprogram kan man även explicit kasta exceptions med satsen throw.

I java finns en varité av redan definierade exceptions, men programmerare kan även definiera och kasta egna exceptions. De flesta run-time exceptions representerar ganska logiska fel som bör åtgärdas.

[edit] Hierarkin av exceptions 4.6.2

Exceptions är modellerade som objekt av exception-klasser. Olika exceptions har olika klasser och de är organiserade enligt en hierarki som ses i figur 4.2 på sidan 141. Klassen Throwable är superklass till alla Errors och Exceptions och endast instanser av Throwable eller dess subklasser kan kastas i java.

Subklasserna till Throwable definieras i tabeller i boken på sidorna 141-143.

[edit] Att kasta exceptions 4.6.3

De flesta exceptions kastas av JVM, men kan även kastas av programmeraren var som helst i programmet för att uppmärksamma fel. I koden kastar man ett exception med satsen throw enligt syntaxen

throw Exception;

Där "Exception" är en instans av Throwable eller dess subklasser. Om man inte redan har en instans färdig att kastas, så får man skapa en ny med satsen new:

throw new MyException;

Där "MyException är en godtycklig exceptionklass. Metoden, där man kastar ett exception, måste i deklarationen visa att den kan kasta alla exceptions kan kasta. Se följande exempel av en metoddeklaration:

public void MyMethod(Parameter p1, Parameter p2) throws Exception1, Exception2 {
   Satser;
}

Ett kast av ett nytt exception måste alltid i:

  • En try-catch-sats med ett catch-block som matchar det exception som kastas.
  • En metod, som i deklarationen anger att den kan kasta detta exception.

[edit] Att fånga och hantera Exceptions 4.6.4

Huvudskälet till att man använder exceptions på det här sättet är, för att man skall kunna fånga och hantera exceptions någon helt annanstans än där det uppstår. När ett exception kastas startar en mekanism, som undersöker om det hanteras i den omedelbara närheten. Om det inte hanteras, skickas det uppåt i "anropshierarkin" (t.ex. till starten av en loop och om loopen inte hanteras, kan den skickas vidare upp till där anropet till metoden sker). Satser som kan kasta ett exception bör någonstans hanteras med en try-catch-sats enligt följande:

try {
    (Satser som kan ge upphov till ett exception)
}
catch (Exception1 e1) {
    (Satser som hanterar Exception1)
}
catch (Exception2 e2)
    (Satser som hanterar Exception2)
}
finally {
    (Satser som alltid exekveras innan try-catch-blocket lämnas (frivillig))
}
  • I try-blocket testas de satser som kan kasta exceptions.
  • Catch-blocken speglar de exceptions som kan kastas i try-blocket och i catch-blocken finns kod som anger vad som ska hända om detta specifika exception fångas. Som parameter till varje catch-block skall man ge vilket exception som man vill att catch-blocket ska hantera. "e1", "e2" etc blir instanser av detta exception.
  • Finally blocket är frivilligt att ha med och koden som står där exekveras först precis innan det flödet ska till att lämna try-catch-satsen.

Man ska akta sig för att använda generella exception-klasser, då catch-blocken gås igenom sekvensiellt och om man har varsitt catch-block för Exception1 och Exception2 och det gäller att Exception2 är en subklass till Exception1, så kommer båda exceptions fastna i första catch-blocket i exemplet.


[edit] Checked Exceptions

Ett kontrollerat exception måste antingen hanteras, eller så måste man uttryckligen ange att klassen kan kasta ett sådant exception. Okontrollerade exceptions är antingen så allvarliga att det är för sent att göra något åt det redan, eller så är de så vanliga att de är onödiga att nämna (t.ex. IndexOutOfBoundsException eller NullPointerException - dessa kan ju uppstå i princip vart och när som helst).

Alla Exceptions som inte är Errors (alltså hyperallvarliga fel) eller RunTimeExceptions, är kontrollerade Exceptions. Det måste fångas där det kastas, eller deklareras i metodhuvudet med Throws "Exception".

[edit] Arv, hur och inte hur. (Disa)

varför ska man ärva?
hur ärver man?

Kapitel 5.1-5.4

[edit] Overloading Methods and Constructors 5.1

  • Överlagringsregeln: Två metoder eller konstruktorer i samma klass kan överlagras (ha samma namn), om de antingen har olika många parametrar eller samma antal parametrar men av olika typ. Med andra ord kan inte två metoder eller konstruktorer i samma klass ha identiska "signaturer".
  • Signatur: En metod eller konstruktors signatur består av dess namn och en lista över dess parametertyper. T.ex. har metoden void move(int dx, int dy) signaturen move(int, int).

När ska man använda överladdning?

  1. När det finns en generell, ickediskriminerande beskrivning av funktionaliteten som passar alla överlagrade metoder.
  2. När alla överlagrade metoder gör samma sak, och någon/några av dem ger defaultargument.
OBS!
Även om detta sällan händer, verkar Bror ha använt sig av ett aningen svengelskt uttryck för överlagring, 
nämligen överladdning. "Överladdning" och överlagring är alltså samma sak. 
OBS! 
När man skapar en subklass där man skriver över metoder så kallas detta just för överskrivning. Bra att veta.

[edit] Extending Classes 5.2

Arv definierar en relation mellan klasser. En klass som ärver (extends) en annan klass får alla metoder och dylikt från den klassen, och blir då en subklass. Klassen den ärver från är dess superklass. Arv är ett sätt att återanvända en implementation och utöka en superklass funktionalitet. Man kan nå alla public- och protecteddelar i superklassen från dess subklasser.

Tre typer av arv:

  • Extension mellan klasser: Den mest strikta formen av arv. Superklassens innehåll ärvs/återanvänds i subklassen.
  • Interface extension: Svagare arv än ovan. Återkommer till detta i kpitel 5.3.
  • Interface implementation: Svagare arv än ovan. Återkommer till detta i kpitel 5.3.

En klass kan endast extenda en enda superklass, men multipelt arv är tillåtet för interface extension/implementation. Alla klasser utom Object har en superklass, om ingen superklass anges i koden så blir det just Object som man ärver.

[edit] Constructors of Extended Classes 5.2.1

Två faser:

  1. Initialisering av det som ärvts från superklassen.
  2. Initialisering av det som tillkommer i den nya subklassen.

Variabler o.dyl. (fields i boken), som ärvts bör initialiseras genom att man anropar någon av superklassens konstruktorer. T.ex. om variablerna double x och double y finns i superklassen kan man skriva super(x, y) där x och y har typen double för att använda superklassens metod samtidit som x och y initieras till passande värden. (Om det låter rörigt se mer utförligt exempel på sidan 164.)

Om man inte har någon konstruktor i sin extended klass så får man automatiskt en default no-arg konstruktor som anropar superklassens no-arg konstruktor(super()).

[edit] Subtypes and Polymorphism 5.2.2

Man kan se på arvrelationen på olika sätt:

  • Subklassen utökar (extends) superklassens förmåga.
  • Subklassen ärver egenskaper från superklassen
  • Subklassen är en specialisation av superklassen.

Nytt sätt för detta kapitel:

  • Varje klass är en typ. Alla instanser av klassen är som ett set av alla giltiga värden av klassens typ. Eftersom varje instans av en subklass även är en instans av dess superklass så är den typ som subklassen definierar ett giltig subset till den typ som superklassen definierar. Dvs. subklassens set av instanser ingår i superklassens set av instanser (som att mängden av subklassens instanser är en äkta delmängd av superklassens instanser!). Denna relation kallas för subtype relation.

Varje instans av subklassen är även en instans av superklassen, men inte vice versa!

Några begrepp:

  • Utbytbarhet: Ett subtypvärde kan dyka upp närhelst ett supertypvärde förväntas. Alltså kan ett subtypvärde alltid substituera ett supertypvärde.
  • Widening: Att konvertera en subtyp till en av dess supertyper. Är alltid tillåtet och kan ske implicit om det behövs.
  • Narrowing: Att konvertera en supertyp till en av dess subtyper. Kallas ibland downcasting och kräver explicit handling. Alltid tillåtet vid compileringen, men kan vara osäkert och resultera i exceptions då programmet körs.

Polymorphic Assignment: (I exemplen i följande text extendar klassen Subtyp klassen Typ.)

Rule of Assignment:

Vid tilldelning måste typen på uttrycket i högerledet måste vara en subtyp till typen i vänsterledet. (Eller samma typ.)

Såhär:

Typ a = new Subtyp();

Om man har motsatt ordning på typ och subtyp får man kompileringsfel. Om man ändå vill göra en sådan sak, alltså låta en pekare av en subtyp peka på en instans av en högre typ måste man använda sig av "narrowing" (se ovan). Det ser ut såhär:

Då b har den deklarerade typen Typ, medan a har den deklarerade typen Subtyp:
Subtyp a = (Subtyp) b;

Observera att även om b råkar peka på en instans av Subtyp måste man använda detta skrivsätt så länge den deklarerade typen till b är en högre typ! Man säger att man downcastar b. Om det visar sig när programmet körs att downcastingen är ogiltig så kommer ett ClassCastException att kastas.

[edit] Overriding Methods 5.2.3

(Överskrivning på svenska)

Definition:

Att introducera en instansmetod i en subklass som har samma namn, signatur(se ovan) och returtyp som en metod som finns 
i superklassen. Detta resulterar i att subklassens metod ersätter superklassens.

Viktigt att skilja från överlagring (overloading)! Överskrivning gäller metoder i olika klasser som har en arvsrelation.

  • Final-metoder: Metoder som är final kan inte överskrivas.
  • Att använda en överskriven metod: Man kan anropa en metod som har blivit överskriven från dess subklass genom att använda anropet super t.ex. super.equals(p).
  • Restrictions: Om man har en subclass där en av metoderna i superklassen är oönskad kan man göra den metoden otillgänglig i subklassen. Eftersom det restrictions inte blir subtyper av sin superklass är de liteproblematiska och supportas därför inte direkt i Java. Vill man använda det gör man antingen en överskrivning med en helt tom metod, eller en metod som kastar ett MethodNotSupported exception.

[edit] Extending and Implementing Interfaces 5.3

Interface deklarerar egenskaper (features), men har inga implementeringar. Meningen är att ett interface ska fånga gemensamma karaktärsdrag och egenskaper hos de klasser som implementerar det.

  • Implementering av interface: En klass kan implementera flera interface. Den ärver inga implementeringar, utan implementerar själv de metoder som deklareras i interfacet.
  • Extention av interface: Ett interface kan extenda (utöka) ett eller flera andra interface. Det innehåller då alla superinterfacets egenskaper (features).

En klass som implementerar ett interface tillhandahåller implementeringar av de abstrakta metoder som deklareras i interfacet genom att överskriva dessa metoder. Tänk på att om man implementerar flera interface måste man överskriva alla abstrakta metoder i alla interface.

[edit] Subtypes Revisited 5.3.1

Lite mer om subtyper. (Se även 5.2.2)

Referenstyperna i Java kan vara klasstyper, arraytyper eller interfacetyper. Alltså definierar även ett interface en typ precis som klasser gör. På samma sätt som när klasser extendar varandra så gäller medför även interface extention/implementation att man får en subtyprelation.

Tips! På sidan 177 i boken finns en käck lista över alla subtyprelationer i Java.

Genom att implementera flera interface kan man bygga en klass som tar på sig olika roller beroende på kontext. Det gör också att klassen kan ha flera olika supertyper.

Exempel på detta från boken (förkortat): Man kan ha en referenstyp Student, och en annan Employee, som båda är interfacetyper, sedan kan man implementera dessa interface i tre olika klasser FulltimeStudent, StudentEmployee och FulltimeEmployee. På så sätt kan StudentEmployee vara en subtyp till både Student och Employee, medan de båda andra bara har varsin supertyp. Logiskt va? =)

[edit] Single Versus Multiple Inheritance 5.3.2

I t.ex. C++ kan en klass ärva från flera andra klasser. Det har fördelen att man slipper skriva om en massa metoder som man ska använda, vilket man får göra i Javas lösning med interfaces. Fördelen med Javas system är att det blir mycket enklare att fatta vad man sysslar med, t.ex. råkar man inte ut för att en klass ärver två likadana metoder som eventuellt t.o.m. innehåller olika information från två olika klasser.

Om man i Java vill återanvända metoder mera kan man använda något som kallas delegering. Det går ut på att man skapar en klass (kalla den ImplKlassen) som implementerar det inteface som man vill kunna använda direkt. Sedan kan man skapa en klass, ExtKlassen, som extendar ImplKlassen, och på så sätt "ärver" interfacets metoder.

Man kan även använda en metod som finns i interfacet genom att delegera det till ImplKlassen (alltså skriva: implKlassen.metodNamn(); --> där implKlassen är en instans av ImplKlassen).

Med hjälp av den här tekniken kan man göra allt som går att göra i språk som tillåter multipelt klassarv även i Java.

[edit] Name Collisions among Interfaces 5.3.3

Eftersom en klass kan extenda en annan klass samt implementera flera interfaces kan man råka ut för att namn från olika håll sammanfaller och kolliderar. Dock löser sånt sig oftast ganska smidigt i Java. Om två metoder i en klass har samma namn gäller följande:

  • Om de har olika signaturer, blir de överlagrade.
  • Om de har samma signatur och returtyp är de samma metod och smälts samman.
  • Om de har samma signatur men olika returtyp får man ett kompileringsfel
  • Om de har samma signatur och returtyp men kastar olika exceptions räknas de som samma metod och alla exceptions kan kastas.

Kolla i boken om du vill ha exempel!

[edit] Marker Interfaces

Marker interfaces är tomma interfaces. De är till för att visa att en klass har en viss egenskap. Det vanligaste exemplet är interfacet Cloneable som talar om att klassen är klonbar, endast klasser som implementerar Cloneable går att klona.

[edit] Hiding Fields and Class Methods 5.4

Överskrivning och gömning är två skilda begrepp som liknar varandra:

  • Instansmetoder kan endast överskrivas. Metoden man skriver över med måste ha samma signatur och returtyp.
  • Klassmetoder och "fält" (eng. fields i betydelsen instanser/klasser) kan endast gömmas. Man kan gömma dem med en klassmetod eller ett fält med vilken signatur eller av vilken typ som helst.

När man gömmer en metod i en superklass är det typen på ett objekt (egentligen typen på referensen till objektet) som avgör vilken av metoderna som kommer användas. Om man i deklarationen av referensen anger supertypen kommer den "gömda" metoden att användas, medan om referensen är av subtypen så används den nya metoden. Det betyder att två referenser som pekar på samma objekt kan anropa olika metoder med samma anrop, ifall den ena referensen är vidare definierad (se widening). Syftet med hiding är att lösa problem som beror på att flera metoder som används i samma klass råkar ha samma namn. I övrigt ska man alltid undvika att ge flera metoder med olika syften samma namn!

[edit] In- och utmatning kap 8.4 (Lisa)

[edit] Kommandoraden, args

  • När man öppnar ett javaprogram kan man skriva in argument efter filnamnet. Dessa argument kommer man åt i main-funktionen.
exempel, java openfile args1 args2 args3.
hittas i main (String[] args){ }

[edit] File objekt

  • Klassen File används när man vill komma åt information om enstaka filer eller mappar. Den innehåller också metoder för att ta bort filer, byta namn på filer och för att skapa nya filer och mappar. Obs! Klassen File är inte till för att läsa eller skriva till en fil.

[edit] Scanners

  • Scanner finns med i java 5.0 i standardpaketet java.util. Den delar upp texten i tokens (delar) som normalt avgränsas av vita tecken (blanka tecken, \t eller \n).
  • Man kan med denna på ett lättare sätt läsa data. Vill man läsa en inström från kommandoraden deklarerar man bara en ny scanner.
Scanner sc = new Scanner(System.in);
  • För att läsa ifrån en sträng så börjar man med att ange vad stringobjektet (indata) är. Sen kan man skapa en scanner.
Scanner sc = new Scanner(indata);
  • För att läsa från en fil, så skickar man med ett File-objekt.
Scanner sc = new Scanner(new File(filnamn));

[edit] Input/Output Framework 8.4

  • En viktig sak att komma ihåg när man jobbar med strömmar och filer är att göra import på java.io.*;
  • Stream I/O: en ström är en ordningsföljd(sekvens) av bytes. En strömbaserad I/O stödjer läsning eller skrivning av data som kommer i en följd endast i ena riktningen. Alltså: en ström kan inte både läsa och skriva samtidigt, så man måste skapa två stycken.
  • Random Access I/O: Random Access I/O stödjer läsning och skrivning av data på vilken possition som helst i en fil. Den kan alltså öppna filen för både läsning och skrivning.
  • Det finns två typer av strömmar: byte streams och character streams. Byte streams stödjer läsning och skrivning av alla typer av data, inkluderat strings, i binärt format. Character streams stödjer läsning och skrivning av text, using locale-dependent character encodings.

[edit] Byte Streams 8.4.1

  • De mest grundläggande I/O strömmarna är deklarerade i två abstract classes: InputStream och OutputStream. De stödjer läsning och skrivning av enstaka byte och en sekvens av bytes i en array.
  • Två av de mer konkreta klasserna för byte stream I/O som gör extend på de två abstracta klasserna är FileInputstream och FileOutputStream. Instanser av dessa två klasser kan bli konstruerade av att man anger filnamnet. Dessa klasser gör läsning och skrivning av alla typer av data möjlig men knappast lätthanterlig. Det skickas också mycket data fram och tillbaka då den endast hämtar en byte i taget.
  • För att lösa problemet att den endast hämtar ett ord i taget har man skapat klasserna BufferedInputStream och BufferedOutputStream. Dessa är filtrerade strömmar som stödjer buffered I/O. De tar I/O strömmen och gör om den till en buffered I/O ström. Vilket betyder att den hämtar flera ord i taget och behöver därför söka igenom filen färre gånger.

[edit] Character Stream 8.4.3

  • I Java program är en string representerad i Unicode, där alla tecken är uppdelad i två bytes. Det finns olika sätt att omkoda tecknen, lite beroende på plattform samt vilket språk och land man kommer från. Därför finns det olika ISO standarder, vilket gör att det blir krångligt för programmeraren att hålla reda på vilken standard som gäller. Därför så konverterar en character baserad I/O ström alla tecken mellan Unicode och den lokala variationen som gäller medan den läser och skriver strings.
Med andra ord: character-based I/O streams är känslig för olika språkstandarder, medan byte streams inte är det.
  • Det finns två abstract classes, Reader och Writer, som är ursprunget på arvshierarkin för alla character-baserade input och output strömmar.
  • FileReader och FileWriter är två konkreta strömmar som använder sig av möjligheterna som grunderna av Character-based I/O har.
  • BufferedReader och BufferedWriter är två filter som stödjer buffered character-based I/O. Det som är speciellt med BufferedReader klassen är att den har en metod som heter readLine(), som läser en rad ur en text.
  • PrintWriter är en klass vi använder oss ganska mycket av då den skriver ner värdet av datatyper genom att konventera dem till strings. Den använder främst två metoder print(v) och println(v) där v är det den skriver ut. Den använder alltså själv klassen ToString().

Exempel på att läsa och skriva:

(Rätta, förbättra och utöka gärna dessa exempel)

För att läsa:

Scanner sc = new Scanner(new File("/path/to/file"));
PrintWriter("/path/to/file");
PrintWriter(BufferedReader in = new BufferedReader(new FileReader("/path/to/file")));

För att skriva:

BufferedWriter out = new BufferedWriter(new FileWriter("/path/to/file"));

[edit] Ramverket Collection kap 8.2 (Miriam)

Detta ramverk är en mängd interfaces och klasser som stödjer lagring och hämtning av objekt i collections (behållare, samlingar) av olika typer.

En Collection är ett objekt som innehåller andra objekt, som kallas elements. Dessa element skall vara av samma typ; man kan t.ex. inte ha en lista med Integers och Strings i samma Collection. Däremot kan man lägga dessa i en Collection för t.ex. Objects.

När används det?

[edit] Abstract Collections 8.2.1

Abstract collections delas in i 4 huvudtyper:

  • Bags (multisets): Oordnad mängd (collection) av element, tillåter dubletter. Eftersom bags är så generella, används de inte så ofta. Representeras i Java av interfacet Collection.
  • Sets: Oordnad mängd av element, kan inte innehålla dubletter. Det finns vanliga set och även sorted set. Det senare sorteras automatiskt i en viss ordning. Representeras i Java av interfacen Set resp. SortedSet.
  • Lists (sequences): Ordnad mängd av element, tillåter dubletter. Får index från 0 och uppåt. Representeras i Java av interfacet List.
  • Maps (functions, dictionaries, associative arrays): Oordnad mängd av par av en nyckel och ett värde (key, value). Max ett värde kan ges åt varje nyckel, och varje nyckel måste vara unik. Det finns vanliga map och även sorted map. Det senare sorteras automatiskt i en viss ordning. Representeras i Java av interfacen Map resp. SortedMap.

[edit] Interfaces of Collections 8.2.2

Olika implementationer av en samling (abstract collection) extendar samma interface. Därför är det viktigt att veta vilket interface en viss samling använder.

För att tex komma åt metoderna från samlingen Set i subtypen HashSet, skriver man

Set mySet = new HashSet();

Dvs man extendar interfacet Set. Om man skriver namnet på interfacet först, så blir det lätt att byta mellan t.ex HashSet och TreeSet.

  • Collection interface: Representerar en bag. Kan innehålla vilka objekt som helst, men värden av primitiva typer måste omges av en omslagsklass för att kunna lagras.
  • Set interface: Extendar Collection interface och representerar ett set. Ändrar några metoder (s.312).
  • List interface: Extendar Collection interface. Ändrar och lägger till några metoder (s.313)
  • Map interface: Representerar en map. Extendar INTE Collection eller Set interface, eftersom några metoder ifrån dessa interfaces inte stöds.

[edit] Implementationer av samlingar 8.2.3

En implementation av en samling är en slags undertyp, som kallas en concrete collection.

Om mängden är ordnad, är standarden att det första elementet är det minsta.

[edit] Implementationer för Set

Använd TreeSet för särskild ordning på objekten, annars använd HashSet för effektivitet.

  • HashSet: Elementen lagras huller om buller i en hash table. Effektiv användning av add() och membership checking (contains()). (Man måste själv definiera metoderna equals() och hashCode() ?).
  • LinkedHashSet: Väldigt lik HashSet, men elementen lagras efter när de tillades.
  • TreeSet: Implementerar interfacet SortedSet, kan ordnas efter behag. Inte lika effektiv som HashSet, så använd bara denna om elementen måste lagras i en viss ordning.

[edit] Implementationer för List

Använd ArrayList när du ska hämta information ofta, och LinkedList för listor som växer och krymper mycket.

  • ArrayList: När den blir full så gör den en ny mycket större array, slösar datorkraft. Har alltid en stor array för att rymma alla element, men den står ofta tom. Mer effektiv än LinkedList när det gäller metoderna get() och set().
  • LinkedList: När element läggs till, ökar den bara sin storlek för att rymma ett nytt element. Har alltid bara så mycket utrymme som krävs.

[edit] Implementationer för Map

Använd Treemap för särskild ordning på objekten. Annars använd HashMap för effektivitet.

  • HashMap: Elementen lagras i en hash table. Effektiv när det gäller put() och get(). (Man måste själv definiera metoderna equals() och hashCode() ?).
  • LinkedHashMap: Väldigt lik HashMap, men elementen lagras efter när de tillades.
  • IdentityHashMap: Också väldigt lik HashMap, men man jämför om 2 nycklar är samma nyckel istället för att jämföra om de innehåller samma värden. Mer effektiv än HashMap i detta avseende.
  • TreeMap: Implementerar SortedMap. Inte lika effektiv som HashMap när det gäller metoder som put() och get().

[edit] Iterators of Collections 8.2.4

Det finns två itererator-interfaces: Iterator och ListIterator. Iterator löper igenom en lista framåt, och ListIterator kan gå både framåt och bakåt. ListIterator extendar Iterator-interfacet.

Instanser av concrete iterators skrivs:

i Collections interface:
Iterator iterator()
i List interface:
ListIterator listIterator()

läs mer: s. 319 - 323.

[edit] Att ordna och sortera

läs nedan, under Comparable / Comparator.

[edit] Likhet, hashkoder och jämförelse av objekt (Josef)

[edit] equals() 6.3.2

Metoden equals() finns i Object-klassen, och finns således automatiskt med i alla klasser. Standardimplementationen av equals() returnerar true om för o1.equalt(o2) om o1 och o2 är referenser till samma objekt.

[edit] Krav att uppfylla

Om man överlagrar equals()-metoden bör den uppfylla följande krav:

  • Reflexivitet
  • Symmetri
  • Transitivitet
  • Konsekvent resultat: x.equals(y) ska konsekvent returnera antingen true eller false, om inte något av tillstånden för x eller y har förändrats.
  • Icke-null: x.equals(null) ska alltid returnera false

[edit] hashCode()

Det viktigaste att komma ihåg när man överlagrar equals()-metoden är att man också måste överlagra hashCode()-metoden. Om x.equals(y) så måste x.hashCode() == y.hashCode(). Däremot får hashCode() för två olika objekt returnera samma hashkod, även om det är bra ur effektivitetssynpunkt är bra om hashkoden för två olika objekt är annorlunda.

Här följer en generell metod för att skapa hashkoder:

  • Skapa en hashkod för alla signifikanta element (d.v.s. de element som tas hänsyn till i equals()-metoden). För primitiva värden kan en hashkod genereras genom att helt enkelt konvertera värdet till typen integer. Om det signifikanta elementet är en referens till ett objekt kan man kalla på det objektets hashkod, såvida värdet av referensen inte är null.
  • Kombinera alla hashkoder för de signifikanta elementen genom att köra följande sats, där c är hashkoden för varje signifikant element och p är ett primtal: newHashCode = newHashCode * p + c.

(Avsnitt 6.3.2 i kursboken, sid 228)

[edit] Gränssnittet Comparable

Vill man kunna ordna objekten i någon slags storleksordning kommer gränssnitten Comparator och Comparable väl till pass. I del flesta fall är gränssnittet Comparable det mest lämpade.

public interface Comparable {
    public int compareTo(Object o)
}

Resultatet ska tolkas som följande:

  • < 0 om this är mindre än o
  • = 0 om de ska komma lika
  • > 0 om this är större än o

compareTo()-metoden ska alltid definiera en total ordning - d.v.s. om x.compareTo(y) < 0 så måste y.compareTo(x) > 0.

compareTo()-metoden måste dessutom sammanfalla med equals()-metoden. (t.ex. x.equals(y) är sant om och endast om x.compareTo(y) är sant)

Om en klass implementerar Comparable så sägs klassen vara naturligt jämförbar.

[edit] Gränssnittet Comparator

Ett annat sätt att jämföra två objekt på är genom att skapa en s.k. komparator. Detta behövde man göra förr innan gränssnittet Comparable fanns, och det är fortfarande väldigt andvändbart om man vill jämföra två objekt på annat sätt än vad objektets compareTo()-metod gör.

En komparator är en helt fristående klass och gränssnittet ser ut som följande:

public interface Comparator {
    int compare(Object 01, Object o2);
}

Metoden compare() ska ge ett returvärde < 0 om o1 är mindre än o2, > 0 om o1 är större än o2 och 0 om o1 är lika med o2.

Enligt kursboken implicerar x.equals(y) om sant att c.compare(z,y) är 0, och vice versa. Detta tycker jag verkar helt asdåligt - vad i hela världen tänkter dom med? Vad ska jag nu har komparatorer till??


TODO:
?naturligt jämförbara

[edit] Återanvändbara komponenter, Design kap 7.1-3 (Erik)

Det är olika kodformer man kan använda när man kodar, och vad man ska tänka på; hur strategin ska vara helt enkelt.

inga public variabler!!

[edit] Designmönster skrivs på följande form.

Designmönster har den engelska översättningen Design Patterns

Category: där vilken sorts mönster skrivs, det finns 3 olika:

  • Kreativa
  • Strukturella
  • Beteendemönster.

Intent: där skrivs vad meningen med den är.

Applicability: vart man ska och inte ska använda den.

[edit] Några exempel på dom vanligaste designmönstrena:

[edit] Gemensam metod sid 254(lätt)(användbar):

Ha en gemensam metod som gör arbetet åt en.

Används när miljön runtomkring inte spelar någon roll för just den kodbiten, eller när det är samma kod i två olika metoder.

[edit] Gemensam ärvd metod sid 255(lätt)(användbar):

Den går ut på att ärva en klass där man har skrivit all gemensam kod.

Används när det är gemensam kod, miljön inte spelar någon roll, och man har samma kod i två olika klasser. att man kan överlagra metoder är en viktig del i detta.

[edit] Delegation sid 255(lätt):

Används när man inte kan ärva och vill ha samma funktonalitet nästan som ovan. Alternativt när man vill ärva men inte vill att användaren ska få tillgång till alla metoder som superklassen har. Går ut på att man skapar ett objekt av en klass, som man sedan anropar när man vill ha den gemensamma koden.


Exempel:


public class Stack<E> extends ArrayList<E>{
public void push(E element){
...
add(E);
stackpointer++;
}
public E pull(){
...
stackpointer--;
return get(stackpointer + 1);
}
}

Denna konstruktion är inte bra då programeraren som använder stacken fortfarande kan använda add() och get() som den ärver från ArrayList. Om han gör det så förändras inte stackpekare och dylikt. Inte bra. Löses genom delegering:


public class Stack<E>{
private ArrayList<E> li = new ArrayList<E>;

public void push(E element){
...
li.add(element);
stackpointer++;
}
public E pull(){
...
stackpointer--;
return li.get(stackpointer + 1);
}
}

[edit] ReferensDelegation (svår)(användbar):

Används när det är rätt information framför och bakom och det är i en while, if, for, eller annan rolig sats. ex.


int[20] list{11,23,54,567,234437,34,234,324,32,776,456,56,68,89,99}
for(int i:lista){
viktigKod1
skillnad på koden.
viktigKod2
}


Lösning.


Public void metod(obijekt obijektNamn){
int[20] list{11,23,54,567,234437,34,234,324,32,776,456,56,68,89,99}
for(int i:lista){
viktigKod1
obijektNamn.skillnad(i);
viktigKod2
}}


där obijektNamn är en variabel som kan ändras beroende på vad metoden ska användas till.

[edit] Singelton(svår) sid 251:

Används till att se till att det bara finns ett objekt av den här sorten.

class Mysingelton{
  privat static Mysingelton singel; 
   protected mysingelton{}
   public static synkronised Mysingelton getInstans{
   if(singel== null){
      singel=new MySingelton();
   }
 return singel;
 }
}

[edit] Composite sid 531(användbar)

När en sak ska bete sig nästan som en annan i en lista eller liknade.

ReferensDelegration i en lista för att tex måla ut många saker som är liknande varandra.


Lyckas man med den här uppgiften, så kan man det mesta om detta ämne.

[edit] Trådar kap 11.1-2 (Emanuel)

[edit] Vad är det?

En tråd är ett sekvensiellt kontrollflöde i ett program. Jämför med "process" (fastän det inte är samma sak).

Java har inbyggt stöd för multipla trådar

Jämför "samtidighet"

[edit] Hur fungerar det?

Oftast implementerat som virtuell parallellism, eftersom de flesta datorer inte kan ha en processor per process.

Olika trådar schemaläggs.

Flera trådar kan existera i samma process.

Flera trådar kan dela på samma minnesmängd.

Flera trådar kan kommunicera med varandra med delade variabler och objekt.

Inte samma sak som process.

Den tråd med högst prioritet är den som exekveras.

Genom att ett program innehåller flera trådar, kan flera saker beräknas "samtidigt".

[edit] Användningsområden

Responiva GUIs, som interagerar med användaren medan beräkningar utförs i bakgrunden.

Servrar kan hantera flera klienter samtidigt

[edit] Problematik

  • Schemaläggning av multipla trådar är svårt.
  • Det kan leda till säkerhetshål och beräkningsfel.
  • Java garanterar inte en jämlik exekvering av trådar med lika stor prioritet.
  • Eftersom Java enbart kör den tråd med högst prioritet, kan när som helst byta prioritet och hoppa till en annan tråd.
  • Detta medför att objekt som håller på att modifieras lämnas i "ogiltiga" tillstånd. Se därför Synchronized

[edit] Hur implementera och använda

2 sätt att skapa och deklarera trådar:

- Göra subklass till klassen Thread.

Skapa objekt av klassen vars superklass är Thread. 
Klassen måste överlagra metoden run(), som startas indirekt med metoden start() vid skapandet av instansen av klassen.
Ex: new MyThread().start();
Nackdelar: Java kan enbart ha en superklass

- Implementera interfacet Runnable.

Består av enbart en metod: run()
Skapa körbart objekt via konstruktorn till klassen som implementerar Runnable
Skapa ny tråd via konstruktorn till Thread, vars parameter ska vara av typen Runnable - alltså då lämpligen objektet av klassen som implementerar Runnable.
Sedan anropas start(), som implicit anropar run()
Ex: new Thread(new MyThread()).start();

[edit] Konsistenssäkerhet

En klass är konsistenssäker om det är garanterat att den inte kan avbrytas även vid parallellism.

Har man inte kontroll över hur objekt exekveras kan det leda till säkerhetshål och beräkningsfel. Olika trådar får inte hantera gemensamma data samtidigt, och en tråd får inte (oavsiktligt) avbryta en annan tråd. Därför måste man kontrollera trådarna.

[edit] Synkronisering

Kritiska områden med potentiellt interfererande händelser bör programmeraren identifiera och åtgärda genom synkronisering.

Java löser det med att tilldela varje unik instans av ett objekt ett lock (eng. lås).

Locket finns inte på en metod som sådan, utan på metoden i instansen.

Varje lock ägs av endast och endast EN tråd åt gången.

Locken är instansberoende, dvs att de delas INTE mellan olika trådar.

För att en tråd ska kunna exekvera kritisk kod måste tråden först få locket

Metoder eller hela satser kan synkroniseras.

Ex synchronized void Method()

Ex void Method() { synchronized(this) { } }

Man kan säga att en metod/sats är ägaren åt locket, medan trådarna blir ägare till locket när de får tillgång till det. Om det finns 2 instanser av samma objekt, kan två trådar INTE exekvera en synchronized metod i samma instans, utan enbart en tråd i taget. DÄREMOT kan en tråd exekvera en synchronized metod i en instans, medan den andra tråden exekverar "samma" metod i den andra instansen.

sleep()
Medan en tråd är igång kan den tillfälligt "pausas". sleep() tar ett värde på hur många millisekunder den skall "sova".

yield()
Den aktuella tråden "pausas" tills andra trådar "hunnit ikapp" eller enbart fortsätter exekvera kod

th.join()
Den aktuella tråden "pausas" tills tråden th avslutas, och fortsätter sedan

Variabler kan inte synkroniseras direkt, utan istället kan man använda synkroniserade get() och set()-metoder

Collection och Map är osynkroniserade, men de kan synkroniseras med synkroniserade omslagsklasser, tex klassen Collections

wait()
Väntar på att bli väckt av ett notify.

notifyAll()
Väcker alla trådar som väntar för tillfället

interrupt()
Sätter interrupt flaggan till true, man måste fortfarande kontroller om tråden blivit avbruten vid passande tillfälle och därefter avsluta det som skall
avslutas.

Detta för att exekveringen av tråden inte skall avbrytas t.ex. mitt i en viktig loop eller medan man modifierar något viktigt. Därför sätter man en flagga som man skall kontroller med jämna mellanrum med t.ex. en if-sats

if (isInterrupted())
    //stäng filer och annat du vill göra när innan du "stänger" tråden

[edit] Javadoc kap 6.1.4 (Lisa)

  • Hur skriver man javadoc? Och varför?
  • Anledningen till att man skriver är för att personer snabbt ska kunna sätta sig in i vad klassen gör, vilka variabler och metoder klassen har samt vilka inparametrar varje metod har. Man skriver även med vem som programmerat klassen, vilken variation, samt om den kastar några exceptions.

[edit] Example

An example of using Javadoc to document a method follows. Notice that spacing and quantity of characters in this example are as conventions state.

/**
 * Validates a chess move. Use {@link #doMove(int, int, int, int)} to move a piece.
 * 
 * @param theFromFile file from which a piece is being moved
 * @param theFromRank rank from which a piece is being moved
 * @param theToFile   file to which a piece is being moved
 * @param theToRank   rank to which a piece is being moved
 * @return            true if the chess move is valid, otherwise false
 * @author            John Doe
 */
boolean isValidMove(int theFromFile, int theFromRank, int theToFile, int theToRank)
{
    ... 
}
 
/**
 * Move a chess piece.
 *
 * @see java.math.RoundingMode
 */
boolean doMove(int theFromFile, int theFromRank, int theToFile, int theToRank)
{
    ... 
}

[edit] Iterator

En iterator är en pekare som går igenom en collection av prylar, steg för steg.

För att hämta nästa element anropar man metoden next().

Under tiden man använder iteratorn kan man inte modifiera den collection man går igenom utan att förstöra iteratorn. Därför finns metoden remove() i Interface, som tar bort det senaste elementet iteratorn passerade.

Det finns också en metod som heter hasNext() som kontrollerar om det finns ett nästa objekt att hämta.

exempel:

Iterator i = set.iterator();
 while(i.hasNext()){
    println(i.next());
 }

en for-each:

Arraylist<string> arr=new Arraylist<string>();
 for(String h:arr){
   println(h);
 }

[edit] Diverse koncept av vikt

[edit] StringTokenizer

En klass som används för att dela upp en sträng i delar. Denna klass är gammal och bör inte användas. Använd istället String.split("\\s") som har samma funktionalitet.

Exempel:

    StringTokenizer st = new StringTokenizer("this is a test");
    while (st.hasMoreTokens()) {
        System.out.println(st.nextToken());
    }

och

    String[] result = "this is a test".split("\\s");
    for (int x=0; x<result.length; x++)
        System.out.println(result[x]);

Ger utskriften:

    this
    is
    a
    test

Man kan också använda Scanner men det är mindre effektivt, den passar bättre på filer.

[edit] Vart finner man klassnamnen?

Vårt klassnamn "ClassName" återfinns på följande ställen:

  • Klassen ClassName
Beskrivning av de objekt som ingår i mängden
  • Konstruktorn ClassName()
En eller flera. Används till att skapa objekt av typen ClassName
  • Typen ClassName
Mängden av alla objekt av klassen ClassName
  • Klassobjektet ClassName
Ett visst bestämt objekt
  • Class-filen ClassName.class
Filen som körs, filen där klassobjektet hämtas

[edit] Saker att ta upp

TODO:
Kontrakt


[edit] Functional and structural testing

Funktionell testning innebär att man testar en enhet enbart genom att kontrollera att enheten fungerar enligt enhetens specifikation. Strukturell testning innebär att man tar hänsyn till själva implementationen.

[edit] Brors styggelser

  • Hur de generiska typerna är skrivna
Personal tools