Universität Dortmund IV: Objektorientierte Programmierung Java-Tutorium August 2005 Folie 1 von 69 Universität Dortmund Objekte ● ● Klassen sind selbstdefinierte Typen, die mehrere Variablen (Attribute) zusammenfassen können. Jede Klasse steht in einer eigenen Datei <Klassenname>.java. public class Geld{ public String waehrung; public long betrag; } Java-Tutorium August 2005 Folie 2 von 69 Universität Dortmund Objekte ● Ein Objekt ist eine Instanz einer Klasse. ● Ein Objekt wird mit new erzeugt. ● Auf die Attribute des Objekts wird mit . zugegriffen. Geld wenig; wenig=new Geld(); wenig.waehrung="Pesos"; wenig.betrag=50; System.out.println(wenig.betrag); Java-Tutorium August 2005 Folie 3 von 69 Universität Dortmund Objekte ● ● ● Es kann beliebig viele Objekte einer Klasse geben. Objekte werden von Java auf dem Heap gespeichert. In der Variablen ist nicht das Objekt, sondern nur seine Adresse (ein Zeiger) gespeichert. Java-Tutorium August 2005 Folie 4 von 69 Universität Dortmund Objekte Geld wenig; wenig=new Geld(); wenig.währung="Pesos"; wenig.betrag=40; Geld viel=new Geld(); viel.währung="Franken"; viel.betrag=50000; Heap Geld währung: Pesos betrag: 40 Geld-Adresse wenig: 231231 Geld-Adresse viel: Java-Tutorium 803541 August 2005 Geld währung: Franken betrag: 50000 Folie 5 von 69 Universität Dortmund Aufgabe ● ● ● Schreibe eine Klasse Punkt, die einen zweidimensionalen Vektor speichert. Schreibe eine Methode, die den Abstand zwischen zwei Punkten berechnet. Gib den Abstand zwischen (0,5.5) und (4,9) aus. Java-Tutorium August 2005 Folie 6 von 69 Universität Dortmund Zeiger ● Objekte werden bei einer Zuweisung nicht kopiert. ● Stattdessen wird nur die Adresse kopiert. ● gilt auch für Parameterübergabe Java-Tutorium August 2005 Folie 7 von 69 Universität Dortmund Zeiger Geld eines=new Geld(); eines.betrag=50; Geld dasselbe; dasselbe=eines; System.out.println(dasselbe.betrag); eines.betrag=3; System.out.println(dasselbe.betrag); Heap Geld-Adr. eines: 467890 Geld-Adr. dasselbe: 467890 Java-Tutorium August 2005 Geld währung: betrag: 3 Folie 8 von 69 Universität Dortmund Zeiger ● zum Vergleich nochmal mit int int eines; eines=50; int dasgleiche=eines; System.out.println(dasgleiche); eines=3; System.out.println(dasgleiche); 50 50 Java-Tutorium August 2005 Folie 9 von 69 Universität Dortmund Zeiger ● ● ● Strings und Arrays sind ebenfalls Objekte. Nur die Adresse ist in der Variablen gespeichert. Wir hatten große Mühe, Beispiele zu finden, bei denen das nicht so sehr auffällt. Java-Tutorium August 2005 Folie 10 von 69 Universität Dortmund Zeiger ● was bei den Vergleichen mit == passiert ist int[] a1=new int[2]; int[] a2=new int[2]; if(a1==a2){ ... } int[]-Adr. a1: 4401455 int[]-Adr. a2: 9456431 Java-Tutorium August 2005 Heap int[] 0: 0 1: 0 int[] 0: 0 1: 0 Folie 11 von 69 Universität Dortmund Zeiger ● ● Bei der Erzeugung mit new werden die Variablen in Objekten automatisch initialisiert. Die Defaultwerte entsprechen denen von Arrayelementen. Punkt p=new Punkt(); System.out.println(p.x); 0.0 Java-Tutorium August 2005 Folie 12 von 69 Universität Dortmund Aufgabe ● ● ● ● Schreibe eine Methode, die zwei Punkte koordinatenweise vergleicht. Schreibe eine Methode, die einen Punkt kopiert. Erstelle einen Punkt, setze die Koordinaten auf (3,4) und kopiere den Punkt. Vergleiche das Original mit der Kopie — einmal mit == und einmal mit deiner Methode. Java-Tutorium August 2005 Folie 13 von 69 Universität Dortmund Zeiger ● Garbage Collection (Müllabfuhr) Punkt p=new Punkt(); p=new Punkt(); p=new Punkt(); System.gc(); Heap Punkt x: 0 y: 0 Punkt x: 0 y: 0 Punkt p: 789045601 Punkt x: 0 y: 0 Java-Tutorium August 2005 Folie 14 von 69 Universität Dortmund Zeiger ● Garbage Collection (Müllabfuhr) Punkt p=new Punkt(); p=new Punkt(); p=new Punkt(); System.gc(); Heap Punkt p: 789045601 Punkt x: 0 y: 0 Java-Tutorium August 2005 Folie 15 von 69 Universität Dortmund Zeiger ● ● Die Garbage Collection ist ein besonderes Feature von Java. Sie muss normalerweise nicht explizit aufgerufen werden. Java-Tutorium August 2005 Folie 16 von 69 Universität Dortmund Zeiger ● Zeiger, die nirgendwohin zeigen Punkt p=new Punkt(); p=null; System.gc(); Heap Punkt p: 0000000000000 Java-Tutorium August 2005 Folie 17 von 69 Universität Dortmund Zeiger ● ● NullPointerException alias allgemeine Schutzverletzung, alias Segmentation Violation Punkt punkt=null; System.out.println(punkt.x); java.lang.NullPointerException at Main.main(Main.java:119) Exception in thread "main" Java-Tutorium August 2005 Folie 18 von 69 Universität Dortmund Zeiger ● ● Objekte können selbst wieder Zeiger enthalten. Der Defaultwert von allen Zeigern ist null. public class Strecke{ public Punkt start; public Punkt ende; } Java-Tutorium August 2005 Folie 19 von 69 Universität Dortmund Zeiger ● Verzeigerung Punkt p1=new Punkt(); Punkt p2=new Punkt(); Strecke s=new Strecke(); s.start=p1; s.ende=p2; p1=null; p2=null; System.gc(); Punkt p1: 00000000 Punkt p2: 00000000 Strecke s : 87301564 Java-Tutorium August 2005 Heap Punkt x: 0 y: 0 Punkt x: 0 y: 0 Strecke start: 12896453 ende : 43678941 Folie 20 von 69 Universität Dortmund Aufgabe ● ● ● Schreibe eine Klasse Kreis, die aus einem Mittelpunkt und einem Radius besteht. Schreibe eine Methode, die bestimmen kann, ob ein Punkt innerhalb des Kreises liegt. Liegt (1.7,2.6) in einem Kreis mit Radius 1 um (1,2)? Java-Tutorium August 2005 Folie 21 von 69 Universität Dortmund Aufgabe ● ● ● Schreibe eine Klasse Ring mit den Methoden – String weiter(Ring) – void fügeHinzu(Ring, String) Die Methode weiter gibt der Reihe nach jeweils einen String aus dem Ring aus. fügeHinzu fügt den String in den Ring an der Stelle ein, die als nächstes dran ist. Java-Tutorium August 2005 Folie 22 von 69 Universität Dortmund Tipp ● Verwende folgende Struktur. Heap Ring aktuell: RingElement vor: zurück: RingElement vor: zurück: RingElement vor: zurück: Java-Tutorium August 2005 RingElement vor: zurück: Folie 23 von 69 Universität Dortmund Objekte ● Methoden in anderen Klassen ● zusammen, was zusammen gehört public class Punkt{ public double x; public double y; } public static double abstand(Punkt a, Punkt b){ double x=a.x-b.x; double y=a.y-b.y; return Math.sqrt(x*x+y*y); } Java-Tutorium August 2005 Folie 24 von 69 Universität Dortmund Objekte ● Methoden in anderen Klassen aufrufen public static void main(String[] arguments){ Punkt p1=new Punkt(); Punkt p2=new Punkt(); p2.x=3; p2.y=4; System.out.println(Punkt.abstand(p1, p2)); } 5.0 Java-Tutorium August 2005 Folie 25 von 69 Universität Dortmund Objekte ● Viele Methoden arbeiten mit einem Objekt. public class Punkt{ ... } public static double abstandZuNullA(Punkt p){ double xQuadrat=p.x*p.x; double yQuadrat=p.y*p.y; return Math.sqrt(xQuadrat+yQuadrat); } Java-Tutorium August 2005 Folie 26 von 69 Universität Dortmund Objekte ● Methoden non-static definieren public class Punkt{ ... } public double abstandZuNullB(){ double xQuadrat=this.x*this.x; double yQuadrat=this.y*this.y; return Math.sqrt(xQuadrat+yQuadrat); } Java-Tutorium August 2005 Folie 27 von 69 Universität Dortmund Objekte ● nochmal zum Vergleich public class Punkt{ ... } public static double abstandZuNull(Punkt p){ double xQuadrat=this/p.x*this/p.x; double yQuadrat=this/p.y*this/p.y; return Math.sqrt(xQuadrat+yQuadrat); } Java-Tutorium August 2005 Folie 28 von 69 Universität Dortmund Objekte ● Wie bestimmt man jetzt, welchen Punkt man meint? Punkt p1=new Punkt(); Punkt p2=new Punkt(); p2.x=4; System.out.println(p1.abstandZuNullB()); System.out.println(p2.abstandZuNullB()); 0.0 4.0 Java-Tutorium August 2005 Folie 29 von 69 Universität Dortmund Objekte //in Main.java public static void main(...){ Punkt p=new Punkt(); double z=p.abstandZuNullB(); } //in Punkt.java public double abstandZuNullB(){ double xQdr=this.x*this.x; double yQdr=this.y*this.y; return Math.sqrt(xQdr+yQdr); } Punkt p: 32383409 this: <static> Heap Punkt x: 0 y: 0 double z: 0 Java-Tutorium August 2005 Folie 30 von 69 Universität Dortmund Objekte ● Andere Parameter darf man natürlich trotzdem noch haben. public class Punkt{ ... } public double abstandZu(Punkt andererPunkt){ double dx=this.x-andererPunkt.x; double dy=this.y-andererPunkt.y; return Math.sqrt(dx*dx+dy*dy); } Java-Tutorium August 2005 Folie 31 von 69 Universität Dortmund Aufgabe ● ● Schreibe eine Methode, die auf einem Kreis aufgerufen wird und seine Fläche zurückgibt. Schreibe eine Methode schließeEin(Punkt), die einen Kreis falls nötig vergrößert, so dass er den angegebenen Punkt einschließt. Java-Tutorium August 2005 Folie 32 von 69 Universität Dortmund Objekte ● Es gibt selbstverständlich weiterhin verschachtelte Methodenaufrufe. public class Buch{ public Cover cover; public Seite[] seiten; } public double dicke(){ double ergebnis=this.cover.dicke(); for(int i=0;i<this.seiten.length;i++){ ergebnis+=this.seiten[i].papierDicke(); } return ergebnis; } Java-Tutorium August 2005 Folie 33 von 69 Universität Dortmund Objekte ● Methoden auf das aktuelle Objekt kann man (logisch!) mit this aufrufen. public class Brief{ public Adresse wohin; public String text; } public void druckeAdresse(){ this.wohin.drucke(); } public void drucke(){ this.druckeAdresse(); System.out.println(this.text); } Java-Tutorium August 2005 Folie 34 von 69 Universität Dortmund Aufgabe ● ● ● ● Baue die alten Methoden fügeEin und weiter in die Klasse Ring ein. Schreibe eine Methode int anzahl(). Schreibe eine Methode boolean enthält (String) (die aktuelle Position soll nicht verändert werden). Schreibe eine Methode fügeAlleEin(Ring). – Tipp: Benutze die anderen Methoden dafür. Java-Tutorium August 2005 Folie 35 von 69 Universität Dortmund Objekte ● Auf private Attribute und Methoden kann nur aus der Klasse zugegriffen werden, in der sie definiert sind. ● ermöglicht Kapselung ● verhindert unerwünschte Seiteneffekte Java-Tutorium August 2005 Folie 36 von 69 Universität Dortmund Objekte ● wenn man es trotzdem versucht public class Punkt{ private double x; private double y; } public class Main{ public static void main(String[] s){ Punkt p=new Punkt(); System.out.println(p.x); } } Main.java [37:1] x has private access in Punkt System.out.println(p.x); 1 error ^ Java-Tutorium August 2005 Folie 37 von 69 Universität Dortmund Objekte ● Wie kommt man jetzt an die Werte? ● get-Methoden public class Punkt{ private double x; private double y; } public double getX(){ return this.x; } public double getY(){ return this.y; } Java-Tutorium August 2005 Folie 38 von 69 Universität Dortmund Objekte ● set-Methoden public class Geld{ private long betrag; } public void setBetrag(long eur, int ct){ this.betrag=euro*100+cent; } public long getEuros(){ return this.betrag/100; } public int getCent(){ return this.betrag%100; } Java-Tutorium August 2005 Folie 39 von 69 Universität Dortmund Objekte ● Konstruktoren public class Punkt{ private double x; private double y; } public Punkt(double x, double y){ this.x=x; this.y=y; } ... Java-Tutorium August 2005 Folie 40 von 69 Universität Dortmund Objekte ● Konstruktoren benutzen Punkt p1=new Punkt(1, 1); Punkt p2=new Punkt(2, 2); System.out.println(Punkt.abstand(p1, p2)); 1.4142135623730951 Java-Tutorium August 2005 Folie 41 von 69 Universität Dortmund Objekte ● Der Standardkonstruktor verschwindet. Punkt p1=new Punkt(1, 1); Punkt p2=new Punkt(); System.out.println(Punkt.abstand(p1, p2)); Main.java [34:1] cannot resolve symbol symbol : constructor Punkt () location: class Punkt Punkt p2=new Punkt(); ^ 1 error Java-Tutorium August 2005 Folie 42 von 69 Universität Dortmund Objekte ● den Standardkonstruktor wiederbekommen public class Punkt{ private double x; private double y; public Punkt(){ } } public Punkt(double x, double y){ this.x=x; this.y=y; } ... Java-Tutorium August 2005 Folie 43 von 69 Universität Dortmund Aufgabe ● ● ● Schreibe eine Klasse Konto mit einem Attribut guthaben. Die Klasse soll einzahlen, abheben und Kontostand anzeigen unterstützen. Ein Konto muss immer mit einer Einzahlung eröffnet werden. Java-Tutorium August 2005 Folie 44 von 69 Universität Dortmund Objekte ● abkürzende Schreibweise ohne this public class Konto{ private long guthaben; } public Konto(long einzahlung){ zahleEin(einzahlung); } public void zahleEin(long betrag){ guthaben+=betrag; } Java-Tutorium August 2005 Folie 45 von 69 Universität Dortmund Objekte ● Manchmal braucht man this trotzdem. public class Person{ public void heirate(Person partner){ Standesamt.heiraten(this, partner); } } Java-Tutorium August 2005 Folie 46 von 69 Universität Dortmund Exceptions ● private reicht nicht immer zum Schutz. ● Fehler niemals stillschweigend ignorieren! public void hebeAb(int betrag){ if(guthaben>=betrag){ guthaben-=betrag; } } public static void überweise(Konto von, Konto nach, int betrag){ } von.hebeAb(betrag); nach.zahleEin(betrag); Java-Tutorium August 2005 Folie 47 von 69 Universität Dortmund Exceptions ● eine Exception werfen public void hebeAb(int betrag){ //testen if(betrag<=0)throw new RuntimeException(); if(guth<betrag)throw new RuntimeException(); } //ausführen guth-=betrag; Java-Tutorium August 2005 Folie 48 von 69 Universität Dortmund Exceptions ● eine Exception "geworfen bekommen" public static void main(String[] arguments){ Konto pleite=new Konto(50); pleite.hebeAb(35); System.out.println(pleite.getKontostand()); pleite.hebeAb(23); System.out.println(pleite.getKontostand()); } 15 java.lang.RuntimeException: at Konto.hebeAb(Konto.java:14) at Main.main(Main.java:36) Exception in thread "main" Java-Tutorium August 2005 Folie 49 von 69 Universität Dortmund Exceptions ● eine Exception fangen Konto pleite=new Konto(50); try{ pleite.hebeAb(35); pleite.hebeAb(23); System.out.println("Juhuu"); }catch (RuntimeException exc){ System.out.println("Mist"); } System.out.println(pleite.getKontostand()); Mist 15 Java-Tutorium August 2005 Folie 50 von 69 Universität Dortmund Exceptions ● Es kann natürlich auch mal gut gehen. Konto pleite=new Konto(100); try{ pleite.hebeAb(35); pleite.hebeAb(23); System.out.println("Juhuu"); }catch (RuntimeException exc){ System.out.println("Mist"); } System.out.println(pleite.getKontostand()); Juhuu 42 Java-Tutorium August 2005 Folie 51 von 69 Universität Dortmund Exceptions ● ● ● ● Sobald eine Exception geworfen wird, sucht java das letzte (innerste) try, das bei der Ausführung passiert wurde. Dann springt java zu dem catch-Block, der zu diesem try gehört. Gibt es kein try, wird eine Nachricht ausgegeben und das Programm beendet. Warnung! Lügen für Kinder! Java-Tutorium August 2005 Folie 52 von 69 Universität Dortmund Aufgabe ● ● Füge der Klasse Konto eine pin hinzu, die bei jeder kritischen Operation als Paramter korrekt angegeben werden muss. Sichere die Klasse Konto mit Exceptions ab. Java-Tutorium August 2005 Folie 53 von 69 Universität Dortmund Exceptions ● Was soll man hier als Fehlermeldung ausgeben? int geld=readInt("Wieviel wollen Sie abheben?"); String pin=readString("Ihre Geheimzahl"); try{ konto.hebeAb(geld, pin); }catch (RuntimeException exc){ System.out.println("Falsche PIN?"); System.out.println("Kein Geld mehr?"); } Java-Tutorium August 2005 Folie 54 von 69 Universität Dortmund Exceptions ● eine neue Klasse von Exceptions deklarieren public class KontoÜberzogenException extends RuntimeException{ } Java-Tutorium August 2005 Folie 55 von 69 Universität Dortmund Exceptions ● die richtige Exception werfen public void hebeAb(long betrag, String pin){ if(!pin.equals(this.pin)){ throw new FalschePinException(); } if(betrag<0){ throw new NegativerBetragException(); } if(guth<betrag){ throw new KontoÜberzogenException(); } } guthaben-=betrag; Java-Tutorium August 2005 Folie 56 von 69 Universität Dortmund Exceptions ● selektiv Exceptions fangen int geld=readInt("Wieviel wollen sie abheben"); String pin=readString("Ihre Geheimzahl"); try{ konto.hebeAb(geld, pin); }catch (FalschePinException exc){ System.out.println("Falsche PIN"); }catch (KontoÜberzogenException exc) System.out.println("Sie sind pleite"); }catch (NegativerBetragException exc){ System.out.println("Trottel!"); } Java-Tutorium August 2005 Folie 57 von 69 Universität Dortmund Exceptions ● catch (RuntimeException exc) fängt auch eine KontoÜberzogenException ● Reihenfolge beachten int geld=readInt("Wieviel wollen sie abheben"); String pin=readString("Ihre Geheimzahl"); try{ konto.hebeAb(geld, pin); }catch (FalschePinException exc){ System.out.println("Falsche PIN"); }catch (RuntimeException exc){ System.out.println("Anderer Fehler"); } Java-Tutorium August 2005 Folie 58 von 69 Universität Dortmund Exceptions ● Fehlermeldung von der Exception bekommen try{ throw new RuntimeException("Hallo"); }catch (RuntimeException exc){ String nachricht=exc.getMessage(); System.out.println(nachricht); } Hallo Java-Tutorium August 2005 Folie 59 von 69 Universität Dortmund Exceptions ● Call-Stack ausgeben – hilft dem Programmierer, die Ursache zu verstehen try{ throw new RuntimeException("Hallo"); }catch (RuntimeException exc){ exc.printStackTrace(); } java.lang.RuntimeException: Hallo at Huibu.wirfMal(Huibu.java:12) at Konto.hebeAb(Konto.java:14) at Main.main(Main.java:36) Java-Tutorium August 2005 Folie 60 von 69 Universität Dortmund Exceptions ● Es gibt neben RuntimeExceptions auch noch normale (checked) Exceptions. public class PleiteExc extends Exception{ } Java-Tutorium August 2005 Folie 61 von 69 Universität Dortmund Exceptions ● Checked Exceptions müssen deklariert oder gefangen werden. public void hebAb(int betrag){ if(betrag<=0)throw new NegativerBetragExc(); if(guthaben<betrag)throw new PleiteExc(); } guthaben-=betrag; Konto.java [12:1] unreported exception java.lang.Exception; must be caught or declared to be thrown if(guthaben<betrag) throw new PleiteExc(); 1 error ^ Java-Tutorium August 2005 Folie 62 von 69 Universität Dortmund Exceptions ● Checked Exceptions müssen deklariert oder gefangen werden. public void hebAb(int betrag) throws PleiteExc{ if(betrag<=0) throw new NegativerBetragExc(); if(guthaben<betrag) throw new PleiteExc(); } guthaben-=betrag; Java-Tutorium August 2005 Folie 63 von 69 Universität Dortmund Exceptions ● Auch wer eine Methode mit throws aufruft, muss die Exception fangen oder deklarieren. public static void main(String[] arguments) throws PleiteExc{ Konto konto=new Konto(50); konto.hebeAb(35); System.out.println(konto.getKontostand()); konto.hebeAb(23); System.out.println(konto.getKontostand()); } Java-Tutorium August 2005 Folie 64 von 69 Universität Dortmund Exceptions ● RuntimeExceptions werfen, wenn die aufrufende Methode etwas unsinniges will – IllegalArgumentException – ArrayIndexOutOfBoundsException – NullPointerException – NegativerBetragException Java-Tutorium August 2005 Folie 65 von 69 Universität Dortmund Exceptions ● checked Exceptions werfen, wenn ein an sich vernünftiger Aufruf nicht ausgeführt werden kann – FileNotFoundException – MidiUnavailableException – NoRouteToHostException – KontoÜberzogenException Java-Tutorium August 2005 Folie 66 von 69 Universität Dortmund Exceptions ● ● ● In der Methode wird die Ausnahme nur entdeckt. Die Ausnahmebehandlung wird der aufrufenden Methode überlassen. throws sagt der aufrufenden Methode, was prinzipiell schief gehen könnte. Java-Tutorium August 2005 Folie 67 von 69 Universität Dortmund Exceptions ● Die aufrufende Methode hat mehr Kontextinformation – Eine Klasse Geldautomat bietet dem Benutzer an, weniger abzuheben – Eine Überweisungsmethode reicht die Exception einfach nach oben durch Java-Tutorium August 2005 Folie 68 von 69 Universität Dortmund Aufgabe ● ● ● Schreibe eine Klasse Geldautomat, die ein User Interface im Textmodus für die drei Funktionen bietet. Die Aufgabe lässt viel Spielraum: – Muss man das Abheben bestätigen? – Muss man die PIN nochmal eingeben, wenn man sich beim Betrag vertippt? – Kann man zwischendurch abbrechen? KISS: Keep It Simple and Stupid Java-Tutorium August 2005 Folie 69 von 69