Föreläsning 8. Undantag Designmönstert Strategy Gränssnittet Comparable Gränssnittet Comparator

Relevanta dokument
Föreläsning 8. Undantag Designmönstert Strategy Gränssnittet Comparable Gränssnittet Comparator

Föreläsning 8. Undantag Gränsnittet Comparator Gränssnittet Comparable Designmönstert Strategy

Testning av program. Verklig modell för programutveckling

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Att skriva till och läsa från terminalfönstret

Objektorienterad Programkonstruktion. Föreläsning 4 8 nov 2016

Föreläsning 5. Gränsnittet Comparable. Gränssnittet Comparator. Undantag

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Idag. Exempel, version 2. Exempel, version 3. Ett lite större exempel

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Föreläsning 12. Föreläsning 12. Rörliga figurer Klassen Timer Undantag Något om applets. Rörliga appletsfigurer Klassen Timer Undantag

Klassen javax.swing.timer

Föreläsnings 9 - Exceptions, I/O

1 Comparator & Comparable

Outline. Objektorienterad Programmering (TDDC77) En frukt har ett namn. Man kan lägga en frukt i en korg... Hashing. Undantag. Ahmed Rezine.

Objektorienterad Programmering (TDDC77)

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Föreläsning 3 Innehåll

Diskutera Sortera objekt

OOP Objekt-orienterad programmering

Föreläsning 3 Innehåll. Generiska klasser. Icke-generisk lista ArrayList, skiss av implementering. Icke-generisk lista Risk för fel

Testning och felhantering

Språkkonventioner och redigering av tal.

Lösningsförslag till omtentamen för TDA540 Objektorienterad Programmering

Recitation 4. 2-D arrays. Exceptions

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

DAT043 - föreläsning 8

Felhantering TDDD78, TDDE30, 729A

Objektorienterad programmering

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Objektorienterad Programmering (TDDC77)

Command line argumenter. Objektorienterad Programmering (TDDC77) Vad blir resultatet? Nu då? Ahmed Rezine. Hösttermin 2016

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Övning vecka 6. public void method2() { //code block C method3(); //code block D }//method2

DAT043 Objektorienterad programmering för D, DIT011 Objektorienterad programvaruutveckling för GU

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Repetition av OOP- och Javabegrepp

Undantagshantering. Fördjupad Java. Fel. Undantag. Fånga Undantag. Grupper av Undantag

Undantagshantering. Fördjupad Java. Undantag. Fel. Grupper av Undantag. Fånga Undantag

Tentamen FYTA11 Javaprogrammering

Objektorienterad Programkonstruktion. Föreläsning 2 2 nov 2016

Lösningar för tenta 2 DAT043,

Repetition av OOP- och Javabegrepp

Instuderingsuppgifter läsvecka 6 - LÖSNINGAR

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 2

Classes och Interfaces, Objects och References, Initialization

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

DAT043 Objektorienterad Programmering

Objektorienterad programmering

Undantag. Engelska: exceptions. Skansholm: exceptionella händelser

Objektorienterad programmering i Java

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Outline. Objektorienterad Programmering (TDDC77) Signatur. Klassen calculator. Överlagring (overloading) Arv (inheritance) Ahmed Rezine

Kungl. Tekn. Högskolan Förel 1, bild 1 Föreläsning 1: Introduktion ffl Kursinnehåll ffl Javarepetition ffl Referenser ffl Nyckelordet static ffl Klass

Lösningsförslag, tentamen FYTA11 Javaprogrammering

DI-institutionen Sid 1 av 6 Hans-Edy Mårtensson Sten Sundin

Fördjupad Java. Undantagshantering. Fel

DAT043 - Föreläsning 7

Objektorienterad Programmering DAT043. Föreläsning 4 23/1-18 Moa Johansson (delvis baserat på Fredrik Lindblads material)

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Objektorienterad Programmering (TDDC77)

Tentamen ID1004 Objektorienterad programmering May 29, 2012

Kopiering av objekt i Java

Övning 4. I denna övning ska vi titta på icke-muterbarhet kontra muterbarhet, samt metoderna equals, hashcode och clone.

Felsökning, UML. Översikt. Java starkt typat. Typomvandling (casting) Exempelhierarki. Stark typning

Överlagring, static, testning, formella metoder och undantag! Förelasning 13!! TDA540 Objektorienterad Programmering!

Objektorienterad programmering E. Telefonboken, än en gång. Gränssnitt. Telefonboken med gränssnitt specificerat, del 1.

Javas Exceptions. DD2385 Programutvecklingsteknik Fler bilder till föreläsning 7 23/ Kort om Javas Exceptions Trådar i Java

Algoritmer. Två gränssnitt

Laboration 13, Arrayer och objekt

F4. programmeringsteknik och Matlab

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Föreläsnings 10 - Överlagring, Konstruerare, Arv, Mer Exceptions, Reguljära Uttryck

FÖRSLAG TILL LÖSNINGAR FÖR TENTAMEN I INTERNETPROGRAMMERING MED JAVA, 5p för SY , kl

Parallellism, återblick

Omtentamen för TDA540 Objektorienterad Programmering. Institutionen för Datavetenskap CTH HT-17, TDA540. Dag: , Tid:

Sammanfattning och repetition utgående från typiska tentamensuppgifter

TENTAMEN OOP

Tentamen LÖSNINGSFÖRSLAG. c) Tilldelningen C x = new D() ger kompileringsfel eftersom klassen D är abstrakt.

Outline. Objektorienterad Programmering (TDDC77) Åsidosättning. Signatur. Åsidosättning. Abstrakta klasser. Ahmed Rezine.

Abstrakt datatyp. -Algoritmer och Datastrukturer- För utveckling av verksamhet, produkter och livskvalitet.

Länkade strukturer, parametriserade typer och undantag

Felhantering. Andra brott mot språkets regler. Man kan också i programmet bryta mot ett antal olika regler som gäller. Exempelvis:

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Lösningsförslag till tentamen

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

Tänk på följande: Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Parsing med Recursive Descent, Avbildningsklasser. Syntaxdiagram. Syntaxdiagram och kodning expression. Betrakta följande uttryck

Föreläsning 3. Stack

Uno Holmer, Chalmers, :17 Uno Holmer, Chalmers, :17

Föreläsning 3. Stack

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 3

Föreläsning REPETITION & EXTENTA

TENTAMEN: Objektorienterad programmering. Läs detta! Skriv din tentamenskod på varje blad (så att vi inte slarvar bort dem).

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Transkript:

Föreläsning 8 Undantag Designmönstert Strategy Gränssnittet Comparable Gränssnittet Comparator Fel i program När man skriver program uppkommer alltid olika typer av fel: Kompileringsfel, fel som beror på att programmeraren bryter mot språkreglerna. Felen upptäcks av kompilatorn och är enkla att åtgärda. Kompileringsfelen kan indelas i syntaktiska fel och semantiska fel. Exekveringsfel, fel som uppkommer när programmet exekveras och beror på att ett uttryck evalueras till ett värde som ligger utanför det giltiga definitionsområdet för uttryckets datatyp. Felen uppträder vanligtvis inte vid varje körning utan endast då vissa specifika sekvenser av indata ges till programmet. Logiska fel, fel som beror på ett tankefel hos programmeraren. Exekveringen lyckas, men programmet gör inte vad det borde göra. Alla utvecklingsmiljöer (JGrasp, Eclipse, NetBeans, etc) tillhandahåller verktyg för debugging, lär dej att använda dessa i den utvecklingsmiljö du använder.

Orsaker till exekveringsfel Orsaker till att exekveringsfel uppstår: Oförutsägbara externa problem. Nätverket gick ner, hårddisken är full, minnet är slut, databasen har kraschat, DVD:n var inte insatt, osv. Felaktig användning. Användaren har inte läst dokumentationen, dvs följer inte uppställda förvillkor. Brister i koden. Programmeraren har inte gjort sitt arbete. Koden innehåller buggar (t.ex. refererar till ett objekt som inte finns, adresserar utanför giltiga index i ett fält och representations exponering). Exekveringsfel i ett program Kod metodanrop method() { När allt går som man förväntar sig. Kod metodanrop felmeddelande method() { När något går galet. För att hantera felet måste den anropande koden kunna tolka felmeddelandet och vidta lämpliga åtgärder.

Fel i ett program Har programspråket inga inbyggda mekanismer för felhantering, måste felhanteringen ske via konventioner. public class PurchaseOrder { public static final double ERROR_CODE1 = 1.0; private Product prod; private int quantity; public class double PurchaseOrder totalcost() { { if (quantity < 0) public return static ERROR_CODE1; final double ERROR_CODE1 = 1.0; private else Product prod; return prod.getprice() * quantity; private //totalcost int quantity; //PurchaseOrder public double totalcost() { Problem: if (quantity < 0) Det finns oftast många olika typer av fel, d.v.s. många felkoder. Felkoderna return måste ha ERROR_CODE1; samma typ som metoden normalt returnerar. Leder till else att koden blir komplex och svårläst. return prod.getprice() * quantity; //totalcost //PurchaseOrder Hantering av exekveringsfel i Java Java använder exceptions (undantag) för att hantera exekveringsfel. Ett exception är ett objekt som påtalar en avvikande eller felaktig situation i ett program. Java tillhandahåller följande konstruktioner för exceptions: konstruktioner för att "kasta" exceptions (konstruktionen throw) konstruktioner för att "specificera" att en metod kastar eller vidarebefordrar exceptions (konstruktionen throws) konstruktioner för att fånga exceptions (konstruktionerna try, catch och finally). Felhanteringen blir därmed en explicit del av programmet, d.v.s. felhanteringen blir synlig för programmeraren och kontrolleras av kompilatorn.

Kasta exceptions public class PurchaseOrder { private Product prod; private int quantity; public double totalcost() throws IllegalQuantityException { if (quantity < 0) Deklarerar att ett exception kastas public throw class new PurchaseOrder IllegalQuantityException("quantity { is < 0"); else private return Product prod.getprice() prod; * quantity; private //totalcost int quantity; Ett exception //PurchaseOrder kastas public double totalcost() throws IllegalQuantityException { if (quantity < 0) throw new IllegalQuantityException("quantity is < 0"); else return prod.getprice() * quantity; //totalcost Klasshierarkin för exceptions En exception är ett objekt som tillhör någon subklass till standardklassen Throwable. Det finns två standardiserade subklasser till Throwable: klasserna Exception och Error. Throwable Error Exception

Klasserna Error och Exception Klassen Error används av Java Virtual Machine för att signalera allvarliga interna systemfel t.ex. länkningsfel, hårddisken är full och minnet tog slut. Vanligtvis finns inte mycket att göra åt interna systemfel. Vi kommer inte att behandla denna typ av fel ytterligare. De fel som hanteras i "vanliga" program tillhör subklasser till Exception. Denna typ av fel orsakas av själva programmet eller vid interaktion med programmet. Sådana fel kan fångas och hanteras i programmet. Hantering av exceptions Hur kan ett exception (fel) hanteras? Kod metodanrop exception method() { Man kan ha olika ambitionsnivåer: Ta hand om det och försöka vidta någon lämplig åtgärd så att exekveringen kan fortsätta. Fånga det, identifiera det och kasta det vidare till anropande programenhet. Ignorera det, vilket innebär att programmet avbryts om felet inträffar. Java skiljer mellan två kategorier av exceptions - checked exceptions - unchecked exceptions

Checked och unchecked exceptions Checked exceptions måste hanteras i programmet: antingen fånga det eller ange i den s.k. händelselistan i metodhuvudet att det kastas vidare public int method() throws CheckedException { Throwable Error Checked exceptions tillhör klassen Exception eller någon subklass till denna klass (förutom subklassen RuntimeException). Unchecked exceptions behöver inte specificeras i händelselistan. Unchecked exceptions tillhör klasserna Error eller RuntimeException eller någon subklass till dessa klasser. Exception RuntimeExecption unchecked unchecked checked Anrop av metoder som kastar exceptions Från API-dokumentationen kan vi se att metoden parseint, i klassen java.lang.integer, kastar en NumberFormatException om parametern s som ges till metoden inte kan översättas till ett heltal.

Anrop av metoder som kastar exceptions Från API-dokumentationen kan vi se att konstruktorn Scanner(File source), kastar en FileNotFoundException om filen source som ges som parameter inte finns. Feltyper i Java I dokumentationen av en exception, kan man se om den är checked eller unchecked. Checked exception subtyp till Exception Unhecked exception subtyp till RuntimeException

Att kasta exceptions vidare Fel kan oftast inte hanteras där de inträffar! Save Do you want to replace the file? No Yes gui.saveaction() exception filehandler och document vet inte vad som skall göras när filen redan existerar! Därför skickar de en exception vidare uppåt i anropskedjan. gui vet vad som skall göras åt felet! document.save(filename) exception filehandler.save(text, filename) throw new FileAlreadyExistException(fileNamne + " exists."); Kasta exceptions //save //Document public class Document { private FileHandler filehandler; private String thedocument;. public void save(string filename) throws FileAlreadyExistException { filehandler.save(thedocument, filename); //save //Document public class FileHandler {. public void save(string text, String filename) throws FileAlreadyExistException { File f = new File(fileName); if (f.exists()) throw new FileAlreadyExistException(fileNamne + " exists."); //save //Document Kan inte åtgärda felet! Detekterar felet, men kan inte åtgärda det!

Fånga exceptions "An exception will be thrown when semantic constraints are violated and will cause a non-local transfer of control from the point where the exception occurred to a point that can be specified by the programmer." "During the process of throwing an exception, the Java virtual machine abruptly completes, one by one, any expressions, statements, method and constructor invocations, initializers, and field initialization expressions that have begun but not completed execution. This process continues until a handler is found that indicates that it handles that particular exception by naming the class of the exception or a superclass of the class of the exception." // JLS 11 Om ingen exception handler finns terminerar programmet! finally { Att fånga // satser exceptions som utförs oberoende av om exceptions har inträff För att fånga exceptionella händelser används try-catch-finally konstruktionen. try { // anrop av metod(er) som kan kasta exceptions catch (ExceptionOne e) { // exception handler för klassen ExceptionOne eller subklasser // till denna klass catch (ExceptionTwo e) { // exception handler för klassen ExceptionTwo eller subklasser // till denna klass finally { // satser som utförs oberoende av om exceptions har inträffat eller inte

Att fånga exceptions När ett exception inträffar i ett try-block avbryts exekveringen och exception kastas vidare. Finns ett catch-block som hanterar den typ av exception som inträffat, fångas exception och koden i catch-blocket utförs. Därefter fortsätter exekveringen med satserna efter catch-blocken. Man hoppar aldrig tillbaks till try-blocket. Ett godtyckligt antal catch-block får finnas. Ett catch-block fångar alla exception som är av specificerad klass eller subklasser till denna. catchsatserna genomsöks sekventiellt. Ordningen av catch-blocken är således av betydelse. Finns ett finally-block exekveras detta oavsett om ett exception inträffar eller ej. Om inget catch-block finns för den klass av exceptions som inträffat kastas exception vidare till den anropande metoden. Checked exceptions som kastas från en metod måste anges i metodens händelselista. Anropsstacken Då ett program körs och en metod anropas används anropsstacken. All data som behövs vid anropet, t.ex. parametrar och återhoppsadress, sätts samman till en s.k. stackframe och läggs upp på anropsstacken. Då metoden är klar avläses eventuellt resultat varefter stackframen tas bort från stacken. Exekveringen fortsätter vid angiven återhoppsadress. Antag att metoden a anropar metoden b som anropar metoden c. a läggs på stacken, anropar b b läggs på stacken, anropar c c läggs på stacken c klar, c tas bort från stacken, exekveringen fortsätter i b b klar, b tas bort från stacken, exekveringen fortsätter i a a klar, a tas bort från stacken

Anropsstacken Då ett undantag uppstår avbryts det normala flödet och programmet vandrar tillbaks genom anropsstacken. Hanteras inte undantaget någonstans kommer programmet att avbrytas med en felutskrift. Method where error occurred Method without an exception handler Method with an exception handler Method call Method call Method call Throws exception Forwards exception Catches exception Method where error occurred Method without an exception handler Method with an exception handler Looking for appropiate handler Looking for appropiate handler main main //saveaction Att fånga exceptions //GUI Do you want to replace the file? Save No Yes public class GUI { private Document document;. public void saveaction(string filename) { try { document.save(filename); catch (FileAlreadyExistException e) { replacedialog(filename); //saveaction //GUI gui.saveaction() exception document.save(filename) exception filehandler.save(text, filename)

Flera catch-block Exception IOException EOFException public void p() { try { m1(); m2(); catch (EOFException e) { //kör om metoden p kastar EOFException catch (IOException e) { //kör om metoden p kastar IOException public void p() { //p try { m1(); m2(); catch (EOFException e) { public void m1() throws IOException { public void m2() throws EOFException { public void m1() throws IOException { public void q() { public void m2() throws EOFException { //q try { m1(); m2(); catch (IOException e) { public void q() { try { m1(); m2(); catch Kompileringsfel! (IOException e) { Det andra catch-blocket är oåtkomligt! catch (EOFException e //q catch (EOFException e) { Vilka exceptions kan en metod kasta? Exception IOException EOFException public void m1() throws Exception { throw new IOException(); public void m2() throws EOFException { throw new IOException(); Det är tillåtet att kasta en subtyp till den exceptiontyp som metoden deklarerar.

Att kasta egna exceptions Det är möjligt att skapa och kasta egendefinierade exceptions. Denna möjlighet skall dock användas restriktivt återanvändning av existerande exceptiontyper från API:n oftast bättre. När man skall kasta ett eget exception måste man först bestämma om det skall vara checked eller unchecked. Unchecked exceptions: Används för programmeringsfel, d.v.s. fel som programmerarna själva är ansvariga för. Dessa undantag skall inte fångas. Ju snabbare de inträffar dessdå bättre (fail fast). Checked exceptions: Används för fel som inträffar vid interaktionen med programmet och som är möjliga att hantera (programmet skall inte terminiera). Till exempel skall inte en databasfråga som resulterar i att man inte hittar det eftersökta göra att programmet avslutas. Att kasta egna exceptions Egna exceptionsklasser erhålls genom att skapa subklasser till klassen Exception (checked) eller till klassen RuntimeException (unchecked): public class ExceptionName extends Exception { public ExceptionName() { super(); public ExceptionName(String str) { super(str); Konstruktorn ExceptionName(String str) används för att beskriva det uppkomna felet. Beskrivningen kan sedan läsas när felet fångas m.h.a. metoden getmessage(), som ärvs från superklassen Throwable. Om felet inte fångas i programmet kommer den inlagda texten att skrivas ut när programmet avbryts. Även metoden printstacktrace() ärvs från Throwable. Denna metod skriver ut var felet inträffade och "spåret" av metoder som sänt felet vidare. Metoden printstacktrace() anropas automatiskt när en exception avbryter ett program.

Kasta exceptions med rätt abstraktionsnivå Det är förvillande om en metod kastar ett exception som inte har någon uppenbar koppling till den uppgift som metoden utför. try { catch (LowLevelException e) { throw new HighLevelException(s); try { catch (LowLevelException e) { //returns: x such that ax^2 + bx + c = 0 //throws: NoRealSolutionsException if no real solutions exist public double throw solvequad(double new HighLevelException(s); a, double b, double c) throws NoRealSolutionsException { try { return (-b + Math.sqrt(b *b - 4 * a * c) / (2 * a); catch (IllegalArgumentException e) { throw new NotRealSolutionException("No real solutions exists"); //returns: //solvequad x such that ax^2 + bx + c = 0 //throws: NoRealSolutionsException if no real solutions exist public double solvequad(double a, double b, double c) throws NoRealSolution Exception Swallowing // BAD! BAD! BAD! try{ // Possible exception. catch (SomeException e) { // Empty, nothing here, but exception handled // program will continue. // So exception unnoticed from now on. Detta är det sämsta tänkbara sättet att hantera exceptions! Endast acceptabelt om det går att bevisa att SomeException aldrig kan inträffa.

Dokumentation av exceptions Både checked och unchecked exceptions som kastas är en del av metodens kontrakt och skall dokumenteras med Javadoc: /** * * @throws IllegalArgumentException if parameter args is null * @throws NoSuchFileException if referencing a non-existing file */ public void makesomething(string args) throws IllegalArgumentException, /** NoSuchFileException { *. * @throws //makesomething IllegalArgumentException if parameter args is nul * @throws NoSuchFileException if referencing a non-existing */ public void makesomething(string args) throws IllegalArgum NoSuchFile. finally-blocket Rätt använt är finally-blocket mycket användbart för att frigöra resurser eller återställa objekt till väldefinierade tillstånd då fel inträffar. Det finns ett antal användbara tekniker. Exempel: Vid läsning av eller skrivning på en fil skall filen alltid stängas, annars riskerar man att data kan gå förlorat. public FileReader(String filename) throws FileNotFoundException kastar FileNotFoundException om filen inte existerar eller inte kan öppnas för läsning public String readline() throws IOException kastar IOException om läsningen misslyckas public void close() throws IOException kastar IOException om stängningen misslyckas

finally-blocket import java.io.*; public final class SimpleFinally { public static void main(string[] args) throws IOException { simplefinally("test.txt"); Metoden skickar alla undantag vidare. Metoden skickar alla undantag v import java.io.*; //main public private final static class void simplefinally(string SimpleFinally afilename) { throws IOException { //If this line throws an exception, then neither the public //try block static nor the void finally main(string[] block will execute. args) throws IOException { simplefinally("test.txt"); //That is a good thing, since reader would be null. BufferedReader reader = new BufferedReader(new FileReader(aFileName)); //main try { private //Any static exception void in the simplefinally(string try block will cause the finally block afilename) to execute throws IOException String line = null; //If while this ( (line = throws reader.readline()) an exception,!= null ) { then neither the //try //process block the nor line... the finally block will execute. finally { //That is a good thing, since //The reader reader object would will never be null. be null here. BufferedReader reader = new //This BufferedReader(new finally is only entered after the try FileReader(aFileNa block is entered. reader.close(); try { //Any exception in the //simplefinally try block will cause the finally block to execut //SimpleFinally String line = null; while ( (line = reader.readline())!= null ) { //process the line... finally { finally-blocket import java.io.*; public final class NestedFinally { public static void main(string[] args) { nestedfinally("test.txt"); //main private static void nestedfinally(string afilename) { try { //If the constructor throws an exception, the finally block will NOT execute BufferedReader reader = new BufferedReader(new FileReader(aFileName)); try { String line = null; while ( (line = reader.readline())!= null ) { //process the line... catch (IOException ex) { ex.printstacktrace(); //nestedfinally Metoden fångar alla undantag. //NestedFinally try..finally nästlad med try..catch finally { //no need to check for null, any exceptions thrown here //will be caught by the outer catch block reader.close(); catch (IOException ex) { ex.printstacktrace(); //nestedfinally //NestedFinally

finally-blocket import java.io.*; public final class CatchInsideFinally { public static void main(string[] args) { catchinsidefinally("test.txt"); Metoden fångar alla undantag. try..catch inuti finally Metoden fångar alla undant try..catch inuti finally catch(ioexception ex){ ex.printstacktrace(); finally { try { //need to check for null if ( reader!= null ) { reader.close(); import //main java.io.*; private static void catchinsidefinally(string afilename) { public final class CatchInsideFinally { //Declared here to be visible from finally block public BufferedReader static void reader main(string[] = null; args) { try { catchinsidefinally("test.txt"); //if this line fails, finally will be executed, //main//and reader will be null reader = new BufferedReader( private static void new catchinsidefinally(string FileReader(aFileName)); afilename) { //Declared String line here = null; to be visible from finally block while ((line = reader.readline())!= null ) { BufferedReader //process the line... reader = null; try { //catchinsidefinally //if this line fails, finally will be executed, //CatchInsideFinally //and reader will be null reader = new BufferedReader( new FileReader(aFileName)); catch(ioexception ex) { ex.printstacktrace(); catch( ex.p finally try // if Exceptions och överskuggning Vid överskuggning får metoden i subklassen inte kasta en exception med vidare typtillhörighet. Exception IOException RuntimeException @Override public void m2() throws Ex public class Sup { public void m1() throws Exception { public void m2() throws RumtimeException { EOFException IllegalArgumentException public class Sub extends Sup { @Override public void m1() throws IllegalArgumentException { @Override public void m2() throws Exception {

Exceptions: Sammanfattning Finns ingen allmänt accepterad best practices. Använd unchecked exceptions för programmeringsfel, men överväg noga om det borde vara förvillkor och assertions istället. Använd checked exception då det kan antas att klienten verkligen kan åtgärda det uppkomna felet. Throw early, catch late. Kasta ett exception direkt när felet upptäcks, åtgärda felet där det kan åtgärdas. Kasta exceptions som är på rätt abstraktionsnivå. Använd företrädesvis fördefinierade exceptions. Dokumentera alla exceptions (både checked och unchecked) som en metod kastar. Inkludera information som beskriver felorsaken när ett exception kastas. Använd inte tomma catch-block (swallowing exceptions). // code for sorting Integer arrays Case study: Sortering // methods for sorting other arrays Problem: Skapa en klass Sorter som kan sortera alla typer av fält. En första design: public class Sorter { public static void sort(string[] data) { // code for sorting String arrays public static void sort(integer[] data) { // code for sorting Integer arrays // methods for sorting other arrays +sort(integer[]): void +sort(string[]): void... more sort methods Integer[ ] uses Sorter uses String[ ]

Problem med den första versionen För varje specifik typ av array måste det finnas en specifik metod i klassen Sorter. - Vad händer som vi i framtiden inför nya typer? Mycket kod är duplicerad i metoderna. - Kan vi undvika detta? I bland vill man sortera på något annat sätt än i växande ordning. - Hur kan vi åstadkomma detta? Duplicerad kod public class Sorter { public static void sort(integer[] data) { for (int i = data.length-1; i >= 1; i--) { int indexofmax = 0; for (int j = 1; j <= i; j++) { if (data[j] > data[indexofmax]) indexofmax = j; //sort Integer temp = data[i]; data[i] = data[indexofmax]; data[indexofmax] = temp; //sort // methods for sorting other a //Sorter public static void sort(string[] data){ for (int i = data.length-1; i >= 1; i--) { int indexofmax = 0; for (int j = 1; j <= i; j++) { if (data[j].compareto(data[indexofmax]) > 0) indexofmax = j; String temp = data[i]; data[i] = data[indexofmax]; data[indexofmax] = temp; //sort // methods for sorting other arrays //Sorter

Skillnader i koden Vi notera att metoderna är identiska förutom att fälten i parameterlistorna har olika typer de använder olika sätt att jämföra två värden; - operationen > för Integer - metoden compareto för String de använder olika typer på den lokala variabeln temp. För att undvika duplicering av kod vill vi skapa en metod som är generisk (allmängiltigt) för alla typer av fält. public int compare(integer o1, Integer o2) return o1 - o2; Steg 1: Inför en //compare ny klass Comparator //more compare methods for other types För att eliminera skillnaden i hur de båda metoderna jämför objekt //Comparator inför vi en ny klass Comparator, vars uppgift är att utföra jämförelserna åt oss. Klassen innehåller överlagrade compare-metoder för de typer av objekt vi vill hantera. public class Comparator { public int compare(string o1, String o2) { return o1.compareto(o2); //compare public int compare(integer o1, Integer o2) { return o1 - o2; //compare //more compare methods for other types //Comparator

Steg 2: Använd klassen Comparator public class Sorter { public static void sort(integer[] data, Comparator comp) { for (int i = data.length-1; i >= 1; i--) { public class int indexofmax Sorter { = 0; for (int j = 1; j <= i; j++) { public static if (comp.compare(data[j], void sort(integer[] data[indexofmax]) data, Comparator > 0) comp) { for (int i indexofmax = data.length-1; = j; i >= 1; i--) { public static void sort(string[] data, Comparator comp) { int Integer indexofmax temp = data[i]; = 0; for (int i = data.length-1; i >= 1; i--) { for data[i] (int = j data[indexofmax]; = 1; j <= i; j++) { int indexofmax = 0; data[indexofmax] = temp; for (int j = 1; j <= i; j++) { if (comp.compare(data[j], data[indexofmax]) if (comp.compare(data[j], data[indexofmax]) > 0) > 0) //sorterindexofmax = j; indexofmax = j; String temp public = data[i]; static void sort(string[] Integer temp = data[i]; data[i] = data[indexofmax]; for (int i = data.length-1; i >= data[indexofmax] = temp; data[i] = data[indexofmax]; int indexofmax = 0; //sorter data[indexofmax] = temp; for (int j = 1; j <= i; j++) { // methods for sorting other arrays //Sorter if (comp.compare(data[j //sorter indexofmax = j; Steg 2: Använd klassen Comparator Integer[ ] Sorter +sort(integer[], Comparator): void +sort(string[], Comparator): void String[ ] Comparator +compare(integer, Integer): int +compare(string, String): int

Steg 3: Utvidga typtillhörigheten - polymorfism Det gäller att: typerna Integer och String är subtyper till typen Object typerna Integer[] och String[] är subtyper till Object[]. Vi kan således utnyttja denna möjlighet till polymorfism för att eliminera den återstående skillnaden i de båda metoderna i klassen Sorter. Vi ersätter typerna String och String[] respektive Integer och Integer[], med typerna Objekt och Objekt[]. De båda metoderna blir därmed identiska! Slutlig version //sort av klassen Sorter //Sorter public class Sorter { public static void sort(object[] data, Comparator comp) { for (int i = data.length-1; i >= 1; i--) { int indexofmax = 0; for (int j = 1; j <= i; j++) { if (comp.compare(data[j], data[indexofmax]) > 0) indexofmax = j; Object temp = data[i]; data[i] = data[indexofmax]; data[indexofmax] = temp; //sort //Sorter

Problem: Eftersom den statiska typen på de objekt som hanteras i metoden sort nu är Object inträffar ett kompileringsfel vid anropet av comp.compare(data[j], data[indexofmax]) Det finns ingen metod compare i klassen Comparator med signaturen compare(object, Object) Vi måste införa en sådan metod i Comparator. Denna metod blir dock den metod som alltid kommer att väljas! Därför måste denna nya metod handha alla typer av objekt. Ny version av klassen Comparator public class Comparator { public int compare(object o1, Object o2) { if (o1 instanceof String && o2 instanceof String ) return ((String) o1).compareto((string) o2); else if (o1 instanceof Integer && o2 instanceof Integer ) return (Integer) o1 - (Integer) o2; else throw new IllegalArgumentException ("Can't handle this type of objects."); //compare //Comparator

Den nya designen Object[] Sorter +sort(object[], Comparator): void Integer[ ] String[ ] Comparator +compare(object, Object): int Brister med klassen Comparator Metoden compare(object, Object) uppvisar flera brister: vill vi hantera andra typer av fält än Integer[] och String[] måste metoden skrivas om metoden klarar inte av att sortera ett fält på olika sätt (t.ex. i stigande eller avtagande ordning). Problemet är att metoden försöker göra för mycket, nämligen att handha jämförelsen av all typer av objekt. Lösningen är att göra Comparator till ett interface och implementera en Comparator-klass för varje typ av objekt och sorteringsordning.

Interfacet Comparator och konkreta klasser public interface Comparator { public int compare(object o1, Object o2); //Comparator public class StringComparator implements Comparator { public interface Comparator { @Override public int compare(object public int compare(object o1, Object o1, o2); Object o2) { String s1 = (String) o1; //Comparator String s2 = (String) o2; public class StringComparator impleme return s1.compareto(s2); @Override //StringComparator public int compare(object o1, Object public class IntegerComparator implements String Comparator s1 = (String) { o1; @Override public int compare(object o1, Object String o2) { s2 = (String) o2; return (Integer) o1 - (Integer) o2; return s1.compareto(s2); //IntegerComparator //StringComparator public class IntegerComparator implements Comparator { Slutlig design Sorter Object[ ] +sort(object[], Comparator): void Integer[ ] String[ ] AnyOther[ ] <<interface>> Comparator +compare(object, Object): int IntegerComparator StringComparator AnyOtherComparator

Testprogram public class Main { public static void main(string[] args) { String[] names = {"Sture", "Malin", "Maja", "Adam","Hilda"; public Integer[] class values Main = {12, { 16, 134, 2, 7; Sorter.sort(names, new StringComparator()); public static void main(string[] args) { Sorter.sort(values, new IntegerComparator()); for String[] (int i = 0; names i < names.length; = {"Sture", i++) "Malin", "Maja", "Adam System.out.println(names[i]); Integer[] values = {12, 16, 134, 2, 7; System.out.println(); for Sorter.sort(names, (int i = 0; i < values.length; new i++) StringComparator()); System.out.println(values[i]); Sorter.sort(values, new IntegerComparator()); for (int i = 0; i < names.length; i++) System.out.println(names[i]); Ger utskriften: Adam System.out.println(); Hilda Maja Malin Sture 2 7 12 16 134 for (int i = 0; i < values.length; i++) System.out.println(values[i]); Designmönstret Strategy Vår slutliga lösning utnyttjar designmönstret Strategy. Designmönstret Strategy är en generell teknik som används när man vill att ett objekt skall ha olika beteenden, d.v.s. utföra olika algoritmer, beroende på vilken klient som använder objektet. Detta åstadkoms genom att objektet och dess beteende separeras och läggs i olika klasser. När man har flera likartade objekt som endast skiljer sig åt i sitt beteende, är det en bra idé att använda sig av Strategy-mönstret. Context -strategy: Strategy contextmethod() <<interface>> Strategy algorithm() contextmethod() { strategy.algorithm(); ConcreteStrategyA algorithm() ConcreteStrategyB algorithm() ConcreteStrategyC algorithm()

Jämförelse av objekt För att finna ett specifikt objekt i en samling, eller för att sortera en samling av objekt, är det nödvändigt att kunna jämföra två objekt på storlek. Exempelvis tillhandahåller klasserna Arrays och Collections statiska metoder för att sortera ett fält respektive en lista. Hur jämför vi objekt av klassen Person? public class Person { private String name; private int id; public Person(String name, int id) { this.name = name; this.id = id; //constructor public class Person { private String name; private int id; //tostring public Person(String //Person name, int id) { this.name = name; this.id = id; public int getid() { return id; //getid @Override public String tostring() { return ("Namn: " + name + " IDnr: " + id); public int getid() { return id; Gränssnitten Comparable<T> Om en klass implementerar gränssnittet Comparable<T> är objekten i klassen jämförbara på storlek. Gränssnittet Comparable innehåller endast en metod: Ett anrop a.compareto(b) public interface Comparable <T> { public int compareto(t o); skall returnera värdet 0 om a har samma storlek som b, returnera ett negativt tal om a är mindre än b och returnera ett positivt tal om a är större än b.

Gränssnitten Comparable<T> public class Person implements Comparable <Person>{ private String name; private int id; public Person(String name, int id) { public this.name class = Person name; implements Comparable <Person>{ this.id = id; private //constructor String name; private public int int getid() id; { return id; //tostring public //getid Person(String name, int id) { this.name = name; this.id = id; //constructor public int getid() { return id; //getid @Override public String tostring() { return ("Namn: " + name + " IDnr: " + id); @Override public int compareto(person otherperson) { return name.compareto(otherperson.name); //compareto //Person @Override public String tostring() { return ("Namn: " + name + " //tostring @Override public int compareto(person othe Total ordning När man implementerar compareto, måste man förvissa sig om att metoden definierar en total ordning, d.v.s. uppfyller följande tre egenskaper: Antisymmetri: Om a.compareto(b) <= 0, så b.compareto(a) >= 0 Reflexiv: a.compareto(a) = 0 Transitiv: Om a.compareto(b) <= 0 och b.compareto(c) <=0, så a.compareto(c) <= 0 När en klass implementerar Comparable skall man förvissa sig om att villkoret x.equals(y) (x.compareto(y) == 0) gäller, samt eftersträva att villkoret gäller. x.equals(y) (x.compareto(y) == 0)

Gränssnitten Comparator<T> i Java Gränsnittet Comparator<T> som vi införde tidigare finns att tillgå i Javas API: Ett anrop public interface Comparator<T> { public int compare(t o1, T o2); public boolean equals(object obj); comp.compare(a, b) public interface Comparator<T> { public int compare(t o1, T o2); public boolean equals(object obj); skall returnera värdet 0 om a är lika med b, returnera ett negativt tal om a är mindre än b och returnera ett positivt tal om a är större än b. Metoden equals används för att undersöka om två objekt av Comparator är lika och behöver normalt inte överskuggas. return 0; Exempel: return Comparator<T> 1; //compare //IDComparator Antag att vi vill jämföra objekt av klassen Person med avseende på växande ordning på komponenten id. Vi måste då införa en ny klass som vi kallar IDComparator, vilken implementerar gränssnittet Comparator: import java.util.*; public class IDComparator implements Comparator <Person> { @Override public int compare(person a, Person b) { if (a.getid() < b.getid()) return -1; if (a.getid() == b.getid()) return 0; return 1; //compare //IDComparator

Exempel: Comparator<T> Att sortera fält av godtyckliga typer, som vi gjorde vårt tidigare exempel, finns också att tillgå i Javas API i klassen Arrays. Att sortera ett fält med objekt av typen Person i växande ordning på id-nummer sker på följande vis: int size = ; Person[] persons = newperson[size]; // add persons Arrays.sort(persons, new IDComparator()); System.out.println("I id-ordning:"); for (int i = 0; i < persons.length; i++ ) Fortsättning System.out.println(persons[i]); på exempel: //main //PersonTest Nedan ges ett program som lagrar ett antal objekt av klassen Person i ett fält och objekten skrivs ut dels i bokstavsordning med avseende på namnen och dels i växande ordning med avseende på id-numret. import java.util.*; public class PersonTest { public static void main(string[] arg) { Person[] persons = {new Person("Kalle", 22), new Person("Bertil", 62), new Person("Sture", 42), new Person("Rune", 12), new Person("Allan", 52); Arrays.sort(persons); I bokstavordning: System.out.println("I bokstavordning:"); for (int i = 0; i < persons.length; i++ ) System.out.println(persons[i]); Arrays.sort(persons, new IDComparator()); System.out.println("I id-ordning:"); for (int i = 0; i < persons.length; i++ ) I id-ordning: System.out.println(persons[i]); //main //PersonTest Utskriften av programmet blir: Namn: Allan IDnr: 52 Namn: Bertil IDnr: 62 Namn: Kalle IDnr: 22 Namn: Rune IDnr: 12 Namn: Sture IDnr: 42 Namn: Rune IDnr: 12 Namn: Kalle IDnr: 22 Namn: Sture IDnr: 42 Namn: Allan IDnr: 52 Namn: Bertil IDnr: 62