• No results found

Föreläsning 1-2 Innehåll. EDAA01 Programmeringsteknik - fördjupningskurs. Detta kan du... Förkunskaper

N/A
N/A
Protected

Academic year: 2022

Share "Föreläsning 1-2 Innehåll. EDAA01 Programmeringsteknik - fördjupningskurs. Detta kan du... Förkunskaper"

Copied!
27
0
0

Loading.... (view fulltext now)

Full text

(1)

EDAA01 Programmeringsteknik - fördjupningskurs

Läsperiod lp 1+2 (Ges även lp 3) 7.5 hp

anna.axelsson@cs.lth.se http://cs.lth.se/edaa01ht Förkunskapskrav:

Godkänd på de obligatoriska momenten i EDAA45 Programmering, grundkurs eller godkänt betyg på tentamen i denna kurs eller i EDA011, EDA016, EDA017, EDAA20 eller EDA501

EDAA01 (Föreläsning 1-2) HT 2016 1 / 107

Föreläsning 1-2

Innehåll

Introduktion

Kursens mål och innehåll Undervisning

Språkkonstruktioner i Java och delar av Javas klassbibliotek Interface

Exceptions

Generik, Autoboxing - och unboxing

Lagra element – Java Collections Framework (interface och klasser för samlingar av element)

Traversera genom en samling element – interfacen Iterator och Iterable och foreach-sats

Jämföra element – metoden equals, interfacet Comparable

EDAA01 (Föreläsning 1-2) HT 2016 2 / 107

Språkkonstruktioner i Java och delar av Javas klassbibliotek

Undervisningsmoment:

föreläsning 1-2 övningsuppgifter 1-3 laboration 1

Avsnitt i läroboken:

1, 2.1, Appendix A6, A11, A12

I gamla upplagan: 1.1-1.3, 2.1-2.4, 4.1

Detta kan du ...

Förkunskaper

en hel del om programmering och objektorientering begrepp som klass, objekt, attribut, metod, parameter skriva mindre program i programspråket Java

skriva och debugga program i utvecklingsverktyget Eclipse använda vektorer, matriser och (delvis) klassen ArrayList

enkla algoritmer som t.ex. linjärsökning, insättning i en redan sorterad vektor

använda arv – superklass, subklass, abstrakt metod

(2)

Detta ska du lära dig ...

Kursens mål

mer om programmering och objektorientering interface, exceptions, generik ...

formulera och använda olikaalgoritmer för att effektivt lösa problem sökning, sortering ...

rekursiva algoritmer använda olika datastrukturer

listor, binära sökträd, hashtabeller, heapar ...

dels genom att använda färdigaklassbibliotek och dels genom att göra egna implementeringar

skriva program med grafiska användargränssnitt (JavaFX) testa klasser (jUnit)

analysera och jämföra algoritmers tidsåtgång

EDAA01 (Föreläsning 1-2) HT 2016 5 / 107

Mål

Förklaring av termer

Algoritm

Beskrivning hur man stegvis löser ett problem.

Ex: matrecept, linjärsökning Datastruktur

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

EDAA01 (Föreläsning 1-2) HT 2016 6 / 107

Varför är detta viktigt att kunna?

Till skillnad mot övningsprogram är riktiga program stora, skrivs av flera personer, har lång livstid, kräver underhåll . . . .

Därför är följande viktigt:

bra design läsbar kod

att man kan välja lämpliga algoritmer, datastrukturer och färdiga byggstenar (klasser ur bibliotek)

bra verktyg för programutveckling, felsökning och testning

Exempel

Skriv program för att hantera kontakter (namn, mobil nr ...).

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?

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?

Hur söker man snabbt om antal poster är stort är stor?

. . .

(3)

Från problem till program

Specifikation av problemet Design

Val av lösningsmetoder (algoritmer, datastrukturer) för delproblem Implementering (programskrivning) Testning

Underhåll (korrigeringar och uppdateringar)

XX XX XX XX X y

Behandlas i EDA061/F10, OMD

Behandlas i denna kurs

Parallellt: dokumentation

EDAA01 (Föreläsning 1-2) HT 2016 9 / 107

Kursens struktur

Algoritmers effektivitet, tids- komplexitet Interface,

exceptions, generik, JCF, iteratorer

Rekursion

Grafiska användar- gränssnitt

Set, map.

Träd, binära sökträd, hash- tabeller

Sortering

Prioritets- köer, heapar Listor,

stackar köer, länkade strukturer

f 1-2 f 3-4 f 5 f 6 f 7 f 8-10 f 11 f 12

ö1-3, lab1

ö 4-5 lab 2

ö 6 ö 7

lab 3 lab 6

ö 8-11 lab 4-6

ö 12 ö 13

EDAA01 (Föreläsning 1-2) HT 2016 10 / 107

Kursmoment

Laborationer – 6 st lp 1 läsvecka 3, 5, 7 och lp 2 läsvecka 2, 4, 6, obligatoriska

Kräver förberedelser.

Ska lösas i grupper om två. Anmälan till önskad labbgrupp görs på kursens hemsida senastons 31/8.

Inlämningsuppgift – andra halvan av kursenobligatorisk Ska lösas i grupper om två.

Finns på hemsidan. Det finns två alternativ att välja mellan.

Redovisas i läsvecka 7 i lp 2.

Övningsuppgifter

Viktigt komplement till laborationerna.

Löses på egen hand. Uppgifter och lösningsförslag finns på kursens hemsida. Ev. frågestunder, tid och sal på kursens hemsida.

Föreläsningar – 13 st, lp 1 läsvecka 1-7 och lp 2 läsvecka 1-3, 5-7 Föreläsningsbilderna innehåller det viktigaste av kursmaterialet och ger en sammanfattning av kursinnehållet. Bara en delmängd av dem visas

Examination

Skriftlig tentamen

Kursen inrapporteras i Ladok i två delar

Obligatoriska moment (laborationer + inlämningsuppgift) 3 hp Tentamen 4.5 hp

(4)

Lärobok

E. Koffman och A. T. Wolfgang:Data Structures: Abstraction and Design Using Java, Second Edition.

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 har kommit. Överväg denna ifall du köper ny bok.

EDAA01 (Föreläsning 1-2) HT 2016 13 / 107

Relation till andra kurser

För C och D ingår kursen i kurskedjor.

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) HT 2016 14 / 107

CEQ-synpunkter

Överlag nöjda studenter

Några synpunkter från senaste två kursomgångararna:

Lärorika labbar

Väntetid för att få redovisa – Jag ska se över detta och diskutera detta med labbledarna. Ofta finns färdiga testklasser som visar om

programmet fungerar som det ska.

Laborationsförberedelserna tar tid – Ja så är det. Labbarna kräver förberedelser.

Tillfällen att fråga om övningsuppgifterna efterfrågades – Det fanns, men de var ej så välbesökta.

Stressigt i slutet av läsperiod 2 med labb och inlämningsuppgift – Det beror på hur man planerar sitt arbete. Labbarna kan förberedas veckan innan. Inlämningsuppgiften kan påbörjas i slutet av lp 1.

Uppvärmningsuppgift för de som inte programmerat på ett tag önskas – fixat, finns på hemsidan.

Nytt sedan förra kursomgången:

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.

Tentorna påverkas ej av detta. Extentorna är alltså fortfarande aktuella.

Labb 6 (grafiska användargränsnitt) är omarbetad.

Det finns en uppvärmningsuppgift (med ArrayList, arv mm) på kurshemsidan. Lös den ifall du känner dig ringrostig och/eller vill repetera.

(5)

Om att lära sig programmera

Programmering är kul!

Programmering tar tid (fundera ut lösningar, hitta fel ...).

Man lär sig programmera genom att träna. Skriv program, testa, hitta på egna program, experimentera ...

Men inte bara - glöm inte bort teorin.

Starten är viktig. Häng med från början! Det man lär sig kommer att byggas på och användas genom hela kursen.

De olika undervisningsmomenten (övningsuppgifter, labbar, föreläsningar ...) finns av en anledning och kompletterar varandra.

EDAA01 (Föreläsning 1-2) HT 2016 17 / 107

Arv – repetition

Exempel

I ett program ska geometriska figurer (kvadrater och cirklar) hanteras.

Figurerna ska kunna flyttas och ritas upp på skärmen.

Shape(int, int) moveTo(x, y)

draw(SimpleWindow) Shape {abstract}

x y

Circle(int, int, int) radius

Circle side

Square Square(int, int, int)

EDAA01 (Föreläsning 1-2) HT 2016 18 / 107

Arv

Superklassen Shape

public abstract class Shape { protected int x;

protected int y;

protected Shape(int x, int y) { this.x = x;

this.y = y;

}

public void move(int dx, int dy) { x = x + dx;

y = y + dy;

}

public abstract void draw(SimpleWindow w);

}

Arv

Subklassen Square

public class Square extends Shape { private int side;

public Square(int x, int y, int side) { super(x, y);

this.side = side;

}

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);

} }

(6)

Arv

Exempel

public class Main {

public static void main(String[] args) { Shape[] theShapes = new Shape[3];

theShapes[0] = new Square(100, 300, 100);

theShapes[1] = new Square(400, 200, 100);

theShapes[2] = new Circle(400, 400, 50);

SimpleWindow w = new SimpleWindow(600, 600, "Figurer");

for (int i = 0; i < theShapes.length; i++) { theShapes[i].move(10, 10);

}

for (int i = 0; i < theShapes.length; i++) { theShapes[i].draw(w);

} } }

EDAA01 (Föreläsning 1-2) HT 2016 21 / 107

Diskutera

Klassen Shape har den abstrakta metoden draw.

Vad är en abstrakt metod?

Varför finns den abstrakta metoden draw i klassen Shape?

EDAA01 (Föreläsning 1-2) HT 2016 22 / 107

Interface

I ett helt annat program är man bara intresserad av att beräkna figurernas area. Metoderna draw och move behövs ej och då inte heller de

gemensamma attributen x och y. Onödigt att använda arv!

Lösning: Skriv ettinterface Measurable med en abstrakt metod för att beräkna arean. Låt klasserna Square och Circle implementera interfacet.

public interface Measurable { /** Returns the area. */

double area();

}

<<interface>>

Measurable area() : double

Circle(int, int, int) radius

Circle side

Square Square(int, int, int)

Implementera interface

Klassen Square implementerar interfacet Measurable

I en klass som implementerar ett interface måste alla abstrakta metoder i interfacet implementeras:

public class Square implements Measurable { private int side;

public Square(int side) { this.side = side;

}

public double getSide() { return side;

}

public double area() { return side * side;

}

(7)

Interface

Exempel

En variabel av typen Measurable kan referera till objekt av alla klasser som implementerar interfacet:

public class Main {

public static void main(String[] args) {

Measurable[] theShapes = new Measurable[3];

theShapes[0] = new Square(100);

theShapes[1] = new Square(100);

theShapes[2] = new Circle(50);

int sum = 0;

for (int i = 0; i < theShapes.length; i++) { sum += theShapes[i].area();

}System.out.println(sum);

} }

EDAA01 (Föreläsning 1-2) HT 2016 25 / 107

Interface

Betyder ”gränssnitt”.

Innehåller oftast en eller flera publika, abstrakta metoder.

Metoderna är implicit publika och abstrakta, dvs. man behöver inte skriva public abstract ....

public interface Measurable { /** Returns the area. */

double area();

}

EDAA01 (Föreläsning 1-2) HT 2016 26 / 107

Interface

Java 8

Från och med Java 8 kan interface innehålla abstrakta metoder

konstanter statiska metoder default-metoder

public interface Measurable { /** Returns the area. */

double area();

/** Returns a String representation of the area. */

public default String areaAsString() { return String.valueOf(area());

} }

Interface

Implementera flera interface

En klass kan implementera flera interface 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

}

(8)

Interface

Typ

Interface kan användas som typer (precis som klasser) Exempel 1:

Measurable m = new Square(50);

System.out.println(m.area());

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) HT 2016 29 / 107

Interface som typnamn

Genom att använda interfacenamnet som typnamn kan man skjuta upp valet av implementering

lätt byta en implementerande klass mot en annan

Exempel:

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) HT 2016 30 / 107

Exempel: Komplexa tal

Interfacet ComplexNumber

public interface ComplexNumber { /** Returns real part. */

double getRe();

/** Returns imaginary part. */

double getIm();

/** Adds this number and rhs and returns result as a new complex number. */

ComplexNumber add(ComplexNumber rhs);

}

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 double getRe() { return re;

}

public double getIm() { return im;

} ...

(9)

En annan klass som implementerar interfacet

public class PolarComplexNumber implements ComplexNumber { private double r;

private double theta;

public PolarComplexNumber(double re, double im) { r = Math.sqrt(re*re + im*im);

theta = Math.atan2(im, re);

}

/** returns real part */

public double getRe() {

return r * Math.cos(theta);

}

/** returns imaginary part */

public double getIm() {

return r * Math.sin(theta);

} ...

EDAA01 (Föreläsning 1-2) HT 2016 33 / 107

Interface

Kontrakt

Interfacet fungerar som kontrakt eller specifikation.

Flera implementeringar (klasser) kan uppfylla kontraktet.

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.

ComplexNumber c1 = new RectangularComplexNumber(1,2);

ComplexNumber c2 = c1;

c2 = c2.add(c1);

EDAA01 (Föreläsning 1-2) HT 2016 34 / 107

Dokumentationskommentar

En publik metod bör förses med en kommentar på formen /** ... */.

Det är sedan enkelt att framställa javadoc-filer med information om klassen. Kommentaren ska innehålla:

Minst en mening (avslutad med punkt) som beskriver vad metoden gör.

HTML-taggarna @param, @return ... för att beskriva parametrar, returvärde ...

/*** Deposits the specified amount.

* @param n The amount to deposit public void deposit(int n) {*/

balance = balance + n;

}

Pre- och postvillkor (eng. pre- och postconditions)

Kontrakt på metodnivå

I en metods dokumentationskommentar kan man ange pre- och postvillkor.

Previllkor är villkor som måste vara uppfyllda för att en metod ska kunna utföra sin uppgift.

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.

(10)

Pre- och postvillkor

Exempel

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;

} } ...

EDAA01 (Föreläsning 1-2) HT 2016 37 / 107

Problem att lösa

Fel värde på parameter

/*** 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) HT 2016 38 / 107

Fel i program (”buggar”)

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.

Exekveringsfel

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 (exception-objektets typ) stacktrace (sekvensen av metodanrop) framgår.

(11)

Exception

Betyder undantag

Exception genereras (”throws”) vid exekveringsfel.

Man kan fånga (”catch”) exception och då själv avgöra hur felsituationen ska hanteras.

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.)

EDAA01 (Föreläsning 1-2) HT 2016 41 / 107

Exception

Olika typer av fel beskrivs av olika subklasser till klassen Exception.

Exception

RuntimeException IOException

FileNotFoundException

...

ArrayIndexOutOfBoundException

NullPointerException

NoSuchElementException

...

...

EDAA01 (Föreläsning 1-2) HT 2016 42 / 107

Exceptions

Unchecked och checked

Det finns två slag av Exceptions:

Unchecked Exceptions

Subklass till RuntimeException.

Behöver inte fångas.

Exempel: ArrayIndexOutOfBoundException, NullPointerException

Checked Exceptions

Måste fångas någonstans i anropskedjan, annars kompileringsfel.

Exempel: FileNotFoundException

Exceptions

Unchecked och checked, forts

Unchecked Exceptions – används då felet beror på programmeraren Ex: NullPointerException eller

ArrayIndexOutOfBoundsException

Checked Exceptions – används då felet inte beror på programmeraren Ex: FileNotFoundException om man försöker öppna en fil som inte finns

(12)

Generera exception

Exempel:

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) HT 2016 45 / 107

Generera exception

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;

}

EDAA01 (Föreläsning 1-2) HT 2016 46 / 107

Egna exceptionklasser

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 { } ...

Fånga exception

Mönster

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 }

(13)

Fånga exceptions

Exempel

När man anropar en metod som genererar ett exception fångar man normalt 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) HT 2016 49 / 107

Fånga exceptions

Forts

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) HT 2016 50 / 107

Ignorera checked 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:

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;

}

I den metod som anropar createScanner måste man ta hand om detta exception och kan korrigera felet på valfritt sätt.

Hantera unchecked exceptions

Metod som genererar unchecked exception behöver inte ange det i sin rubrik

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.

(14)

Generik

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

Vissa av dessa moment dyker upp och förklaras senare, t.ex. i samband med laborationer.

EDAA01 (Föreläsning 1-2) HT 2016 53 / 107

Generik

Bakgrund

Klasser bör implementeras så att de blir generella d.v.s. går att använda i många olika sammanhang.

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 public boolean add(Object x);

EDAA01 (Föreläsning 1-2) HT 2016 54 / 107

Generik

Bakgrund forts

Typosäkerhet utan generik!

I den gamla modellen kunde man skriva:

myList.add(new Integer(1));

myList.add(new Integer(2));

myList.add(new Person(”Bilbo”));

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.

Generik i Java

Ger oss möjlighet att abstrahera över typer

Vi kan användatypparametrarnär vi definierar en klass. Ex:

public class ArrayList<E> {...}

Vid användning av en generisk klass anges etttypargument. Ex:

ArrayList<Integer> myList = new ArrayList<Integer>();

(15)

Generik i Java

Kompilatorn kommer att upptäcka typfel. Ex:

ArrayList<Integer> myList = new ArrayList<Integer>();

myList.add(new Person("Bilbo"));

ger nu kompileringsfel, myList får enligt sin deklaration endast innehålla objekt av typen Integer.

EDAA01 (Föreläsning 1-2) HT 2016 57 / 107

Exempel på en generisk klass

java.util.ArrayList

Utdrag ur den generiska klassen java.util.ArrayList:

public class ArrayList<E> { public ArrayList() {...}

public boolean add(E x) {...}

public void add(int index, E x) {...}

public E get(int index) {...}

} ...

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) HT 2016 58 / 107

Exempel på en generisk klass

java.util.ArrayList, forts

Observera att inte alla metoder i ArrayList<E> har E som typparameter.

T.ex. har contains och remove följande signaturer:

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).

Användning av en generisk klass

java.util.ArrayList

Exempel:

ArrayList<String> list = new ArrayList<String>();

list.add("Kili");

list.add("Balin");

...String s = list.get(0);

System.out.println(s);

...

(16)

Diskutera

Antag att vi lagrar heltal i en lista:

ArrayList<Integer> list = new ArrayList<Integer>();

list.add(5);

int j = list.get(0);

Hur kan detta fungera?

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) HT 2016 61 / 107

Primitiva datatyper - wrapperklasser

Primitiva typer i Java:

boolean short intlong charbyte float double

Motsvarande wrapperklasser:

Boolean Short Integer LongCharacter ByteFloat Double

EDAA01 (Föreläsning 1-2) HT 2016 62 / 107

Primitiva datatyper - wrapperklasser

Exempel

int a = 42;

Integer b = new Integer(42);

42 b

42 a

Variabeln a har värdet 42, medan variabeln b innehåller en referens till ett Integer-objekt.

Autoboxing – unboxing

Autoboxing automatisk konvertering från primitiv typ till objekt av motsvarande wrapperklass

Unboxing automatisk konvertering av objekt av wrapperklass till motsvarande primitiva typ

Exempel:

Integer k = 3; // autoboxing int j = k; // unboxing Integer i = new Integer(2);

i = i + 1; // 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);

(17)

Autoboxing – unboxing

i samband med generiska klasser

Praktiskt när man vill använda en generisk klass för att lagra element av primitiv typ. Ex:

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) HT 2016 65 / 107

Implementering av generisk klass

Java 1.4

public class Container { private Object item;

public Container(Object x) { item = x;

}

public Object get() { return item;

}

public void set(Object x) { item = x;

} }

Fr o m Java 5.0 generisk klass public class Container<E> {

private E item;

public Container(E x) { item = x;

}

public E getItem() { return item;

}

public void setItem(E x) { item = x;

} }

EDAA01 (Föreläsning 1-2) HT 2016 66 / 107

Generisk klass med flera typparametrar

Implementering

public class Pair<K, V> { private K key;

private V value;

public Pair(K key, V value) { this.key = key;

this.value = value;

}

public V getValue() { return value;

}

public void setValue(V val) { value = val;

}

Generisk klass med flera typparametrar

Användning

Exempel:

Pair<String, Integer> pair = new Pair<String, Integer>("June", 30);

int nbrDays = pair.getValue();

(18)

Generiska interface

Även interface kan vara generiska. Ex:

public interface Set<E> { boolean add(E x);

int size();

boolean contains(Object x);

} ...

EDAA01 (Föreläsning 1-2) HT 2016 69 / 107

Restriktioner för typparametrar och typvariabler

Parameter till generisk klass kan inte vara primitiv typ:

SomeClass<int> c = ... // Går inte!

Typvariabler kan inte användas för att skapa objekt:

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) HT 2016 70 / 107

Introduktion till delar av Javas klassbibliotek

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 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.

JCF – Java Collections Framework

Ä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();

} ...

(19)

JCF – interface hierarki

<<Interface>>

Map

<<Interface>>

SortedMap

<<Interface>>

Collection

<<Interface>>

Queue

<<Interface>>

List

<<Interface>>

Set

<<Interface>>

SortedSet

<<Interface>>

Deque

EDAA01 (Föreläsning 1-2) HT 2016 73 / 107

JCF – interface hierarki

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

List en samling element där dubbletter tillåts och där

positionering är möjlig (första, sista, element på plats i, ...) Set en samling element där dubbletter är förbjudna

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)

SortedMap som Map men med krav att nycklarna går att jämföra

EDAA01 (Föreläsning 1-2) HT 2016 74 / 107

JCF – några klasser

Interface Klass

Queue ArrayDeque, LinkedList, PriorityQueue Deque ArrayDeque, LinkedList

List ArrayList, LinkedList

Set HashSet

SortedSet TreeSet

Map HashMap

SortedMap TreeMap

Diskutera

Antag att vi lagrar ett antal personer i en lista (eller i någon annan samlingsklass):

ArrayList<Person> pList = new ArrayList<Person>();

// här sätts Person-objekt in i samlingen }

Hur ska vi göra för iterera genom listan och behandla alla personerna (t.ex.

skriva ut alla personernas namn)?

(20)

Iteratorer

För att iterera genom (traversera) listor eller andra samlingar kan man använda ett iteratorobjekt.

Ett iteratorobjekt håller reda på en position i listan:

EDAA01 (Föreläsning 1-2) HT 2016 77 / 107

Iteratorer

Interfacet Iteratorer<E>

Ett iterator-objekt är en instans av en klass som implementerar interfacet Iterator<E>.

public interface Iterator<E> {

/** Returns true if the iteration has more elements. */

boolean hasNext();

/** Returns the next element in the iteration. */

E next();

/** Removes from the underlying collection the last element returned by the iterator (optional). */

void remove();

} ...

EDAA01 (Föreläsning 1-2) HT 2016 78 / 107

Iteratorer

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();

pList itr

0

...

Användning av iterator

Exempel

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 } ...

Lägg märke till hur man skaffar sig en iterator – genom att anropa metoden iterator.

(21)

Interfacet Iterable<E>

I Java finns också 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(). Man kan alltså använda en iterator på objekt av alla dessa klasser.

EDAA01 (Föreläsning 1-2) HT 2016 81 / 107

JCF – interface hierarki

med Iterable<E> och Iterator<E>

<<Interface>>

Collection

<<Interface>>

Queue

<<Interface>>

List

<<Interface>>

Set

<<Interface>>

SortedSet

<<Interface>>

Iterable iterator()

<<Interface>>

Iterator hasNext()

next() remove()

<<Interface>>

Map

<<Interface>>

SortedMap

<<Interface>>

Deque

EDAA01 (Föreläsning 1-2) HT 2016 82 / 107

Metoden iterator()

Exempel på collection-klass med metoden iterator

public class ArrayCollection<E> implements Collection<E> { private E[] theCollection;

private int size;

... impl av konstruktor, add, ...

public Iterator<E> iterator() { return new ArrayIterator();

}

private class ArrayIterator implements Iterator<E> { // Här finns metoderna hasNext, next och remove } }

Implementering av interfacet Iterator<E>

Inre klass

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.

Inuti klassen ArrayIterator från exemplet på förra bilden kan vi använda attributen theCollection och size.

Den kan vara privat, och ha en en privat konstruktor, eftersom det bara är den omgivande klassen som skapar instanser.

I en av övningsuppgifterna kan du träna på att implementera den inre klassen ArrayIterator.

(22)

foreach-sats i Java

Exempel

ArrayList<Person> pList = new ArrayList<Person>();

// här sätts Person-objekt in samlingen ...for (Person p : pList) {

// behandla p }

Ett sätt att enkelt iterera över samlingar. Man slipper att explicit använda en iterator. (Men hasNext() och next() anropas i bakgrunden).

for (Person p : pList) ... kan läsas som”för varje p i pList”. Kan användas för objekt av klasser som implementerar Iterable och för vektorer.

EDAA01 (Föreläsning 1-2) HT 2016 85 / 107

foreach-sats

Vektorer

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[]:

public void print(Person[] a) { for (Person p : a) {

System.out.println(p.getName());

} }

EDAA01 (Föreläsning 1-2) HT 2016 86 / 107

foreach-sats

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();

} }

Här kan iteratorn användas för att ta bort element. Man får inte använda listans egna metoder för att lägga till eller ta bort element under

itereringen.

foreach-sats

Begränsningar

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());

}

(23)

Nästlad foreach-sats

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);

} }

EDAA01 (Föreläsning 1-2) HT 2016 89 / 107

Traversera elementen i en samling

Java 8

Fr.o.m. Java 8 finns metoden forEach i interfacet Iterable.

Exempel:

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) HT 2016 90 / 107

Filtrering med metoden removeIf

Java 8

I interfacet Collection finns metoden removeIf som kan användas för att filtrera bort element ur en lista.

Exempel 1: Filtrera bort alla personer som matchar x ur lista pList:

pList.removeIf(p -> p.equals(x));

Exempel 2: Filtrera bort alla udda tal ur listan list:

list.removeIf(n -> n % 2 != 0);

Argumentet är ett lambdauttryck (behandlas på föreläsning 7).

Strömmar

Java 8

Man kan även använda strömmar för att behandla alla element i en samling eller en vektor.

Exempel 1: Skriv ut alla personerna i listan pList:

pList.stream().forEach(p -> System.out.println(p));

Exempel 1: Skriv ut alla personer i listan pList som matchar x:

pList.stream().filter(p -> p.equals(x)).forEach(p -> System.out.println(p));

Du kan läsa mer om strömmar här:

https://docs.oracle.com/javase/tutorial/collections/streams/

(24)

Diskutera

Söka efter objekt i en lista

Följande klass beskriver en person:

public class Person { private String name;

private int id;

public Person (String name, int id) { this.name = name;

this.id = id;

} }

Vad skrivs ut när följande rader exekveras? Förklara varför?

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) HT 2016 93 / 107

Jämföra likhet

Metoden equals

Inuti ArrayList används metoden equals för att jämföra om två objekt är lika:

if (p1.equals(p2)) {...}

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.

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.

EDAA01 (Föreläsning 1-2) HT 2016 94 / 107

Skugga equals

Specifikation

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).

Upprepade anrop av x.equals(y) ska ge samma resultat (konsistens).

x.equals(null) ska returnera false.

Skugga equals – att tänka på

Parametern till equals måste vara av typ Object, annars blir det inte skuggning och den ursprungliga metoden i klassen Object kommer att användas.

De attribut som används i jämförelsen inuti equals bör inte gå att ändra. Deklarera dem final:

public class Person { private String name;

private final int id;

...

Annars kan det bli svårt att hitta objektet när det satts in i en lista eller annan samling.

När man skuggar equals bör man också skugga metoden hashCode.

Metoderna equals och hashCode används när objekt sätts in i en hashtabell. (Behandlas senare i kursen).

(25)

Omdefiniera equals – med instanceof

public boolean equals(Object obj) { if (obj instanceof Person) {

return idNbr == ((Person) obj).idNbr;

} else {

return 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) HT 2016 97 / 107

Skugga (skugga) equals – med instanceof

Fördelar och nackdelar

Denna lösningen tillåter att subklasser ärver equals-metoden.

Man kan därför 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 skuggar equals i subklassen.

Därför är det lämpligt att deklarera metoden equals final:

public final boolean equals(Object obj) { ...

Nu kan inte equals skuggas i någon subklass till Person.

Detta undviks om man bara tillåter jämförelser mellan objekt av samma typ. Se nästa bild.

EDAA01 (Föreläsning 1-2) HT 2016 98 / 107

Skugga equals – med getClass

public boolean equals(Object obj) { if (obj == this) {

return true;

}if (obj == null) { return false;

}if (this.getClass() != obj.getClass()) { return false;

}return id == ((Person) obj).id;

}

Metoden getClass returnerar typen för det objekt obj refererar till under exekveringen.

Bara metoder av exakt samma klass kan anses vara lika.

Skugga equals – med extra metod canEqual

Ibland blir lösningen på förra bilden för sträng. Det kan man lösa genom att lägga till en extra metod i klassen:

public boolean equals(Object obj) { if (obj instanceof Person) {

Person other = (Person) obj;

return other.canEqual(this) && this.id == other.id;

} else {

return false;

} }

public boolean canEqual(Object other) { return (other instanceof Person);

}

Bägge metoderna ska skuggas i subklasser. För detaljer läs mer här:

(26)

Diskutera

Sortera objekt

Klassen Person beskriver en person. Vad händer när följande rader exekveras? Förklara varför?

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);

}

EDAA01 (Föreläsning 1-2) HT 2016 101 / 107

Interfacet Comparable

Specifikation

I Java finns ett generiskt interface, Comparable<T>:

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);*/

}

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) HT 2016 102 / 107

Implementering av interfacet Comparable

Exempel

public class Person implements Comparable<Person> { private String name;

private int id;

...

public int compareTo(Person x) {

return Integer.compare(id, p.id); } public boolean equals(Object obj) {

if (obj instanceof Person) {

return compareTo((Person) obj) == 0;

} else {

return false;

} }

Jämföra likhet

Metoderna compareTo och equals

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)) {...}

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.

(27)

Typparametrar med begränsningar

Ibland behöver man ange begränsning på typparmetern:

public class ASortedCollection<E extends Comparable<E>>

<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.

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.

EDAA01 (Föreläsning 1-2) HT 2016 105 / 107

Språkkonstruktioner i Java och delar av Javas klassbibliotek

Exempel på vad du ska kunna

Förklara begreppet interface och deklarera interface i Java Skriva klasser som implementerar interface

Skriva programkod för att fånga exception Skriva metoder som genererar exception

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 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) HT 2016 106 / 107

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 implementatör av mängdklassen

2 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).

References

Related documents

Trafikverket får medel till att göra åtgärder på de vägar som Trafikverket är väghållare för genom den Nationella Transportplanen samt den Region- ala Transportplanen för

d) Kunden får inte lov att göra förändringar i Tjänsten för att därefter sälja, kopiera eller överlåta Tjänsten till annan part även om detta sker under annat namn. Kunden

Översikt Kurswebbsidan Mål Kursmoment Kurslitteratur Betyg Frivilliga moment Bonuspoäng Datorkonto Hjälp/redovisning.. Viktiga datum Lärarna Studentrepresentant

• På skannerpennan, tryck på ikonen för att välja, då visas sedan öppnar du appen, klickar på [Anslutning] längst upp till höger på bildskärmen, välj WorldPenScan Go-modell

Om alternativen inte visas i dialogrutan Acrobat Indexsökning, kan du återställa dem genom att stänga dialogrutan Indexsökning, välja Redigera &gt; Inställningar &gt; Allmänt

Att fler elever, särskilt i våra socialt eftersatta områden, får ta del av fritidsklubbar- nas verksamhet är värd den kostnadsökning som det skulle innebära för staden att ta

Koppla ifrån all extern kringutrustning, telefon- eller telekommunikationsledningar och elkontakt (t.ex. extern strömförsörjning, batteri etc.) innan utökningsplatsluckan tas

Koppla ifrån all extern kringutrustning, telefon- eller telekommunikationsledningar och elkontakt (t.ex. extern strömförsörjning, batteri etc.) innan utökningsplatsluckan tas