EDAA01 Programmeringsteknik - fördjupningskurs Föreläsning 1
Transcription
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 anna.axelsson@cs.lth.se 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