EINFÜHRUNG IN DIE PROGRAMMIERUNG FORTGESCHRITTENE KONZEPTE Tobias Witt! ! 26.03.2014 FEHLERBEHANDLUNG KLASSISCHER ANSATZ • Fehlercode als Rückgabewert von Methoden! ‣ String ➜ Fehlercode als String! ‣ int ➜ Fehlercode als Integer! ‣ List ➜ ???! ‣ void ➜ ??? KLASSISCHER ANSATZ PROBLEME • Fehlerbehandlung stets direkt! • Abfrage von Rückgabewert nötig! ‣ • Verschiedene Fehler - verschiedene FehlerRückgabewerte! Einschränkung des Werte-Bereichs der Methode AUSNAHMEN - EXCEPTIONS • Fehler als „Ausnahme“ explizit oder implizit ausgelöst! • Fehlerursache „wirft“ Exception! • Fehlerbehandler „fängt“ Exception AUSNAHMEN - EXCEPTIONS • Geprüfte Ausnahmen (Checked Exceptions)! ‣ • Ungeprüfte Ausnahmen (Unchecked Exceptions)! ‣ • Müssen behandelt werden! Müssen nicht unbedingt behandelt werden! Jede nicht behandelte Exception bricht das Programm ab! AUSNAHMEN BEISPIELE NullPointerException Methode wird auf null aufgerufen ArrayIndexOutOfBoundsException Zugriff auf nicht existierenden ArrayIndex ClassCastException Casting nicht möglich NumberFormatException z.B. bei Integer.parseInt("bogus") FileNotFoundException Dateiname existiert nicht Exception KLASSE • Geprüfte Exceptions:! ‣ • Erben von Exception Ungeprüfte Exceptions: ‣ Erben von RuntimeException AUSNAHMEN BEHANDELN Ungeprüfte NumberFormatException public class Spiel { public static void main(String[] args) { int a = Integer.parseInt("42"); ! FileInputStream f = new FileInputStream("datei"); } } Unhandled exception: java.io.FileNotFoundException AUSNAHMEN BEHANDELN public class Spiel { public static void main(String[] args) { int a = Integer.parseInt("42"); ! try { FileInputStream f = new FileInputStream("datei"); } catch (FileNotFoundException e) { e.printStackTrace(); } } } AUSNAHMEN BEHANDELN public class Spiel { public static void main(String[] args) { int a = Integer.parseInt("42"); ! try { FileInputStream f = new FileInputStream("datei"); int next = f.read(); } catch (FileNotFoundException e) { e.printStackTrace(); } } } Unhandled exception: java.io.IOException AUSNAHMEN BEHANDELN public class Spiel { public static void main(String[] args) { try { FileInputStream f = new FileInputStream("datei"); int next = f.read(); } catch (IOException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } } } AUSNAHMEN BEHANDELN public class Spiel { public static void main(String[] args) { try { FileInputStream f = new FileInputStream("datei"); int next = f.read(); } catch (IOException|FileNotFoundException e) { e.printStackTrace(); } } } AUSNAHMEN BEHANDELN public class Spiel { public static void main(String[] args) { try { FileInputStream f = new FileInputStream("datei"); int next = f.read(); } catch (IOException|FileNotFoundException e) { e.printStackTrace(); } finally { f.close(); } } } Unhandled exception: java.io.IOException AUSNAHMEN BEHANDELN public class Spiel { public static void main(String[] args) { try (FileInputStream f = new FileInputStream("datei")) { int next = f.read(); } catch (IOException|FileNotFoundException e) { e.printStackTrace(); } } } AUSNAHMEN BEHANDELN II int leseDatei() throws FileNotFoundException { FileInputStream f = new FileInputStream("datei"); } AUSNAHMEN ERZEUGEN public class Wurm { public class WurmLebenException extends IllegalArgumentException { } ! private int leben; ! public Wurm(int leben) { if (leben <= 0) { throw new WurmLebenException( "Leben muss mehr als 0 sein"); } ! this.leben = leben; } } NEBENLÄUFIGKEIT MAIN THREAD Start main-Methode im Main Thread! Anweisung 1 • Sequentielle Ausführung innerhalb jedes Threads! Anweisung 2 • Anweisungen blockieren & warten • Anweisung 3 Ende MEHRERE THREADS Main Thread • • • Asynchrone Ausführung von Main Thread und Thread 2! Gefahr bei Verwendung gleicher Daten! Anweisungen blockieren & warten nur innerhalb eines Threads Start Thread 2 Anweisung 1 Start Anweisung 2 Anweisung 4 Anweisung 3 Ende Anweisung 5 Ende THREADS STARTEN public class Spiel { public static void main(String[] args) { final String string = " du"; Thread t = new Thread(new Runnable() { @Override Closure public void run() { try { „main-Methode“ des Threads Thread.sleep(2000); } catch (InterruptedException e) { statische Methode e.printStackTrace(); der Klasse Thread } (nicht mit dem Objekt System.out.println(string); t verwechseln!) } }); t.start(); System.out.print("Hallo"); } } JAVA 8 public class Spiel { public static void main(String[] args) { final String string = " du"; Thread t = new Thread(()-> { Lambdatry { Expression Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(string); }); t.start(); System.out.print("Hallo"); } } ERGEBNIS? Main Thread Start Thread 2 Starte Thread $ java Spiel Hallo du Gebe “Hallo“ aus Ende Start Warte 2s Gebe “ du“ aus Ende TIMING-PROBLEME Korrektes Ergebnis? public class Spiel { public static void main(String[] args) { DatenDownloader dd = new DatenDownloader(); dd.starteLangenDownloadAsynchron(); String ergebnis = dd.getErgebnis(); } } TIMING-PROBLEME Lösung? NEIN!!!!! public class Spiel { public static void main(String[] args) { DatenDownloader dd = new DatenDownloader(); dd.starteLangenDownloadAsynchron(); Thread.sleep(2000); String ergebnis = dd.getErgebnis(); } } CALLBACK public interface DownloadListener { public void fertig(String ergebnis); } public class DatenDownloader { public void starteLangenDownload(DownloadListener l) { new Thread(() -> { // download... String ergebnis = "ergebnis"; l.fertig(ergebnis); }).start(); } } CALLBACK IMPLEMENTIEREN public class Spiel { public static void main(String[] args) { DatenDownloader dd = new DatenDownloader(); dd.starteLangenDownload(new DownloadListener() { @Override public void fertig(String ergebnis) { // verarbeite ergebnis } }); } } JAVA 8 LambdaExpression mit Parameter public class Spiel { public static void main(String[] args) { DatenDownloader dd = new DatenDownloader(); dd.starteLangenDownload((String ergebnis) -> { // verarbeite ergebnis }); } } GEMEINSAM GENUTZTE DATEN • • Thread 1 Thread 2 Start Start konto1 -= 9 konto1 -= 2 konto2 += 9 konto2 += 2 Ende Ende konto1 = 10 konto2 = 0 public class Spiel { static int konto1 = 10; static int konto2 = 0; ! static void transfer(int betrag) { if (konto1 - betrag >= 0) { // Zeit vergeht konto1 -= betrag; konto2 += betrag; } } ! public static void main(String[] args) { new Thread(() -> { transfer(2); }).start(); new Thread(() -> { transfer(9); }).start(); } } MÖGLICHE ERGEBNISSE Gültig konto1 = 1, konto2 = 9 Gültig konto1 = 8, konto2 = 2 Ungültig konto1 = -1, konto2 = 11 public class Spiel { static int konto1 = 10; static int konto2 = 0; ! ! static void transfer(int betrag) { if (konto1 - betrag >= 0) { // Zeit vergeht konto1 -= betrag; konto2 += betrag; } } ! public static void main(String[] args) { new Thread(() -> { transfer(2); }).start(); new Thread(() -> { transfer(9); }).start(); } } public class Spiel { static int konto1 = 10; static int konto2 = 0; ! ! Spiel während Methode gesperrt synchronized static void transfer(int betrag) { if (konto1 - betrag >= 0) { // Zeit vergeht konto1 -= betrag; konto2 += betrag; } } ! public static void main(String[] args) { new Thread(() -> { transfer(2); }).start(); new Thread(() -> { transfer(9); }).start(); } } DEADLOCK DEADLOCK Thread 1 Thread 2 Sperre auf a Sperre auf b Sperre auf b Sperre auf a Entferne Sperre auf a Entferne Sperre auf b Entferne Sperre auf b Entferne Sperre auf a TEST DRIVEN DEVELOPMENT TDD • Software in ständiger Metamorphose! • Tests zwingend erforderlich! ‣ • Egal ob von Menschen oder automatisch! Test Driven Development: Tests vor der Implementierung implementieren BOWLING GAME KATA 1 4 5 4 5 14 6 5 29 0 49 60 1 61 7 6 77 2 97 117 6 133 • 10 Frames! • Spare: 10 Pins in 2 Würfen: Nächster Wurf doppelt! • Strike: 10 Pins in 1 Wurf: Nächsten 2 Würfe doppelt! • Strike oder Spare im letzten Frame: 1-2 Würfe extra ANFORDERUNGEN • Game Klasse! ‣ public void roll(int pins); - ‣ Simuliert einen Wurf! public int score(); - Gibt die Gesamtpunktzahl zurück BEGINN • • Erstelle neues Projekt! ‣ File ➜ New Project ➜ Java! ‣ Name: BowlingGame! Erstelle GameTest Klasse! ‣ Rechtsklick auf src ➜ New ➜ Java Class! ‣ Name: de.hhu.propra.bowlinggame.GameTest BILDQUELLEN Bild Quelle Exceptions, Threads http://geek-and-poke.com/ Deadlock http://openbook.galileocomputing.de/javainsel9/bilder/ 365_java_09_004.gif TDD http://www.projectcartoon.com/cartoon/353819