EDAA01 Programmeringsteknik - fördjupningskurs Föreläsning 1

EDAA01 Programmeringsteknik - fördjupningskurs
Föreläsning 1-2
Innehåll
Introduktion
Läsperiod lp 3 (Ges även lp 1+2)
Kursens mål och innehåll
Undervisning
7.5 hp
[email protected]
Språkkonstruktioner i Java och delar av Javas klassbibliotek
http://cs.lth.se/edaa01vt
Interface
Förkunskapskrav:
Exceptions
Godkänd på obligatoriska moment och/eller på tentamen i någon av
grundkurserna EDA016, EDA011 eller EDA017
Generik, Autoboxing - och unboxing
Godkänt betyg på grundkursen EDA501 eller EDAA20
Traversera genom en samling element – interfacen Iterator och
Iterable och foreach-sats
eller
Lagra element – Java Collections Framework (interface och klasser för
samlingar av element)
Jämföra element – metoden equals, interfacet Comparable
EDAA01 (Föreläsning 1-2)
VT 2016
1 / 99
Språkkonstruktioner i Java och delar av Javas klassbibliotek
EDAA01 (Föreläsning 1-2)
VT 2016
2 / 99
Detta kan du ...
Förkunskaper
Undervisningsmoment:
en hel del om programmering och objektorientering
föreläsning 1-2
begrepp som klass, objekt, attribut, metod, parameter
övningsuppgifter 1-3
skriva mindre program i programspråket Java
laboration 1
skriva och debugga program i utvecklingsverktyget Eclipse
Avsnitt i läroboken:
använda vektorer, matriser och (delvis) klassen ArrayList
1, 2.1, Appendix A6, A11, A12
enkla algoritmer som t.ex. linjärsökning, insättning i en redan sorterad
vektor
I gamla upplagan: 1.1-1.3, 2.1-2.4, 4.1
använda arv – superklass, subklass, abstrakt metod
EDAA01 (Föreläsning 1-2)
VT 2016
3 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
4 / 99
Detta ska du lära dig ...
Mål
Kursens mål
Förklaring av termer
mer om programmering och objektorientering
Algoritm
interface, exceptions, generik ...
formulera och använda olika algoritmer för att effektivt lösa problem
sökning, sortering ...
rekursiva algoritmer
Datastruktur
använda olika datastrukturer
listor, binära sökträd, hashtabeller, heapar ...
dels genom att använda färdiga klassbibliotek och dels genom att göra
egna implementeringar
testa klasser (jUnit)
En samling variabler som hör ihop på något sätt.
Ex: vektor, länkad lista, träd
Biliotek
En samling färdiga klasser som är tänkta att användas i andra program.
Fungerar som en utvidgning av programspråket.
Ex: Javas standardbibliotek för samlingar - Java Collections Framework
analysera och jämföra algoritmers tidsåtgång
skriva program med grafiska användargränssnitt (JavaFX)
EDAA01 (Föreläsning 1-2)
Beskrivning hur man stegvis löser ett problem.
Ex: matrecept, linjärsökning
VT 2016
5 / 99
Varför är detta viktigt att kunna?
EDAA01 (Föreläsning 1-2)
VT 2016
6 / 99
Exempel
Skriv program för att hantera kontakter (namn, mobil nr ...).
Till skillnad mot övningsprogram är riktiga program stora, skrivs av flera
personer, har lång livstid, kräver underhåll . . . .
Att fundera på:
Ska vi använda en vektor eller finns det andra, bättre sätt att lagra
posterna? Finns det färdiga klasser som kan användas?
Därför är följande viktigt:
bra design
Hur sker kommunikationen med användaren (utskrifter i konsolfönstret
eller snyggare grafiskt användargränssnitt)? Hur designar man
programmet så att man lätt kan byta sätt?
läsbar kod
att man kan välja lämpliga algoritmer, datastrukturer och färdiga
byggstenar (klasser ur bibliotek)
Hur söker man snabbt om antal poster är stort är stor?
bra verktyg för programutveckling, felsökning och testning
EDAA01 (Föreläsning 1-2)
...
VT 2016
7 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
8 / 99
Från problem till program
Kursens struktur
Specifikation av problemet
Design
Val av lösningsmetoder (algoritmer, X
y
XXX
XXX
datastrukturer) för delproblem
X
Implementering (programskrivning)
Testning
X
Behandlas i
EDA061/F10,
OMD
Behandlas i
denna kurs
f 1-2
ö1-3,
lab1
f 3-4
ö 4-5
lab 2
Interface,
exceptions,
generik,
JCF,
iteratorer
Listor,
stackar
köer,
länkade
strukturer
f5
ö6
f6
ö7
lab 3
Algoritmers
effektivitet,
Rekursion
tidskomplexitet
f7
lab 6
Grafiska
användargränssnitt
Underhåll (korrigeringar och uppdateringar)
f 8-10
ö 8-11
lab 4-6
Set, map.
Träd,
binära
sökträd,
hashtabeller
f 11
ö 12
f 12
ö 13
Prioritetsköer,
heapar
Sortering
Parallellt: dokumentation
EDAA01 (Föreläsning 1-2)
VT 2016
9 / 99
Kursmoment
EDAA01 (Föreläsning 1-2)
VT 2016
10 / 99
Examination
Laborationer – 6 st, läsveckorna 2-7, obligatoriska
Kräver förberedelser.
Ska lösas i grupper om två. Anmälan till önskad labbgrupp görs på
kursens hemsida senast ons 20/1.
Inlämningsuppgift – andra halvan av läsperioden, obligatorisk
Skriftlig tentamen
Kursen inrapporteras i Ladok i två delar
Ska lösas i grupper om två.
Finns på hemsidan. Det finns två alternativ att välja mellan.
Redovisas i läsvecka 8.
Obligatoriska moment (laborationer + inlämningsuppgift) 3 hp
Tentamen 4.5 hp
Övningsuppgifter
Viktigt komplement till laborationerna.
Löses på egen hand. Uppgifter och lösningsförslag finns på kursens
hemsida
Föreläsningar – 13 st, läsveckorna 1-7
Bilder läggs ut på hemsidan och används delvis under föreläsningarna.
Tillsammans med de bilder som inte visats blir de publicerade bilderna
en sammanfattning av kursinnehållet som kan användas för repetition.
EDAA01 (Föreläsning 1-2)
VT 2016
11 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
12 / 99
Lärobok
Relation till andra kurser
E. Koffman och A. T. Wolfgang: Data Structures: Abstraction and
Design Using Java, Second Edition.
För C och D ingår kursen i kurskedjor.
Den gamla upplagan heter: Objects, Abstraction, Data Structures and
Design Using Java Version 5.0.
Det går bra att använda både den nya och den gamla upplagan
Litteraturanvisningar i kursmaterialet ges för båda upplagorna.
Ny upplaga är på gång (jan 2016).
EDAA01 (Föreläsning 1-2)
VT 2016
13 / 99
CEQ-synpunkter
Det är viktigt att känns till förkunskapskraven i kedjan. Finns på
hemsidan.
I övrigt gäller att nästan alla valfria kurser i datavetenskap kräver
godkänt i EDAA01.
EDAA01 (Föreläsning 1-2)
VT 2016
Nytt sedan förra läsåret:
Överlag nöjda studenter
Några synpunkter från tidigare kursomgångar:
Laborationerna har varit intressanta och har haft ett första intryck av
att vara väldigt avancerade men sedan varit lättare än vad man kunnat
tro.
Laborationerna var för svåra för att klara av på endast ett tillfälle. –
Labbarna kräver förberedelser.
Senaste versionen av Java, Java 8, innehåller en del nyheter med
anknytning till kursen. I kursboken och i det mesta av kursmaterialet
används Java 7.
Vissa föreläsningsbilder med Java 8 kommer dock att smygas in.
Det var bra att jobba i par på uppgifterna så man har någon att
diskutera med hela tiden.
JavaFX kommer att användas (istället för Swing-paketet) för att
skriva grafiska användargränssnitt. Påverkar labb 3, 6 och
inlämningsuppgiften.
Stressigt tempo.
Det finns möjlighet att skriva inlämningsuppgiften för Android.
Jobbigt att behöva köa för att få hjälp med inlämningsuppgiften. –
Börja i god tid.
Tentorna påverkas ej av detta. Extentorna är alltså fortfarande
aktuella.
Saknar övningstillfällen. – Övningsuppgifterna finns som
självstudieuppgifter. Viktiga! Lös dem.
EDAA01 (Föreläsning 1-2)
14 / 99
VT 2016
15 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
16 / 99
Arv – repetition
Arv
Exempel
Superklassen Shape
public abstract class Shape {
protected int x;
protected int y;
I ett program ska geometriska figurer (kvadrater och cirklar) hanteras.
Figurerna ska kunna flyttas och ritas upp på skärmen.
protected Shape(int x, int y) {
this.x = x;
this.y = y;
}
Shape {abstract}
x
y
Shape(int, int)
moveTo(x, y)
draw(SimpleWindow)
Square
side
Square(int, int, int)
public void move(int dx, int dy) {
x = x + dx;
y = y + dy;
}
Circle
radius
Circle(int, int, int)
EDAA01 (Föreläsning 1-2)
}
VT 2016
17 / 99
Arv
public abstract void draw(SimpleWindow w);
EDAA01 (Föreläsning 1-2)
VT 2016
18 / 99
Diskutera
Subklassen Square
public class Square extends Shape {
private int side;
public Square(int x, int y, int side) {
super(x, y);
this.side = side;
}
}
Klassen Shape har den abstrakta metoden draw.
Vad är en abstrakt metod?
Varför finns den abstrakta metoden draw i klassen Shape.
public void draw(SimpleWindow w) {
w.moveTo(x, y);
w.lineTo(x + side, y);
w.lineTo(x + side, y + side);
w.lineTo(x, y + side);
w.lineTo(x, y);
}
EDAA01 (Föreläsning 1-2)
VT 2016
19 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
20 / 99
Interface – exempel
Implementera interface
Exempel
Klassen Square
I ett helt annat program är man bara intresserad av att beräkna figurernas
area.
I en klass som implementerar ett interface måste alla abstrakta metoder i
interfacet implementeras:
Lösning: Skriv ett interface Measurable med en metod för att beräkna
arean. Låt klasserna Square och Circle implementera interfacet.
public interface Measurable {
/** returns the area. */
double area();
}
public Square(int side) {
this.side = side;
}
<<interface>>
Measurable
area() : double
Square
side
Square(int, int, int)
EDAA01 (Föreläsning 1-2)
public class Square implements Measurable {
private int side;
public double getSide() {
return side;
}
Circle
radius
Circle(int, int, int)
VT 2016
21 / 99
public double area() {
return side * side;
}
}
EDAA01 (Föreläsning 1-2)
Interface
VT 2016
22 / 99
VT 2016
24 / 99
Interface
Java 8
Från och med Java 8 kan interface innehålla
Betyder ”gränssnitt”.
abstrakta metoder
T.o.m Java 7 kunde interface bara innehålla abstrakta metoder och
konstanter.
statiska metoder
Metoderna är implicit publika och abstrakta, dvs. man behöver inte
skriva public abstract ....
konstanter
default-metoder
public interface Measurable {
/** returns the area. */
double area();
public interface Measurable {
/** returns the area. */
double area();
}
}
EDAA01 (Föreläsning 1-2)
VT 2016
23 / 99
public default String areaAsString() {
return String.valueOf(area());
}
EDAA01 (Föreläsning 1-2)
Interface
Interface
Implementera flera interface
namn
Interface kan användas som typnamn:
Exempel 1:
En klass kan implementera flera interface
Measurable m = new Square(50);
System.out.println(m.area());
men bara ärva från en klass.
public class Square extends Shape implements Measurable,
Cloneable {
// implementering av alla abstrakta metoder i klassen Shape
// och i interfacen Measurable och Cloneable
}
EDAA01 (Föreläsning 1-2)
VT 2016
25 / 99
Interface som typnamn
Exempel 2:
public static double sumAreas(Measurable[] a) {
int sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i].area();
}
return sum;
}
EDAA01 (Föreläsning 1-2)
VT 2016
26 / 99
Exempel: Komplexa tal
Interfacet ComplexNumber
Genom att använda interfacenamnet som typnamn kan man
skjuta upp valet av implementering
public interface ComplexNumber {
/** Returns real part. */
double getRe();
lätt byta en implementerande klass mot en annan
Exempel:
/** Returns imaginary part. */
double getIm();
List<Integer> list = new ArrayList<Integer>();
eller
List<Integer>list = new LinkedList<Integer>();
}
List<E> är ett interface i java.util, medan ArrayList<E> och
LinkedList<E> är konkreta klasser.
EDAA01 (Föreläsning 1-2)
VT 2016
27 / 99
/** Adds this number and rhs and returns result as
a new complex number. */
ComplexNumber add(ComplexNumber rhs);
EDAA01 (Föreläsning 1-2)
VT 2016
28 / 99
Klass som implementerar interfacet
En annan klass som implementerar interfacet
public class RectangularComplexNumber implements ComplexNumber {
private double re;
private double im;
public RectangularComplexNumber(double re, double im) {
this.re = re;
this.im = im;
}
public PolarComplexNumber(double re, double im) {
r = Math.sqrt(re*re + im*im);
theta = Math.atan2(im, re);
}
public double getRe() {
return re;
}
/** returns real part */
public double getRe() {
return r * Math.cos(theta);
}
}
}
public class PolarComplexNumber implements ComplexNumber {
private double r;
private double theta;
public double getIm() {
return im;
public ComplexNumber add(ComplexNumber rhs) {
return new RectangularComplexNumber(re+rhs.getRe(),im+rhs.getIm());
}
EDAA01 (Föreläsning 1-2)
VT 2016
29 / 99
/** returns imaginary part */
public double getIm() {
return r * Math.sin(theta);
}
...
EDAA01 (Föreläsning 1-2)
VT 2016
Interface
Pre- och postvillkor (eng. pre- och postconditions)
Kontrakt
Kontrakt på metodnivå
I en metods dokumentationskommentar kan man ange pre- och postvillkor.
Interfacet fungerar som kontrakt eller specifikation.
Flera implementeringar (klasser) kan uppfylla kontraktet.
Previllkor är villkor som måste vara uppfyllda för att en metod ska
kunna utföra sin uppgift.
Användare har tillgång till alla metoder i ett interface innan de är
implementerade.
Det är bara när man skapar instanser som man behöver tillgång till en
implementerande klass.
VT 2016
Ibland finns inga preconditions.
När de finns, är de ofta villkor som parametrarna ska uppfylla.
Postvillkor beskriver hur exekvering av metoden förändrar tillståndet
hos objektet.
Behöver bara anges om metoden förändrar tillståndet (oftast
void-metoder).
För metoder som inte är void bör man i stället ge en kommentar om
vad som returneras.
ComplexNumber c1 = new RectangularComplexNumber(1,2);
ComplexNumber c2 = c1;
c2 = c2.add(c1);
EDAA01 (Föreläsning 1-2)
30 / 99
31 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
32 / 99
Pre- och postvillkor
Problem att lösa
Exempel
Fel värde på parameter
public class BankAccount {
private int balance;
/**
* Deposits the specified amount.
* pre: The specified amount is >= 0
* post: The specified amount is added to balance
* @param n The amount to deposit
*/
public void deposit(int n) {
balance = balance + n;
}
...
/**
* Deposits the specified amount.
* pre: The specified amount is >= 0
* post: The specified amount is added to balance
* @param n The amount to deposit
*/
public void deposit(int n) {
balance = balance + n;
}
}
Vad ska hända om man försöker sätta in ett negativt belopp?
...
EDAA01 (Föreläsning 1-2)
VT 2016
33 / 99
Fel i program (”buggar”)
EDAA01 (Föreläsning 1-2)
VT 2016
34 / 99
Exekveringsfel
Olika slags fel
Syntaxfel bryter mot språkets grammatik (syntax).
Exempel: glömt ett {, glömt deklarera en variabel innan den
används ...
Exekveringsfel (Runtime errors eller Exceptions) upptäcks vid exekvering.
Exempel: ArrayIndexOutOfBoundException,
NullPointerException, ...
Logiska fel Programmet kan köras men ger fel resultat.
EDAA01 (Föreläsning 1-2)
VT 2016
35 / 99
Vad händer vid ett exekveringsfel?
Ett objekt (”exception”) skapas som beskriver typen av fel.
Programmet avbryts.
Ett felmeddelande skrivs ut där
typ av fel
stacktrace (sekvensen av metodanrop)
framgår.
EDAA01 (Föreläsning 1-2)
VT 2016
36 / 99
Exception
Exception
Olika typer av fel beskrivs av olika subklasser till klassen Exception.
Exception
Betyder undantag
Exception genereras (”throws”) vid exekveringsfel.
Man kan fånga (”catch”) exception och då själv avgöra hur
felsituationen ska hanteras.
RuntimeException
Man kan skriva kod som genererar exception inuti en metod. (Används
om det uppstår en situation som gör det omöjligt för metoden att
utföra sin uppgift.)
...
IOException
ArrayIndexOutOfBoundException
NullPointerException
FileNotFoundException
...
NoSuchElementException
EDAA01 (Föreläsning 1-2)
VT 2016
37 / 99
EDAA01 (Föreläsning 1-2)
...
Exceptions
Exceptions
Unchecked och checked
Unchecked och checked, forts
VT 2016
38 / 99
Det finns två slag av Exceptions:
Unchecked Exceptions – används då felet beror på programmeraren
Unchecked Exceptions
Ex: NullPointerException eller
ArrayIndexOutOfBoundsException
Subklass till RuntimeException.
Behöver inte fångas.
Exempel: ArrayIndexOutOfBoundException,
NullPointerException
Checked Exceptions – används då felet inte beror på programmeraren
Ex: FileNotFoundException om man försöker öppna en fil som inte
finns
Checked Exceptions
Måste fångas någonstans i anropskedjan, annars kompileringsfel.
Exempel: FileNotFoundException
EDAA01 (Föreläsning 1-2)
VT 2016
39 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
40 / 99
Generera exception
Generera exception
Exempel
Exempel:
/**
* Deposits the specified amount.
* pre: The specified amount is >= 0
* post: The specified amount is added to balance
* @param n The amount to deposit
* @throws IllegalArgumentException if the specified amount is < 0
*/
public void deposit(int n) {
if (n < 0) {
throw new IllegalArgumentException("amount to deposit < 0");
}
balance = balance + n;
}
throw new IllegalArgumentException("amount to deposit < 0");
Mönster:
throw new ExceptionClass();
throw new ExceptionClass(message);
Effekt:
Ett nytt exception-objekt skapas.
Exekveringen av metoden avbryts.
Javasystemet letar efter fångande catch-block.
EDAA01 (Föreläsning 1-2)
VT 2016
41 / 99
Egna exceptionklasser
EDAA01 (Föreläsning 1-2)
VT 2016
42 / 99
Fånga exception
Mönster
Om man vill kan man implementera en egen exceptionklass (behövs
sällan, det finns färdiga exceptionklasser i Javas bibliotek för de flesta
situationer).
Om den ska vara checked:
public class SpellException extends Exception {
...
}
Om den ska vara unchecked:
public class SomeSortOfException extends RuntimeException {
...
}
EDAA01 (Föreläsning 1-2)
VT 2016
43 / 99
try {
// kod som kan generera exception
} catch (ExceptionClass e) {
// kod för att hantera exception
}
try {
// kod som kan generera exception
} catch (ExceptionClass1 e1) {
// kod för att hantera exception av typen ExceptionClass1
} catch (ExceptionClass2 e2) {
// kod för att hantera exception av typen ExceptionClass2
} finally {
// kod som utförs efter try-blocket eller efter catch-blocket
}
EDAA01 (Föreläsning 1-2)
VT 2016
44 / 99
Fånga checked Exceptions
Fånga checked Exceptions
Exempel
Forts
När man anropar en metod som genererar en checked exception måste
man ta hand om det. Normalt fångar man det i en try-catch-sats:
Scanner scan = null;
try {
// försöker öppna en fil med namnet fileName
scan = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
System.err.println("Couldn’t open file " + fileName);
System.exit(1);
}
... använd scan ...
Om exception inträffar, avbryts exekveringen av satserna i try-blocket
och satserna i catch-blocket exekveras.
EDAA01 (Föreläsning 1-2)
VT 2016
45 / 99
Ignorera checked Exceptions
I satsen catch(Exception e) kan t.ex. följande metoder användas
för att få mer information:
e.printStackTrace(); som skriver ut information om raden där felet
inträffat och den/de metodanrop som lett till denna rad.
e.getMessage(); som returnerar en sträng med meddelande om felets
art.
Exempel:
Scanner scan = null;
try {
scan = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
... använd scan ...
EDAA01 (Föreläsning 1-2)
VT 2016
46 / 99
Hantera unchecked exceptions
Man kan ignorera en checked Exception och ”kasta” det vidare till den
anropande metoden.
I så fall måste man ange det i metodrubriken i den metod där
exception genereras:
Metod som genererar unchecked exception behöver inte ange det i sin
rubrik
public Scanner createScanner(String fileName) throws
FileNotFoundException {
// Här genereras exception om filen inte går att öppna
Scanner scan = new Scanner(new File(fileName));
return scan;
}
Kan anges i kommentar
Den som anropar en metod som kan generera en unchecked exception
behöver inte (men kan) fånga den i en try-catch-sats
Leder till exekveringsfel om de inte fångas.
I den metod som anropar createScanner måste man ta hand om
detta exception och kan korrigera felet på valfritt sätt.
EDAA01 (Föreläsning 1-2)
VT 2016
47 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
48 / 99
Generik
Generik
Bakgrund
Introduktion till Generik i Java
Här introduceras generiska klasser och interface.
Mer om generik finns att läsa på OH-bilderna ”Mer om generik” som
finns på kursens hemsida:
generik och arv
wildcards
vektorer och generik
generiska metoder
En klass som hanterar en lista av element ska inte skrivas så att den
bara kan hantera listor med heltal.
Lösningen har i tidigare javaversioner varit att ge parametrar i
metoderna den mest generella typen – Object.
Ex: add-metoden i en lista kunde ha signaturen
Vissa av dessa moment dyker upp och förklaras senare, t.ex. i
samband med laborationer.
EDAA01 (Föreläsning 1-2)
Klasser bör implementeras så att de blir generella d.v.s. går att
använda i många olika sammanhang.
VT 2016
public boolean add(Object x);
49 / 99
Generik
EDAA01 (Föreläsning 1-2)
VT 2016
50 / 99
Generik i Java
Bakgrund forts
Typosäkerhet utan generik!
Ger oss möjlighet att abstrahera över typer
I den gamla modellen kunde man skriva:
Vi kan använda typparametrar när vi definierar en klass. Ex:
myList.add(new Integer(1));
myList.add(new Integer(2));
myList.add(new Person(”Kalle”));
public class ArrayList<E> {...}
Vid användning av en generisk klass anges ett typargument. Ex:
Om avsikten är att listan ska innehålla tal, har vi gjort fel på rad 3.
Kompilatorn kan inte upptäcka detta – koden är korrekt, både Integer
och Person är subklasser till Object.
EDAA01 (Föreläsning 1-2)
VT 2016
51 / 99
ArrayList<Integer> myList = new ArrayList<Integer>();
EDAA01 (Föreläsning 1-2)
VT 2016
52 / 99
Generik i Java
Exempel på en generisk klass
java.util.ArrayList
Utdrag ur den generiska klassen java.util.ArrayList:
Kompilatorn kommer att upptäcka typfel. Ex:
public class ArrayList<E> {
public ArrayList() {...}
public boolean add(E x) {...}
public void add(int index, E x) {...}
public E get(int index) {...}
...
}
ArrayList<Integer> myList = new ArrayList<Integer>();
myList.add(new Person("Kalle"));
ger nu kompileringsfel, myList får enligt sin deklaration endast
innehålla objekt av typen Integer.
Alla add-metoder har inparameter av typen E. Därför kan enbart objekt av
klassen E (eller subklasser till denna) sättas in i listan.
EDAA01 (Föreläsning 1-2)
VT 2016
53 / 99
EDAA01 (Föreläsning 1-2)
Exempel på en generisk klass
Användning av en generisk klass
java.util.ArrayList, forts
java.util.ArrayList
Observera att inte alla metoder i ArrayList<E> har E som typparameter.
T.ex. har contains och remove följande signaturer:
Exempel:
public boolean contains(Object x);
public boolean remove(Object x);
Användare som inte känner till den exakta typen av ett element x ska
kunna anropa metoderna. Dock kommer man att få resultat true om och
endast om x finns i listan (och alltså även är av rätt typ).
EDAA01 (Föreläsning 1-2)
VT 2016
55 / 99
VT 2016
54 / 99
VT 2016
56 / 99
ArrayList<String> list = new ArrayList<String>();
list.add("Lisa");
list.add("Per");
...
String s = list.get(0);
System.out.println(s);
...
EDAA01 (Föreläsning 1-2)
Diskutera
Primitiva datatyper - wrapperklasser
Antag att vi lagrar heltal i en lista:
Primitiva typer i Java:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(5);
int j = list.get(0);
boolean
short
int
long
char
byte
float
double
Varför fungerar detta?
Listan innehåller Integer-objekt.
På andra raden sätter vi in ett heltal (typen int).
På tredje raden har vi deklarerat en variabel j av typen int. Men
metoden get returnerar en referens till ett Integer-objekt.
EDAA01 (Föreläsning 1-2)
VT 2016
57 / 99
Primitiva datatyper - wrapperklasser
Motsvarande wrapperklasser:
Boolean
Short
Integer
Long
Character
Byte
Float
Double
EDAA01 (Föreläsning 1-2)
VT 2016
58 / 99
Autoboxing – unboxing
Exempel
Autoboxing automatisk konvertering från primitiv typ till objekt av
motsvarande wrapperklass
Unboxing automatisk konvertering av objekt av wrapperklass till
motsvarande primitiva typ
int a = 42;
Integer b = new Integer(42);
Exempel:
a
42
Integer
int j =
Integer
i = i +
42
b
Variabeln a har värdet 42, medan variabeln b innehåller en referens till ett
Integer-objekt.
k = 3;
k;
i = new
1;
// autoboxing
// unboxing
Integer(2);
// Unboxing av i för att beräkna i+1.
// Därefter autoboxing av resultatet vid
// tilldelningen.
I tidiga versioner av Java var man tvungen att skriva
i = new Integer(i.intValue() + 1);
EDAA01 (Föreläsning 1-2)
VT 2016
59 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
60 / 99
Autoboxing – unboxing
Implementering av generisk klass
i samband med generiska klasser
Java 1.4
Praktiskt när man vill använda en generisk klass för att lagra element av
primitiv typ. Ex:
public class Container {
private Object item;
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(5);
// Autoboxing till Integer-objekt här.
...
int j = list.get(0); // Unboxing till int här.
}
EDAA01 (Föreläsning 1-2)
VT 2016
61 / 99
Fr o m Java 5.0 generisk klass
public class Container<E> {
private E item;
public Container(Object x) {
item = x;
}
public Container(E x) {
item = x;
}
public Object get() {
return item;
}
public E getItem() {
return item;
}
public void set(Object x) {
item = x;
}
public void setItem(E x) {
item = x;
}
}
EDAA01 (Föreläsning 1-2)
Generisk klass med flera typparametrar
Generisk klass med flera typparametrar
Implementering
Användning
VT 2016
62 / 99
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
Exempel:
Pair<String, Integer> pair = new Pair<String, Integer>("June", 30);
int nbrDays = pair.getValue();
public V getValue() {
return value;
}
public void setValue(V val) {
value = val;
}
...
EDAA01 (Föreläsning 1-2)
VT 2016
63 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
64 / 99
Generiska interface
Restriktioner för typparametrar och typvariabler
Parameter till generisk klass kan inte vara primitiv typ:
SomeClass<int> c = ... // Går inte!
Även interface kan vara generiska. Ex:
Typvariabler kan inte användas för att skapa objekt:
public interface Set<E> {
boolean add(E x);
int size();
boolean contains(Object x);
...
}
public class SomeClass<E> {
public void p() {
E x = new E(); // Fel!
...
Typparametrar kan inte användas för att överlagra metoder:
public class MyClass<T,U> {
public void p(T x) {...}
public void p(U x) {...} // Fel!
...
}
EDAA01 (Föreläsning 1-2)
VT 2016
65 / 99
Introduktion till delar av Javas klassbibliotek
EDAA01 (Föreläsning 1-2)
VT 2016
66 / 99
JCF – Java Collections Framework
Java Collections Framework – interface och klasser för samlingar av
element
interfacen Iterator och Iterable och foreach-sats i Java - används
för att traversera genom en samling element
interfacet Comparable
Är en hierarki av interface, abstrakta klasser och konkreta klasser för
samlingar av element.
Finns i paketet java.util.
Basen i hierarkin är ett interface Collection:
interface Collection<E> {
boolean add(E x);
boolean contains(Object x);
boolean remove(Object x);
boolean isEmpty();
int size();
...
}
Läsanvisningar
Interfacet List och Klassen ArrayList behandlas i avsnitt 2.1.
Fler interface och klasser behandlas senare i kursen/läroboken.
Dokumentation
På Javas hemsida (länk finns på kursens hemsida) finns
dokumentation av Javas standardklasser.
Där finns även tuturials, bl.a. om Javas Collection-klasser.
EDAA01 (Föreläsning 1-2)
VT 2016
67 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
68 / 99
JCF – interface hierarki
JCF – interface hierarki
<<Interface>>
Collection
<<Interface>>
Map
Collection en samling av element, där dubbletter tillåts
Queue en samling av element som utgör en kö
Deque som Queue men man kan sätta in och ta ut element både i
början och i slutet av kön
<<Interface>>
SortedMap
<<Interface>>
Queue
<<Interface>>
List
<<Interface>>
Deque
Set en samling element där dubbletter är förbjudna
<<Interface>>
Set
SortedSet som Set men med krav att elementen går att jämföra
Map en samling av element, där varje element har en en nyckel
och ett värde (jfr. lexikon)
<<Interface>>
SortedSet
EDAA01 (Föreläsning 1-2)
SortedMap som Map men med krav att nycklarna går att jämföra
VT 2016
69 / 99
JCF – några klasser
Interface
Queue
Deque
List
Set
SortedSet
Map
SortedMap
EDAA01 (Föreläsning 1-2)
List en samling element där dubbletter tillåts och där
positionering är möjlig (första, sista, element på plats i, ...)
EDAA01 (Föreläsning 1-2)
VT 2016
70 / 99
Problem att lösa
Antag att vi lagrar ett antal personer i en lista (eller i någon annan
samlingsklass):
Klass
ArrayDeque, LinkedList, PriorityQueue
ArrayDeque, LinkedList
ArrayList, LinkedList
HashSet
TreeSet
HashMap
TreeMap
VT 2016
ArrayList<Person> pList = new ArrayList<Person>();
// här sätts Person-objekt in i samlingen
}
Hur ska vi göra för iterera genom samlingen och behandla alla personerna
(t.ex. skriva ut alla personernas namn)?
71 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
72 / 99
Iteratorer
Iteratorer
Interfacet Iteratorer<E>
Ett iterator-objekt är en instans av en klass som implementerar
interfacet Iterator<E>.
För att iterera genom (traversera) listor eller andra samlingar behöver
vi ett iteratorobjekt.
Ett iteratorobjekt håller reda på en position i listan:
public interface Iterator<E> {
/** Returns true if the iteration has more elements. */
boolean hasNext();
/** Returns the next element in the iteration. */
E next();
}
EDAA01 (Föreläsning 1-2)
VT 2016
73 / 99
Iteratorer
/** Removes from the underlying collection the last
element returned by the iterator (optional). */
void remove();
EDAA01 (Föreläsning 1-2)
VT 2016
74 / 99
Interfacet Iterable<E>
Exempel
Till ArrayList<E> hör en speciell iteratorklass (vars namn vi inte vet).
Denna iteratorklass implementerar interfacet Iterator<E>. I
iteratorklassen finns attribut som håller reda på iteratorns position.
I klassen ArrayList<E> finns en metod iterator() som returnerar
en referens till ett nyskapat iteratorobjekt.
ArrayList<Person> pList = new ArrayList<Person>();
...
Iterator<Person> itr = pList.iterator();
I Java finns följande interface:
public interface Iterable<E> {
/** Returns an iterator over a set of elements of type E */
Iterator<E> iterator();
}
Interfacet Collection ärver interfacet Iterable:
public interface Collection<E> extends Iterable<E> ...
...
Alla klasser som implementerar Collection måste alltså
implementera metoden iterator().
pList
itr
pos 0
EDAA01 (Föreläsning 1-2)
VT 2016
75 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
76 / 99
JCF – interface hierarki
Användning av iterator
med Iterable<E> och Iterator<E>
Exempel
<<Interface>>
Iterable
ArrayList<Person> pList = new ArrayList<Person>();
// här sätts Person-objekt in i samlingen
...
Iterator<Person> itr = pList.iterator();
while (itr.hasNext()) {
Person p = itr.next();
// behandla p
...
}
iterator()
<<Interface>>
Collection
<<Interface>>
Iterator
hasNext()
next()
remove()
<<Interface>>
Queue
<<Interface>>
List
<<Interface>>
Deque
<<Interface>>
Map
<<Interface>>
SortedMap
<<Interface>>
Set
Lägg märke till hur man skaffar sig en iterator – genom att anropa
metoden iterator.
<<Interface>>
SortedSet
EDAA01 (Föreläsning 1-2)
VT 2016
77 / 99
EDAA01 (Föreläsning 1-2)
Metoden iterator()
Implementering av interfacet Iterator<E>
Exempel på collection-klass med metoden iterator
Inre klass
public class ArrayCollection<E> implements Collection<E> {
private E[] theCollection;
private int size;
}
VT 2016
78 / 99
... impl av konstruktor, add, ...
Den klass som implementerar interfacet Iterator kan vara inre klass
i den klass som representerar samlingen.
En inre klass har tillgång till alla attribut i den omgivande klassen.
public Iterator<E> iterator() {
return new ArrayIterator();
}
Den kan vara privat, och ha en en privat konstruktor, eftersom det
bara är den omgivande klassen som skapar instanser.
Inuti klassen ArrayIterator från exemplet på förra bilden kan vi
använda attributen theCollection och size.
private class ArrayIterator implements Iterator<E> {
// Här finns metoderna hasNext, next och remove
}
EDAA01 (Föreläsning 1-2)
VT 2016
I en av övningsuppgifterna kan du träna på att implementera den inre
klassen ArrayIterator.
79 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
80 / 99
foreach-sats i Java
foreach-sats
Exempel
Vektorer
ArrayList<Person> pList = new ArrayList<Person>();
// här sätts Person-objekt in samlingen
...
for (Person p : pList) {
// behandla p
}
Kan också användas för att iterera över elementen i en vektor.
Ex: En metod som skriver ut namn på personer som lagrats i en vektor av
typ Person[]:
Ett sätt att enkelt iterera över samlingar. Man slipper att explicit
använda en iterator.
for (Person p : pList) ... kan läsas som ”för varje p i pList”.
public void print(Person[] a) {
for (Person p : a) {
System.out.println(p.getName());
}
}
Kan användas för objekt av klasser som implementerar Iterable och
för vektorer.
EDAA01 (Föreläsning 1-2)
VT 2016
81 / 99
EDAA01 (Föreläsning 1-2)
foreach-sats
foreach-sats
Begränsningar
Begränsningar
Foreach-sats kan inte användas när man explicit behöver tillgång till
iteratorn i koden.
Exempel: Tag bort alla personer som matchar x ur en ArrayList<Person>
pList:
Iterator<Person> itr = pList.iterator();
while (itr.hasNext()) {
if (itr.next().equals(x)) {
itr.remove();
}
}
VT 2016
82 / 99
Foreach-sats kan inte användas för att iterera parallellt över flera
samlingar, motsvarande följande kod:
ArrayList<Person> list1, list2;
...
Iterator<Person> itr1 = list1.iterator();
Iterator<Person> itr2 = list2.iterator();
while(itr1.hasNext() && itr2.hasNext()) {
System.out.println(itr1.next() + " " + itr2.next());
}
Här behövs iteratorn för att kunna ta bort element.
EDAA01 (Föreläsning 1-2)
VT 2016
83 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
84 / 99
Nästlad foreach-sats
Traversera elementen i en samling
Java 8
I Java 8 har man lagt till metoden forEach i interfacet Iterable.
Exempel:
Däremot går det bra med nästlade loopar.
Ex: Skriv ut alla kombinationer av strängar str1 str2 där str1 finns i
vektorn first och str2 finns i vektorn second. first och second är av
typen String[] :
for (String f : first ) {
for (String s : second) {
System.out.println(f + " " + s);
}
}
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(11);
list.add(12);
list.forEach(e-> System.out.println(e));
// skriver ut alla tal
list.forEach(e-> {
// skriver ut alla jämna tal
if (e % 2 == 0) {
System.out.println(e);
}
});
Det som skicka med som argument till metoden forEach är ett
lambdauttryck – ett block av kod som ska exekveras senare, i det här
fallet när metoden forEach anropas. (Lambdauttryck behandlas på
föreläsning 7.)
EDAA01 (Föreläsning 1-2)
VT 2016
85 / 99
EDAA01 (Föreläsning 1-2)
Diskutera
Jämföra likhet
Söka efter objekt i en lista
Metoden equals
VT 2016
86 / 99
Följande klass beskriver en person:
Metoden equals används för att jämföra om två objekt är lika:
public class Person {
private String name;
private int idNbr;
}
Person p1 = ...;
Person p2 = ;...
if (p1.equals(p2)) {...}
public Person (String name, int idNbr) {
this.name = name;
this.idNbr = idNbr;
}
Metoden equals finns i superklassen Object. Den returnerar true
om och endast om de jämförda objekten är identiska.
Om man istället vill att innehållet inuti objekten ska jämföras måste
man skugga (omdefiniera) equals.
Vad skrivs ut när följande rader exekveras? Förklara varför?
Exempel: Om man vill att två personer ska anses lika när de har
samma id-nummer måste man skugga equals i klassen Person.
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("Fili", 1));
list.add(new Person("Balin", 2));
System.out.println(list.contains(new Person("Balin", 2)));
EDAA01 (Föreläsning 1-2)
VT 2016
87 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
88 / 99
Skugga equals
Skugga equals – med instanceof
Specifikation
public boolean equals(Object obj) {
if (obj instanceof Person) {
return idNbr == ((Person) obj).idNbr;
} else {
return false;
}
}
public boolean equals(Object obj);
Ur equals specifikation:
x.equals(x) ska returnera true (reflexivitet).
Om x.equals(y) returnerar true så ska y.equals(x) returnera
true (symmetri).
Om x.equals(y) returnerar true och y.equals(z) returnerar true
så ska x.equals(z) returnera true (transitivitet).
x.equals(null) ska returnera false.
Observera att parametern till equals måste vara av typ Object,
annars blir det inte skuggning. Därför måste också typomvandling till
Person ske när man ska använda obj:s idNbr.
Uttrycket obj instanceof Person returnerar true om obj:s typ är
Person eller någon subklass till Person.
Uttrycket obj instanceof Person returnerar false om obj har
värdet null.
EDAA01 (Föreläsning 1-2)
VT 2016
89 / 99
Skugga (skugga) equals – med instanceof
EDAA01 (Föreläsning 1-2)
VT 2016
90 / 99
Skugga equals – med getClass
Fördelar och nackdelar
Uttrycket obj instanceof Person returnerar true om obj:s typ är
Person eller någon subklass till Person.
Lösningen tillåter alltså att subklasser ärver equals-metoden.
Man kan använda equals i en arvshieariki och jämföra
”subklassobjekt” och ”superklassobjekt”.
Kan leda till att equals inte uppfyller kraven i specifikationen (om
man t.e.x skuggar equals i subklassen).
Detta undviks om man bara tillåter jämförelser mellan objekt av
samma typ. Se nästa bild.
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
return idNbr == ((Person) obj).idNbr;
}
Metoden getClass returnerar typen för det objekt obj refererar till
under exekveringen.
EDAA01 (Föreläsning 1-2)
VT 2016
91 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
92 / 99
Diskutera
Interfacet Comparable
Sortera objekt
Specifikation
I Java finns ett generiskt interface, Comparable<T>:
Klassen Person beskriver en person. Vad händer när följande rader
exekveras? Förklara varför?
public interface Comparable<T> {
/**
* Compares this object with the specified object for order.
* Returns a negative integer, zero, or a positive integer as
* this object is less than, equal to, or greater than the
* specified object.
*/
public int compareTo(T x);
}
Person[] persons = new Person[4];
persons[0] = new Person("Kili", 1);
persons[1] = new Person("Balin", 2);
persons[2] = new Person("Dori", 4);
persons[3] = new Person("Fili", 3);
Arrays.sort(persons);
for(Person p : persons) {
System.out.println(p);
}
Objekt av klasser som implementerar detta interface går att jämföra
med varandra och kan t.ex. sorteras.
Inuti metoden sort används Comparable som typ för de element som
ska sorteras.
EDAA01 (Föreläsning 1-2)
VT 2016
93 / 99
EDAA01 (Föreläsning 1-2)
Implementering av interfacet Comparable
Jämföra likhet
Exempel
Metoderna compareTo och equals
public class Person implements Comparable<Person> {
private String name;
private int idNbr;
...
public int compareTo(Person x) {
return Integer.compare(idNbr, p.idNbr);
}
94 / 99
Interfacet Comparable innehåller bara metoden compareTo.
Men för klasser som implementerar interfacet Comparable finns det
två sätt att jämföra avseende likhet:
Person p1 = ...;
Person p2 = ;...
if (p1.compareTo(p2) == 0) {...}
if (p1.equals(p2)) {...}
}
public boolean equals(Object obj) {
if (obj instanceof Person) {
return compareTo((Person) obj) == 0;
} else {
return false;
}
EDAA01 (Föreläsning 1-2)
VT 2016
Båda sätten att jämföra bör ge konsistenta resultat.
Därför bör metoden equals skuggas i klasser som implementerar
Comparable.
VT 2016
95 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
96 / 99
Typparametrar med begränsningar
Språkkonstruktioner i Java och delar av Javas klassbibliotek
Exempel på vad du ska kunna
Förklara begreppet interface och deklarera interface i Java
Ibland behöver man ange begränsning på typparmetern:
Skriva klasser som implementerar interface
public class ASortedCollection<E extends Comparable<E>>
Skriva programkod för att fånga exception
Skriva metoder som genererar exception
<E extends T> betyder:
E måste vara subklass till T om T är en klass. Det är också tillåtet att E
= T.
E måste implementera interfacet T om T är ett interface.
Förklara begreppen wrapperklass, autoboxing och unboxing
Förklara begreppet generik, kunna använda respektive implementera
generiska klasser
Använda en iterator för att traversera en samling element
I exemplet ovan anger vi alltså att E måste vara en typ som
implementerar interfacet Comparable<E>. Vi kan därmed använda
metoden compareTo på objekt av typen E i implementeringen av
ASortedCollection.
Implementera iteratorer för enkla datastrukturer som listor och
vektorer
Implementera interfacet Comparable
Formulera testfall och använda JUnit för att testa klasser
Förklara begreppen: skuggning, överlagring, polymorfism
EDAA01 (Föreläsning 1-2)
VT 2016
97 / 99
Datorlaboration 1
generisk klass, testning med jUnit
Implementera en egen generisk klass som beskriver en mängd.
Inuti mängdklassen ska du använda ArrayList<E> för att hålla reda
på mängdens element.
Du har alltså två roller samtidigt:
1
2
implementatör av mängdklassen
användare av ArrayList<E>
Några av metoderna blir korta (en rad räcker). Delegera så mycket
som möjligt till ArrayList<E>.
Innehåll: interface, generisk klass, arv, testning med JUnit (läs PM om
jUnit).
EDAA01 (Föreläsning 1-2)
VT 2016
99 / 99
EDAA01 (Föreläsning 1-2)
VT 2016
98 / 99