Start von Java-Programmen Grundlagen Programmierung Stephan Kleuker 558 Bisher • In BlueJ wurde Objekt erzeugt und dann Methode ausgewählt • alternativ könnte man jetzt direkt auf Klasse eine noch zu schreibende Klassenmethode ausführen • Ansatz weiter gedacht: Klasse heißt ausführbar, wenn sie eine Methode mit folgender Signatur hat public static void main(String[] arg){… Grundlagen Programmierung Stephan Kleuker 559 Nutzung einer Main-Klasse • sinnvoll ist es, eigene Klasse Main zu ergänzen, die ausschließlich zum Start des Programmes genutzt wird • Erstellung notwendiger Objekte und Aufruf von Methoden, damit Objekte "sich kennen" • Start einer Hauptmethode public class Main{ public static void main(String[] arg){ Studentenverwaltung s = new Studentenverwaltung(); s.steuern(); } } Grundlagen Programmierung Stephan Kleuker 560 Aufruf von main in BlueJ • Klassenmethode auswählen • Array kann direkt eingegeben werden (meist ohne Bedeutung, dann leer lassen) Grundlagen Programmierung Stephan Kleuker 561 Vom Source Code zum ausführbaren Programm Java Source (Punkt.java) Java Bytecode (Punkt.class) Java Compiler (javac) Just-in-time Compiler Java Virtual Machine (java)) • Source Code wird vom Compiler in Bytecode übersetzt • Bytecode wird von JVM ausgeführt (d.h. interpretiert) • Ggf. werden über den JIT-Compiler bestimmte Befehlssequenzen in nativen Code übersetzt Grundlagen Programmierung Stephan Kleuker 562 Kompilierung mit der Konsole - Ausgangssituation Grundlagen Programmierung Stephan Kleuker 563 Kompilierung mit der Konsole - Kompilieren Grundlagen Programmierung Stephan Kleuker 564 Kompilierung mit der Konsole - Ausführen man erkennt, dass die Shell kein UTF-8 "spricht" Grundlagen Programmierung Stephan Kleuker 565 ausführbares Programm in BlueJ (1/4) • Annahme: gibt Klasse Main mit main-Methode • Packen des Programms in eine jar-Datei (vergleichbar einer zip-Datei mit einem bestimmten Aufbau) Grundlagen Programmierung Stephan Kleuker 566 ausführbares Programm in BlueJ (2/4) • Auswahl der Startklasse (könnte mehrere main geben) Grundlagen Programmierung Stephan Kleuker 567 ausführbares Programm in BlueJ (3/4) • Speichern der jar-Datei • jar-Datei unter jedem Betriebssystem nutzbar Grundlagen Programmierung Stephan Kleuker 568 ausführbares Programm in BlueJ (4/4) • Kommando-Zeile (oder Batch-Datei) • wenn graphisch (AWT oder Swing) und im Betriebssystem konfiguriert, dann Start durch Doppelklick Grundlagen Programmierung Stephan Kleuker 569 Nutzung von Übergabeparametern (1/2) public class MainAnalyse{ public static void main(String[] s){ if(s==null){ System.out.println("null"); } else { if(s.length==0){ System.out.println("kein Parameter"); } else { for(Integer i=0; i<s.length; i =i+1){ System.out.println(i+": "+s[i]); } } } } }Grundlagen Programmierung Stephan Kleuker 570 Nutzung von Übergabeparametern (2/2) Grundlagen Programmierung Stephan Kleuker 571 Entwicklungsumgebungen Grundlagen Programmierung Stephan Kleuker 572 Programmentwicklung in Java • Grundsätzlich reicht ein beliebiger Texteditor zur Programmerstellung, der Inhalt unformatiert speichert • Klasse K muss in Datei K.java stehen • java und javac benötigt • Problem: viele projekteinheitlich zu lösende Aufgaben müssen individuell geregelt werden – welche Einrückungen – woher kommen benötigte Klassen anderer – wer kompiliert Gesamtprojekt – wer erstellt wie die Dokumentation – ……… Grundlagen Programmierung Stephan Kleuker 573 Entwicklungsumgebung BlueJ BlueJ übernimmt einige typische Aufgaben: • Code-Formatierung (Einrückungen) • Syntax-Highlighting von Schlüsselwörtern • Einfaches Manövrieren in Klassen • Unmittelbare Möglichkeit zur Ausführung • Testklassendefinition und Testausführung (JUnit) • Einfach Debug-Möglichkeiten • aber, Entwicklungsumgebungen für Profis können wesentlich mehr • aber, nur BlueJ kann direkt mit Objekten kommunizieren • Fazit: BlueJ sehr gut zum Lernen geeignet, da man gezwungen wird, alles selbst zu tippen; für größere Projekte eher ungeeignet Grundlagen Programmierung Stephan Kleuker 574 Entwicklungsumgebung Eclipse • • • • • • • • • • • • Editor mit Syntax-Highlighting und Formatierung Anzeige aller Fehler einfaches Starten von Programmen einfaches Einbinden anderer Programme und Bibliotheken einfaches Ausführen von JUnit-Tests viele Möglichkeiten zur Code-Generierung: get-, set- Methoden, Varianten von Konstruktoren, equals, hashCode, toString Einbau umgebender try-catch-Blöcke mächtige Code-Completion (<Strg>+<Space>) einfache Nutzung eines sehr mächtigen Debuggers schnelles Manövrieren zu nutzenden und genutzten Methoden ……… Achtung: man benötigt zunächst nur sehr wenige der vielen Möglichkeiten, Schritt für Schritt vortasten Grundlagen Programmierung Stephan Kleuker 575 Beispiel: Studierendenverwaltung (1/4) - Eingabe Grundlagen Programmierung Stephan Kleuker 576 Beispiel: Studierendenverwaltung (2/4) - Ausführen Grundlagen Programmierung Stephan Kleuker 577 Beispiel: Studierendenverwaltung (3/4) - Debugging Grundlagen Programmierung Stephan Kleuker 578 Beispiel: Studierendenverwaltung (4/4) - Testen Grundlagen Programmierung Stephan Kleuker 579 Erweiterbarkeit von Eclipse • Eclipse kann einfach durch Plug Ins erweitert werden • viele verschiedene Programmiersprachen und Werkzeuge z. B. zur Datenbankverwaltung möglich • Vorwegwarnung: Jedes Plug In macht Eclipse langsamer • Einige weitere Unterstützung bei der Programmierung • statische Quellcode-Analyse – detaillierte Prüfungen von Style-Guides (Einrückungen bis magic Numbers) – Bewertung der Komplexität von Programmen (Anzahl der Verzeigungen) • Messung von Testüberdeckungen (wird Anweisung oder Zweig geprüft) • ……… Grundlagen Programmierung Stephan Kleuker 580 Beispiel: Eclemma für Testüberdeckung Grundlagen Programmierung Stephan Kleuker 581 Eclipse als IDE • IDE = Integrated Development Environment • Gesamter Entwicklungsprozess umfasst Phasen – Anforderungsanalyse – Design – Programmierung – Test • eine IDE unterstützt mehrere dieser Phasen • eine IDE unterstützt die Verwaltung der Ergebnisse (Versionsmanagement) • eine IDE unterstützt den Zusammenbau und die Installation der Software (Build-Management) • trotzdem bleibt IDE nur ein [zentraler] Teil der Entwicklung Grundlagen Programmierung Stephan Kleuker 582 Pakete Grundlagen Programmierung Stephan Kleuker 583 Idee von Paketen • Große Mengen von Klassen oft sehr unübersichtlich • Ähnlich zu Dateisystemen ist eine logische Ordnung in verschiedenen Ordnern sinnvoll • Ordner werden in Java Paket (package genannt) • Paketzugehörigkeitsdeklaration steht immer am Anfang der Klasse package de.ossoft.gui; public class Maske{ • Datei Maske.java muss im Unterordner de/ossoft/gui des Projekts liegen • Nutzung von Klassen aus anderen Paketen über import import de.ossoft.gui.Maske; Grundlagen Programmierung Stephan Kleuker 584 Ausschnitt: Java-Pakete der Klassenbibliothek java.util Contains the collections framework, legacy collection classes, event model, date and time facilities, internationalization, and miscellaneous utility classes (a string tokenizer, a randomnumber generator, and a bit array). java.util. concurrent Utility classes commonly useful in concurrent programming. java.util. A small toolkit of classes that support lock-free thread-safe concurrent.atomic programming on single variables. java.util. concurrent.locks java.util.jar java.util.logging Interfaces and classes providing a framework for locking and waiting for conditions that is distinct from built-in synchronization and monitors. Provides classes for reading and writing the JAR (Java ARchive) file format, which is based on the standard ZIP file format with an optional manifest file. Provides the classes and interfaces of the JavaTM 2 platform's core logging facilities. Grundlagen Programmierung Stephan Kleuker 585 Pakete in BlueJ • etwas aufwändig über das Menü Grundlagen Programmierung Stephan Kleuker 586 Klassen in Pakete verschieben (1/2) • leider funktioniert hier kein Drag & Drop in BlueJ Grundlagen Programmierung Stephan Kleuker 587 Klassen in Pakete verschieben (2/5) • Trick: Paketdeklaration direkt in Klasse eintragen Grundlagen Programmierung Stephan Kleuker 588 Klassen in Pakete verschieben (3/5) • Frage bei "Compile" bestätigen mit "Move" bestätigen Grundlagen Programmierung Stephan Kleuker 589 Klassen in Pakete verschieben (4/5) • Generell müssen Pakete erst angelegt werden, sonst Grundlagen Programmierung Stephan Kleuker 590 Klassen in Pakete verschieben (5/5) • Später Paket (Ordner) mit Doppelklick öffnen Grundlagen Programmierung Stephan Kleuker 591 Beispiel: einfache Software-Architektur (1/3) • bisher bei Studentenverwaltung alle Klassen in einem (dem default-) Paket eine typische Aufteilung: • entity-Paket: alle zu verwaltenden Datenklassen (typisch fast nur get- und set- Methoden) • control-Paket: Verwaltungsklassen, die Sammlungen von Entity-Objekten verwalten; Zugriff auf Entity-Objekte nur über Control-Klassen • boundary-Paket: externer Zugriff auf Verwaltungsklassen, z. B. Nutzungsoberfläche Grundlagen Programmierung Stephan Kleuker 592 Beispiel: einfache Software-Architektur (2/3) entity control (Zugriff auf entity-Objekte) Grundlagen Programmierung Stephan Kleuker 593 Beispiel: einfache Software-Architektur (3/3) • boundary (Zugriff auf control-Objekte) • fehlt: Aufteilung von Boundary und Control Grundlagen Programmierung Stephan Kleuker 594 Pakete und Imports package boundary; import control.Studentenverwaltung; public class Studentendialog { private Studentenverwaltung verwaltung = new Studentenverwaltung(); package control; import entity.Student; import entity.Austauschstudent; // weitere Imports public class Studentenverwaltung { private ArrayList<Student> studenten; private String semester = "Semester XXXX"; Grundlagen Programmierung Stephan Kleuker 595 Aufteilung in Boundary und Control-Funktionalität (1/2) //alt in Studentenverwaltung public void anzahlAustauschstudentenAusgeben() { EinUndAusgabe io = new EinUndAusgabe(); io.ausgeben("Es gibt " + anzahlAustauschstudenten() + " Austauschstudenten\n"); } public Integer anzahlAustauschstudenten() { Integer ergebnis = 0; for (Student s : this.studenten) { ergebnis = ergebnis + s.zaehlenAlsAustauschstudent(); } return ergebnis; } Grundlagen Programmierung Stephan Kleuker 596 Aufteilung in Boundary und Control-Funktionalität (2/2) // neu: boundary (StudentenDialog) public void anzahlAustauschstudentenAusgeben() { EinUndAusgabe io = new EinUndAusgabe(); io.ausgeben("Es gibt " + verwaltung.anzahlAustauschstudenten() + " Austauschstudenten\n"); } // neu: control (Studentenverwaltung) public Integer anzahlAustauschstudenten() { Integer ergebnis = 0; for (Student s : this.studenten) { ergebnis = ergebnis + s.zaehlenAlsAustauschstudent(); } return ergebnis; } Grundlagen Programmierung Stephan Kleuker 597 Aufteilung in Boundary und Control-Funktionalität (1/4) //alt in Studentenverwaltung public void studentSuchen() { EinUndAusgabe io = new EinUndAusgabe(); Integer mat = zahlZwischen("Matrikelnummer" , 99999, 1000000); Student s = studentSuchen(mat); if (s != null) { io.ausgeben("Daten: " + s + "\n"); } else { io.ausgeben("nicht gefunden\n"); } } Grundlagen Programmierung Stephan Kleuker 598 Aufteilung in Boundary und Control-Funktionalität (2/4) //alt in Studentenverwaltung public Student studentSuchen(Integer mat) { Student ergebnis = null; for (Student s : this.studenten) { if (s.getMatrikelnummer().equals(mat)) { ergebnis = s; } } return ergebnis; } Grundlagen Programmierung Stephan Kleuker 599 Aufteilung in Boundary und Control-Funktionalität (3/4) // neu: boundary (StudentenDialog) public void studentSuchen() { EinUndAusgabe io = new EinUndAusgabe(); Integer mat = zahlZwischen("Matrikelnummer" , 99999, 1000000); String s = verwaltung.studentAusgeben(mat); if (s != null) { io.ausgeben("Daten: " + s + "\n"); } else { io.ausgeben("nicht gefunden\n"); } } Grundlagen Programmierung Stephan Kleuker 600 Aufteilung in Boundary und Control-Funktionalität (4/4) // neu: control (Studentenverwaltung) private Student studentSuchen(Integer mat) { Student ergebnis = null; for (Student s : this.studenten) { if (s.getMatrikelnummer().equals(mat)) { ergebnis = s; } } return ergebnis; } public String studentAusgeben(Integer mat){ Student s=studentSuchen(mat); if(s==null){ return null; } return s.toString(); } Programmierung Grundlagen Stephan Kleuker 601 alle Studieren in Control-Klasse public ArrayList<String> studentenAusgeben() { ArrayList<String> ergebnis = new ArrayList<String>(); for (Student s : this.studenten) { ergebnis.add(s.toString()); } return ergebnis; } • Beispiel zeigt deutlich, dass Boundary-Klassen keinen direkten Zugriff auf Entity-Klassen erhalten • (Anmerkung: Ansatz wird nicht immer so konsequent eingehalten) • Ansatz erlaubt leichte Erstellung einer grafischen Oberfläche Grundlagen Programmierung Stephan Kleuker 602 Ergänztes Main-Paket package main; import boundary.Studentendialog; public class Main{ public static void main( String[] arg){ Studentendialog s = new Studentendialog(); s.steuern(); } } Grundlagen Programmierung Stephan Kleuker 603 Kompilieren und Ausführen in der Konsole Grundlagen Programmierung Stephan Kleuker 604 Beispiel: Pakete und Compilieren \home\blubb\a package a; import a.d.D; import a.b.c.C; public class A{ dies ist File \home\blubb\a\A.java \home\blubb\a\d \home\blubb\a\b package a.d; import a.b.B; public class D{ private B b=null; } package a.b; public class B {…} class Ghost {…} \home\blubb\a\b\c package a.b.c; import a.d.D; public class C {} Grundlagen Programmierung Compiliert wird im Verzeichnis oberhalb von a (also in blubb) mit javac a\A.java Ausführung (auch in blubb) java a.A Stephan Kleuker 605 Nutzung von CLASSPATH • Damit Java Verzeichnisse mit Paketen findet, sollte die Umgebungsvariable CLASSPATH gesetzt werden • Diese Variable enthält die Start-Verzeichnisse, in denen bei einem Aufruf nach Klassen oder Paketen gesucht wird • Beim Aufruf >java C durchsucht das Laufzeitsystem sämtliche in CLASSPATH angegebenen Verzeichnisse nach C.class und führt diese aus • Beim Aufruf >java a.b.c.C sucht das Laufzeitsystem C.class in den Unterverzeichnissen a\b\c von Verzeichnissen aus CLASSPATH • Voreingestellt ist meist CLASSPATH=. (oder nichts), in Eclipse zusätzlich das Projektverzeichnis Grundlagen Programmierung Stephan Kleuker 606 Beispiel: Paketnutzung (1/2) package verwaltung.resourcen; import import import import import java.text.DateFormat; java.text.ParseException; java.text.SimpleDateFormat; java.util.Date; java.util.Locale; public class Person { private Date geburt; private String name; private Locale loc; public Person(String geburt, String name) throws ParseException{ DateFormat df = new SimpleDateFormat("dd.MM.yyyy"); this.geburt = df.parse(geburt); this.name = name; } Benutzeroberflächen und Software-Ergonomie Stephan Kleuker 607 Beispiel: Paketnutzung (2/2) public Person(String name){ this.geburt = new Date(); this.name=name; } public void setLoc(Locale loc){ this.loc=loc;} @Override public String toString(){ return name+": "+DateFormat.getDateInstance( DateFormat.LONG, loc).format(geburt); } } public static void main(String[] s) throws ParseException{ Person[] pers={new Person("31.2.2000","Ute"), new Person("Mischa")}; Locale[] loc={Locale.GERMAN, Locale.US, Locale.ITALIAN}; for(Person p:pers){ Ute: 2. März 2000 for(Locale l:loc){ Ute: March 2, 2000 p.setLoc(l); Ute: 2 marzo 2000 System.out.println(p); Mischa: 6. Februar 2012 } } Mischa: February 6, 2012 Benutzeroberflächen und Stephan Kleuker 608 } Software-Ergonomie Mischa: 6 febbraio 2012 Einige Realitätsbeichten Grundlagen Programmierung Stephan Kleuker 609 Bisher • Konsequente Orientierung an Objektorientierung • folgende Vokabeln auf alle objektorientierten Sprachen übertragbar: Klasse, Objekt, Objektvariable, Objektmethode, Sichtbarkeit, abstrakte Klasse, Klassenvariable, Klassenmethode, Paket • konsequente Orientierung an Klassen, deshalb Nutzung von Integer, Double, Boolean • Integer x=42; x ist echtes Objekt mit Methoden • Objekte der oben genannten Klassen (auch String) sind Konstanten, d. h. es können mit Methoden ihre Inhalte nicht verändert werden (gibt keine set-Methoden) Grundlagen Programmierung Stephan Kleuker 610 Java ist nicht konsequent objektorientiert • gleiches gilt für C++ und C# Hintergrund • C++ zunächst nur als Erweiterung von C konzipiert • Kompromiss, es sollten alle C-Programme weiter laufen • Resultat, C hatte einfache Datentypen, die keine Klassen sind und diese wurden nach C++ übernommen • Resultat, die durchgehende sehr saubere Idee der Objektorientierung wird mit Füßen getreten, es entsteht ein Mixed-Stil • Java sollte auch für C++-Entwickler schnell nutzbar sein, deshalb einfache, nicht objektorientierte Typen übernommen Hinweis: gibt echte objektorientierte Sprachen: Smalltalk (seit 1970er), Ruby Grundlagen Programmierung Stephan Kleuker 611 primitive Datentypen Typ repräsentiert boolean true or false char Unicode-Zeichen byte ganze Zahl mit Vorzeichen Größe 1 bit 16 bits 8 bits short - ´´ - 16 bits int - ´´ - 32 bits long - ´´ - 64 bits float IEEE 754-Fließkommazahl double void Prof. Dr. Stephan Kleuker 32 bits - ´´ - 64 bits - Stephan Kleuker 612 Beispielnutzung public class Analyse{ } public static void schleife(){ double[] arr = {0.2, 3., 7e300, 42.42}; for(int i=0; i<4; i=i+1){ System.out.println(i+" :"+ (arr[i]*i)); } 0 :0.0 } 1 :3.0 2 :1.4E301 3 :127.26 Grundlagen Programmierung Stephan Kleuker 613 Einfache Typen vor Java 5 • einfache Typen nicht in Sammlungen nutzbar • vor Java 5: Werte von Hand umwandeln (casten) public static void sammlung(){ ArrayList<Integer> al = new ArrayList<Integer>(); int x = 42; Integer xo = new Integer(x); al.add(xo); int y = (int)al.get(0); 42 System.out.println(y); } Grundlagen Programmierung Stephan Kleuker 614 Ab Java 5: Autoboxing • Kompiler wandelt bei Bedarf von int nach Integer und Integer nach int um • eher workaround, nicht wirklich sauber und auch langsam Integer x = 42; int y = x; Integer z = y; • einfache Typen können keine null-Werte annehmen • fieser Laufzeitfehler: Integer n = null; int m = n; Grundlagen Programmierung Stephan Kleuker 615 Beispiel: Autoboxing public static void boxen(){ ArrayList<Integer> al = new ArrayList<Integer>(); Integer x = new Integer(99999); al.add(42); // int nach Integer al.add(42+1); al.add(x); al.add(x+1); // Integer nach int, int nach Integer al.add(al.get(3)-1); for(int i:al){ System.out.print(i+" "); } boolean identisch = (al.get(2)==al.get(4)); System.out.println("\n identisch: "+ identisch); System.out.println(" gleich: "+ al.get(2).equals(al.get(4))); } 42 43 99999 100000 99999 identisch: false gleich: true Grundlagen Programmierung Stephan Kleuker 616 Zahlenbereiche und Genauigkeiten: int • einfache Datentypen und zugehörige Klassen können nur endlich viele Werte annehmen public static void intgenau(){ Integer max = Integer.MAX_VALUE; for(int i=0; i<3; i=i+1){ System.out.println(max+i); } Integer min = Integer.MIN_VALUE; for(int i=0; i<3; i=i+1){ System.out.println(min-i); } } Grundlagen Programmierung Stephan Kleuker 2147483647 -2147483648 -2147483647 -2147483648 2147483647 2147483646 617 Zahlenbereiche und Genauigkeiten: double (1/3) • sehr großer Zahlenbereich, Zahlen wie 1E12 ist 1*1012 • nicht jede Zahl darstellbar • bekannte besondere Werte Infinity, -Infinity, NaN public static void doubleGenau(){ Double max = Double.MAX_VALUE; for(double i=250; i<=300; i=i+10){ System.out.print(Math.pow(10,i)+" "); System.out.println(max+Math.pow(10,i)); } } 1.0E250 1.7976931348623157E308 9.999999999999999E259 1.7976931348623157E308 1.0E270 1.7976931348623157E308 1.0E280 1.7976931348623157E308 1.0E290 1.7976931348623157E308 1.0E300 Infinity Grundlagen Programmierung Stephan Kleuker 618 Zahlenbereiche und Genauigkeiten: double (2/3) public static void doublegenau2(){ Double winz = Double.MIN_NORMAL; System.out.println(winz); for(double i=10; i<=16; i=i+1){ System.out.println(Math.pow(10,-i)+": "+winz*Math.pow(10,-i)); } System.out.println(winz/0); System.out.println(0./0); 2.2250738585072014E-308 } 1.0E-10: 2.225074E-318 1.0000000000000001E-11: 2.22507E-319 1.0E-12: 2.2253E-320 1.0E-13: 2.223E-321 1.0E-14: 2.2E-322 1.0E-15: 2.5E-323 1.0E-16: 0.0 Infinity NaN Grundlagen Programmierung Stephan Kleuker 619 Zahlenbereiche und Genauigkeiten: double (3/3) public static void verschwindendeMillionen(){ Double konto = 0.0; Double abziehen = 1E6; konto = konto + 1E20 -abziehen - 1E20; System.out.println(konto); konto = 0.0; konto = konto + 1E21 -abziehen - 1E21; System.out.println(konto); konto = 0.0; konto = konto + 1E22 -abziehen - 1E22; System.out.println(konto); } -999424.0 -1048576.0 0.0 Grundlagen Programmierung Stephan Kleuker 620 Bearbeitung von Geldsummen • Beispiele zeigen: kein Double für Geldsummen • Beispiele zeigen: Integer (Long) eventuell zu klein • Ansatz: Schreibe eigene Klasse Geld • naiv: basierend auf Strings: "1234" + "567" = "1801" • alternativ ArrayList<Integer> mit den einzelnen Ziffern der Zahlen • Java bietet Klassen BigInteger und BigDecimal an • natürlich sehr viel langsamer als einfache Typen Grundlagen Programmierung Stephan Kleuker 621 Beispielnutzung von BigInteger import java.math.BigInteger; // … public static void big(){ BigInteger b = new BigInteger("12345"); for(int i=0; i<4; i=i+1){ b = b.multiply(b); System.out.println(b); } } 152399025 23225462820950625 539422123247359763587428687890625 290976227048689786699404610508159269970874403200651318511962890625 Grundlagen Programmierung Stephan Kleuker 622 Inkrement- und Dekrementoperatoren Operator Bedeutung x++ ergibt x und erhöht x um 1 ++x ergibt x+1 und erhöht x um 1 x-- ergibt x und verringert x um 1 --x ergibt x-1 und verringert x um 1 Prof. Dr. Stephan Kleuker Stephan Kleuker 623 Beispiele für Operatorennutzung public class IncTest { public static void main(String args[]){ int i = 1; System.out.println(“i: “+ i); i: 1 System.out.println(“++i: “+ ++i); ++i: System.out.println(“i++: “+ i++); i++: System.out.println(“i: “+ i); i: 3 System.out.println(“--i: “+ --i); --i: System.out.println(“i--: “+ i--); i--: System.out.println(“i: “+ i); i: 1 } 2 2 2 2 } Prof. Dr. Stephan Kleuker Stephan Kleuker 624 Typkonvertierungen (elementare Typen) Generell: Variablen von Typ x dürfen nur Elemente dieses Typs zugewiesen werden Bei Datentypen findet automatisch eine Konvertierung in größeren Typen statt (niemals automatisch in Gegenrichtung) byte short int long float double char • Umwandlung in die andere Richtung mit Casten (Typ in Klammern) int x= double double // int int z3 4; y= 2; z1= x/y; z2= x/y; gibt Fehler = (int) (x/y); Prof. Dr. Stephan Kleuker Stephan Kleuker 625 Logische Operatoren Operator Bedeutung & Und mit vollständiger Auswertung | Oder mit vollständiger Auswertung ^ wahr, wenn Operanden unterschiedlich sind ! Negation && Und mit Kurzschlussauswertung || Oder mit Kurzschlussauswertung Prof. Dr. Stephan Kleuker Stephan Kleuker 626 Beispielauswertung logischer Operatoren (1/2) public static boolean effekt(String s){ System.out.println("Aha "+s); return true; } public static void seiteneffekt(){ boolean wahr = true; boolean falsch = false; if(wahr || effekt("A")){ } if(wahr | effekt("B")){ } if(false && effekt("C")){ } if(false & effekt("D")){ } } Grundlagen Programmierung Stephan Kleuker Aha B Aha D 627 Beispielauswertung logischer Operatoren (2/2) public static void seiteneffekt2(){ if(effekt("E") ^ effekt("F")){ System.out.println("Hoho"); } if(effekt("G") ^ !effekt("H")){ System.out.println("Haha"); } if(!effekt("I") ^ effekt("J")){ System.out.println("Huhu"); } if(!effekt("K") ^ !effekt("L")){ System.out.println("Hihi"); } } Grundlagen Programmierung Stephan Kleuker Aha E Aha F Aha G Aha H Haha Aha I Aha J Huhu Aha K Aha L 628 Code-Formatierungen • bisherige Code-Formatierungen können so beibehalten werden, da sie Lesbarkeit garantieren • Möglichkeit: Weglassen von this und super • Möglichkeit: Weglassen geschweifter Klammern, wenn nur ein Befehl folgt • Möglichkeit: Direkter Zugriff auf Objektvariablen, wenn Objekte gleicher Klassen betrachtet werden • Anmerkung: Viele Coding-Guidelines in Unternehmen verbieten zumindest die ersten beiden Möglichkeiten • Rat: Wenn Sie bisherige Regeln anwenden, ändern Sie Ihren Stil nicht !!! Grundlagen Programmierung Stephan Kleuker 629 Beispiel: Klasse Punkt im Minimalstil (1/2) public class Punkt { private int x; private int y; public Punkt (int xWert, int yWert){ x = xWert; y = yWert; } public boolean istNullpunkt(){ if (x==0 && y==0) return true; else return false; } Grundlagen Programmierung Stephan Kleuker 630 Beispiel: Klasse Punkt im Minimalstil (2/2) public boolean equals(Object o){ if (o==null || !(o instanceof Punkt)) return false; Punkt p = (Punkt) o; if (x==p.x && y==p.y) return true; else return false; } } Grundlagen Programmierung Stephan Kleuker 631 Programmieren ohne echte Klassen Grundlagen Programmierung Stephan Kleuker X 632 Braucht man Objektorientierung? • Ja, da so eine wesentliche Möglichkeit zur Strukturierung von Programmen geschaffen wird • Objekte sollen Ihre Aufgaben selbst erledigen, keine Hauptklasse, die alles über get- und set-Methoden steuert • Nein, da frühere Programmiersprachen (z. B. Fortran, Cobol, PL/1) keine Objektorientierung haben • da gab es aber massive Probleme mit großen Programmen • Nein, da für hardware-nahe Systeme oft keine objektorientierten Sprachen zur Verfügung stehen (aber C) Grundlagen Programmierung Stephan Kleuker X 633 Programme ohne Objektorientierung • Anschaulich stehen nur Klassenvariablen und Klassenmethoden zur Verfügung • Weiterhin gibt es Klassen (Strukturen), die zur Beschreibung von Datenstrukturen genutzt werden (ähnlich zur Objektorientierung, Erzeugung einer neuen Struktur mit new) public class Punkt{ public int x; // in OO nie erlaubt public int y; // direkter Kündigungsgrund } Grundlagen Programmierung Stephan Kleuker X 634 Beispiel: Datenbearbeitung (1/3) public class Punktbearbeitung{ public static Punkt neuerPunkt(int x, int y){ Punkt ergebnis = new Punkt(); ergebnis.x = x; ergebnis.y = y; return ergebnis; } public static Boolean gleich(Punkt p1, Punkt p2){ return (p1.x==p2.x && p1.y==p2.y); } Grundlagen Programmierung Stephan Kleuker X 635 Beispiel: Datenbearbeitung (2/3) public static Boolean istNullpunkt(Punkt p){ return p.x==0 && p.y==0; } public static void verschieben(Punkt p, int dx, int dy){ p.x = p.x + dx; p.y = p.y + dy; } public static void ausgeben(Punkt p){ System.out.print("["+p.x+","+p.y+"]"); } } Grundlagen Programmierung Stephan Kleuker X 636 Beispiel: Datenbearbeitung (3/3) public class Main{ public static void punktanalyse(){ Punkt p1; p1 = Punktbearbeitung.neuerPunkt(6,9); Punktbearbeitung.ausgeben(p1); System.out.println("\n" [6,9] +Punktbearbeitung.istNullpunkt(p1)); false Punkt p2 = Punktbearbeitung.neuerPunkt(3,6); [3,6] Punktbearbeitung.ausgeben(p2); false System.out.println("\n" true +Punktbearbeitung.gleich(p1,p2)); false Punktbearbeitung.verschieben(p2,3,3); System.out.println(Punktbearbeitung.gleich(p1,p2)); System.out.println((p1==p2)); } Grundlagen Programmierung Stephan Kleuker X 637 Neue Datenstruktur: Liste (1/5) public class Punktliste{ public Punkt inhalt; public Punktliste weiter=null; // // // // // ähnlich zu Punkt und Punktbearbeitung wäre auch eine Aufteilung in Punktliste und Punktlistenbearbeitung sinnvoll, generell könnten auch alle Klassenmethoden in einer Datei (Klasse) stehen. public static Punktliste neuePunktliste(Punkt p){ Punktliste ergebnis = new Punktliste(); ergebnis.inhalt = p; return ergebnis; } Stephan Kleuker Grundlagen Programmierung X 638 Neue Datenstruktur: Liste (2/5) public static void ausgeben(Punktliste pl){ Punktliste tmp = pl; System.out.print("["); while(tmp != null){ Punktbearbeitung.ausgeben(tmp.inhalt); tmp = tmp.weiter; } System.out.println("]"); } Grundlagen Programmierung Stephan Kleuker X 639 Neue Datenstruktur: Liste (3/5) public static Punktliste anhaengen(Punktliste pl, Punkt p){ Punktliste tmp = pl; if(tmp == null){ return Punktliste.neuePunktliste(p); } while(tmp.weiter != null){ tmp = tmp.weiter; } tmp.weiter = Punktliste.neuePunktliste(p); return pl; } } Grundlagen Programmierung Stephan Kleuker X 640 Neue Datenstruktur: Liste (4/5) // in Main public static void listenanalyse(){ Punkt p1 = Punktbearbeitung.neuerPunkt(6,9); Punkt p2 = Punktbearbeitung.neuerPunkt(3,6); Punktliste pe = null; Punktliste.ausgeben(pe); pe = Punktliste.anhaengen(pe,p1); Punktliste.ausgeben(pe); // weiter nächste Folie [] [[6,9]] Grundlagen Programmierung Stephan Kleuker X 641 Neue Datenstruktur: Liste (5/5) pe = Punktliste.anhaengen(pe ,Punktbearbeitung.neuerPunkt(6,9)); pe = Punktliste.anhaengen(pe,p2); Punktliste.ausgeben(pe); pe = Punktliste.anhaengen(pe,p1); Punktliste.ausgeben(pe); p1.x = 9; Punktliste.ausgeben(pe); } } Grundlagen Programmierung [[6,9][6,9][3,6]] [[6,9][6,9][3,6][6,9]] [[9,9][6,9][3,6][9,9]] Stephan Kleuker X 642 Laden und Speichern Grundlagen Programmierung Stephan Kleuker 643 Die Klasse File • Objekt von File wird zur Abfrage von Informationen über Dateien und Verzeichnisinhalte genutzt • Die Klasse File enthält z. B. Methoden zum – Auflisten von Dateien und Verzeichnissen – Prüfen, ob eine Datei existiert/lesbar/sichtbar schreibbar – Umbenennen / Löschen von Dateien bzw. Verzeichnissen • Beispiel: Wir wollen mit einem File arbeiten, dessen relativer Pfad unter Windows „ .\z\Hi.txt “ lautet – 1. Möglichkeit: File f= new File("./z/Hi.txt"); – man muss das Trennsymbol von Unix nutzen – 2. Möglichkeit: File f= new File(".\\z\\Hi.txt"); • Backslash (\) leitet in Java Sonderzeichen ein, deshalb \\ • 3. Möglichkeit: systemspezifischer Trenner in Klassenvariable String tr= File.separator; File f= new File("."+tr+"z"+tr+"Hi.txt"); Grundlagen Programmierung Stephan Kleuker 644 Einige Methoden der Klasse File (ohne Parameter) - testet, ob die Datei lesbar ist boolean canWrite() - testet, ob die Datei beschreibbar ist boolean delete() - löscht die Datei (bzw. das Verzeichnis) boolean exists() - testet, ob die Datei existiert boolean renameTo(File) - benennt die Datei um boolean mkdir() - erzeugt ein Verzeichnis boolean mkdirs() - erzeugt einen Verzeichnisbaum String[] list() - liefert Liste von Dateien des Verzeichnisses String getAbsolutePath(), String getPath() - liefert den entsprechenden Pfad der durch File beschriebenen Datei zurück String getName() - gibt den Namen der Datei zurück boolean isFile(), boolean isDirectory() - Abfrage der Dateiart • boolean canRead() • • • • • • • • • • Grundlagen Programmierung Stephan Kleuker 645 Dateianalyse (1/6) import java.io.File; import java.io.IOException; public class FileAnalyse{ public FileAnalyse(){ this.dialog(); } public void datei(File datei){ if(datei.canRead()){ System.out.println("lesbar"); } if(datei.canWrite()){ System.out.println("beschreibbbar"); } if(datei.canExecute()){ System.out.println("ausfuehrbar"); } } Grundlagen Programmierung Stephan Kleuker 646 Dateianalyse (2/6) public void dialog(){ EinUndAusgabe io = new EinUndAusgabe(); String datei = ""; File file; while(!datei.toLowerCase().equals("ende")){ System.out.print("zu untersuchende Datei: "); datei = io.leseString(); file = new File(datei); if (!file.exists()){ System.out.println("existiert nicht"); } else { this.allgemein(file); if(file.isDirectory()){ this.verzeichnis(file); } else { this.datei(file); } } } Grundlagen Stephan Kleuker } Programmierung 647 Dateianalyse (3/6) public void allgemein(File datei){ try{ System.out.println(" Pfad: "+datei.getAbsolutePath() +"\n Pfad: " + datei.getCanonicalPath() +"\n Pfad: " + datei.getPath() +"\n oben: " + datei.getParentFile() +"\n versteckt: " + datei.isHidden() +"\n veraendert: " + datei.lastModified() +"\n Laenge: " + datei.length()); } catch (IOException e){ System.out.println("Fehler: "+e); } } public void verzeichnis(File datei){ System.out.println("Enthaelt:"); for(String d: datei.list()){ System.out.println(" " + d); } Grundlagen Stephan Kleuker } Programmierung } 648 Dateianalyse (4/6) zu untersuchende Datei: . Pfad: F:\workspaces\BlueJWork11\FileAnalyse\. Pfad: F:\workspaces\BlueJWork11\FileAnalyse Pfad: . oben: null versteckt: false veraendert: 1324637498000 Laenge: 0 Enthaelt: package.bluej README.TXT FileAnalyse.java EinUndAusgabe.java EinUndAusgabe.class EinUndAusgabe.ctxt FileAnalyse.class FileAnalyse.ctxt Grundlagen Programmierung Stephan Kleuker 649 Dateianalyse (5/6) zu untersuchende Datei: C:\bootmgr Pfad: C:\bootmgr Pfad: C:\bootmgr Pfad: C:\bootmgr oben: C:\ versteckt: true veraendert: 1162461237049 Laenge: 438840 lesbar ausfuehrbar Grundlagen Programmierung Stephan Kleuker 650 Dateianalyse (6/6) zu untersuchende Datei: F:\workspaces\BlueJWork11\FileAnalyse\FileAnalyse.java Pfad: F:\workspaces\BlueJWork11\FileAnalyse\FileAnalyse.java Pfad: F:\workspaces\BlueJWork11\FileAnalyse\FileAnalyse.java Pfad: F:\workspaces\BlueJWork11\FileAnalyse\FileAnalyse.java oben: F:\workspaces\BlueJWork11\FileAnalyse versteckt: false veraendert: 1324641712000 Laenge: 1851 lesbar beschreibbbar ausfuehrbar Grundlagen Programmierung Stephan Kleuker 651 Ein- und Ausgabe in Java • Basisansatz: Lesen (Input) oder Schreiben (Output) einzelner Bytes ( machbar, aber für Datentypen, die größer als Byte sind, unhandlich) Schreiben Lesen • Es handelt sich um Streams • Streams sind immer unidirektional • Das Paket java.io stellt verschiedene Klassen zur Verfügung, die auf dem Streamkonzept basieren • Hinweis: wir arbeiten hier hauptsächlich mit 8-Bit-Versionen (gibt gleiche Klassen für Uni-Code, 16 Bit) Grundlagen Programmierung Stephan Kleuker 652 Einfaches Schreiben eines Files – Beispiel (1/2) import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; public class Analyse { public static void fileOutput() throws FileNotFoundException, IOException{ FileOutputStream o = new FileOutputStream("xxx"); String s="Hello again"; for(int i=0; i<s.length(); i++){ o.write(s.charAt(i)); } o.close(); } }Grundlagen Programmierung Stephan Kleuker 653 Einfaches Schreiben eines Files – Beispiel (2/2) Grundlagen Programmierung Stephan Kleuker 654 Erinnerung: Sauberes Weiterreichen von Exceptions • in diesem Abschnitt nur Lesen-Schreiben, fehlt try-finally public static void fileOutput() throws FileNotFoundException, IOException{ FileOutputStream o=null; try{ o = new FileOutputStream("xxx"); String s="Hello again"; for(int i=0; i<s.length(); i++){ o.write(s.charAt(i)); } } finally{ if(o!=null){ o.close(); } } Stephan Kleuker 655 Grundlagen } Programmierung Einfaches Schreiben eines Files - Analyse FileOutputStream o = new FileOutputStream("xxx"); String s="Hello again"; for(int i=0; i<s.length(); i++){ o.write(s.charAt(i)); } o.close(); • • • • Im Konstruktor wird ein Filename (oder File) übergeben Es kann nur Byte-Weise geschrieben werden nur verschiedene einfache Varianten von write() verfügbar Generell ist es wichtig, beim Arbeiten mit Files diese am Ende zu schließen ( close() ) • es gibt verschiedene Konstruktoren, z.B.: public FileOutputStream(String name, boolean append) Grundlagen Programmierung Stephan Kleuker 656 Einfaches Lesen eines Files FileInputStream i= new FileInputStream("xxx"); int in = i.read(); while(in!=-1) { System.out.print((char)in); in=i.read(); } i.close(); • Alle Bytes werden grundsätzlich als int eingelesen, müssen bei Bedarf in byte oder char gewandelt werden • Das File-Ende wird durch den Wert -1 erkannt • Vorgestelltes Lesen und Schreiben ineffizient, da jede Methode erneut auf das Betriebssystem zugreifen muss Grundlagen Programmierung Stephan Kleuker 657 Beispiel: Datei kopieren // mehrere Imports weggelassen public class Copy{ public static void main(String[] s) throws IOException{ FileInputStream in = new FileInputStream(s[0]); FileOutputStream out= new FileOutputStream(s[1]); int zeichen=0; while(zeichen!=-1){ zeichen=in.read(); if (zeichen!=-1) { out.write(zeichen); } } in.close(); out.close(); } }Grundlagen Programmierung Stephan Kleuker 658 Schnellere Ein- und Ausgabe in Java • einzulesende (bzw. auszugebende) Daten zwischenpuffern und bei vollem Puffer verarbeiten Ausgabe Puffer out(a) a out(b) a b out(c) a b c out(d) abc d Grundlagen Programmierung Stephan Kleuker 659 Die Klasse BufferedOutputStream • Daten werden in einen Puffer geschrieben, dessen Inhalt nur dann in den Stream geschrieben wird, wenn er voll ist BufferedOutputStream o = new BufferedOutputStream( new FileOutputStream("xxa"),4); String s="Hello again"; for(int i=0;i<s.length();i++) { o.write(s.charAt(i)); } o.close(); • BufferedOutputStream ermöglicht Daten zu schreiben, ohne bei jeden Aufruf physikalisch auf das Gerät zuzugreifen • explizites Leeren des Puffers mit flush() Grundlagen Programmierung Stephan Kleuker 660 Die Klasse BufferedInputStream • Daten werden blockweise in einen Puffer gelesen, auf dem bei jeder Leseaktion zugegriffen wird BufferedInputStream i= new BufferedInputStream( new FileInputStream("xxa"),4); int in = i.read(); while(in!=-1){ System.out.print((char)in); in=i.read(); } • BufferedInputStream ermöglicht Daten zu lesen, ohne bei jeden Aufruf physikalisch auf das Gerät zuzugreifen • BufferedInputStream enthält die Methoden • mark() zum markieren einer Position im Puffer • reset() zur Zurückführung des Pufferzeigers auf die letzte Markierung Grundlagen Programmierung Stephan Kleuker 661 Beispiel public static void bufferedIO() throws IOException{ BufferedOutputStream o = new BufferedOutputStream( new FileOutputStream("xxa"),4); String s="Hello again"; for(int i=0;i<s.length();i++){ o.write(s.charAt(i)); } BufferedInputStream i = new BufferedInputStream( new FileInputStream("xxa"),4); int in = i.read(); while(in!=-1){ Ausgabe: System.out.print((char)in); in=i.read(); Hello ag } i.close(); o.close(); } am Ende aber: Grundlagen Programmierung Stephan Kleuker 662 mächtigeres Arbeiten mit Files • Grundsätzlich kann man beliebige Speicher- und Lesefunktionalitäten auf FileInputStream und FileOutputStream aufbauen • Da sich diese Entwicklung komplexer Speicher- und Leseansätze sich häufig wiederholt, gibt es in der Klassenbibliothek verschiedene mächtigere Klassen zur Zusammenarbeit mit Files • Ein Ansatz wäre, von den genannten Klassen zu erben und die so zu erweitern • Java-Ansatz ist Aggregation, die mächtigeren Klassen haben ein Objekt der oben genannten Klasse als Objektvariable und verwalten den Zugriff Grundlagen Programmierung Stephan Kleuker 663 Die Klasse DataOutputStream • Mit Hilfe eines DataOutputStreams können einfache Datentypen binär geschrieben werden • • • • • • • • writeBoolean(); writeByte(); writeChar(); writeDouble(); writeFloat(); writeInt(); writeLong(); writeShort(); • Konstruktor erwartet einen Outputstream als Parameter public DataOutputStream(OutputStream os); • Analog existiert DataInputStream, mit zusätzlicher Methode readLine() zum Einlesen eines Strings Grundlagen Programmierung Stephan Kleuker 664 Beipiel (1/2) import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class Punkt { private int x; private int y; public Punkt(int a, int b) {this.x = a; this.y = b;} public void speichern(DataOutputStream o) throws IOException{ o.writeInt(this.x); o.writeInt(this.y); } public static Punkt lesen(DataInputStream i) throws IOException{ return new Punkt(i.readInt(),i.readInt()); } Grundlagen Programmierung Stephan Kleuker 665 Beispiel (2/2) public String toString(){ return "X: "+this.x+" Y: "+this.y; } } public static void main(String[] args) throws IOException { DataOutputStream o= new DataOutputStream( new FileOutputStream("aab")); Punkt p1= new Punkt(300,400); Punkt p2= new Punkt(500,600); p1.speichern(o); p2.speichern(o); o.close(); DataInputStream i= new DataInputStream( new FileInputStream("aab")); Punkt p3= Punkt.lesen(i); Punkt p4= Punkt.lesen(i); Ausgabe: System.out.println(p3+"\n"+p4); X: 300 Y: 400 i.close(); X: 500 Y: 600 }Grundlagen Programmierung Stephan Kleuker 666 Ein- und Ausgabe von Objekten (1/2) • Werden die Werte der Datenfelder eines Objektes in einen Bytestrom überführt, der sich rekonstruieren lässt, so spricht man von Objektserialisierung • Java stellt dazu zwei Klassen zur Verfügung ObjectOutputStream: public writeObject(Object o) throws IOException ObjectInputStream: public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException • Objekte werden beim Schreiben und Lesen rekursiv abgearbeitet (d. h. immer alle Objektvariablen) Grundlagen Programmierung Stephan Kleuker 667 Ein- und Ausgabe von Objekten (2/2) • Schnittstelle Serializable dient zur Kennzeichnung, dass ein Objekt einer Klasse serialisierbar ist • Schnittstelle selbst deklariert keine Methoden • Klasse nur serialisierbar, wenn alle Objektvariablen serialisierbar • bis auf einige graphische Klassen sind alle wichtigen Klassen der Klassenbibliothek serialisierbar • grundsätzlich ist "implements Serializable" immer gute Idee • Objekt-Serialisierung: – Vorteile: schnell, recht kompakte Daten – Nachteile: mit neuen Klassenversionen nicht mehr nutzbar, können von keinen anderen Programmen gelesen werden Grundlagen Programmierung Stephan Kleuker 668 Serialisierungsbeispiel (1/3) import import import import import import java.io.Serializable; java.io.IOException; java.io.FileOutputStream; java.io.ObjectOutputStream; java.io.FileInputStream; java.io.ObjectInputStream; public class Person implements Serializable{ private String name; private String vorname; private static final String DATEI = "text.txt"; private static final long serialVersionUID = 2L; public Person (String n, String v){ this.name = n; this.vorname = v; } @Override public String toString(){ return this.vorname+" "+this.name; } Programmierung Grundlagen Stephan Kleuker 669 Serialisierungsbeispiel (2/3) public static void schreiben() throws IOException{ Person pers1 = new Person ("Maier", "Anja"); ObjectOutputStream out= new ObjectOutputStream (new FileOutputStream(DATEI)); out.writeObject (pers1); out.writeObject (new Person ("Schulz", "Oleg")); out.writeObject ("Hallo"); out.close(); } public static void lesen() throws IOException, ClassNotFoundException{ ObjectInputStream in = new ObjectInputStream (new FileInputStream (DATEI)); for(int i=0; i<3; i=i+1){ Object o = in.readObject(); // sonst casten System.out.println(o); } in.close(); Grundlagen Programmierung Stephan Kleuker 670 } Serialisierungsbeispiel (3/3) public static void main(String[] s)throws IOException, ClassNotFoundException{ Person.schreiben(); Person.lesen(); } Grundlagen Programmierung Stephan Kleuker 671 SerialVersionUID • serialisierte Objekte typischerweise nur mit der gleichen Klasse einlesbar, die auch zum Schreiben genutzt wurde • Änderungen an Objektvariablen macht serialisierte Objekte nicht nutzbar • Lösung: Konverter schreiben • Lösung: XMLEncoder und XMLDecoder nutzen • woran erkennt neue Klasse, dass zu alte Objekte gelesen werden soll? – Nutzung eine speziellen vorgegebenen Klassenvariable serialVersionUID – Nummer wird mit serialisiert – stimmt sie beim Laden nicht überein, gibt es Fehlermeldung Grundlagen Programmierung Stephan Kleuker 672 serialVersionUID – Warning in Java • typische Eclipse-Meldung • Lösungsvorschläge in Eclipse (Linksklick) • im ersten Fall beginnt Nummerierung mit 1 (1L für long) • sonst zufällige Nummer Grundlagen Programmierung Stephan Kleuker 673 Beispielproblemfall public class Person implements Serializable{ private String name; private String vorname; private static final String DATEI = "text.txt"; private static final long serialVersionUID = 1L; • Person.schreiben() • Änderung: private static final long serialVersionUID = 2L; • Person.lesen() Grundlagen Programmierung Stephan Kleuker 674 transient Das Schlüsselwort transient: Unterdrückung von Objektvariablen beim Speichern public class person implements Serializable{ private String name; private String vorname; private transient int alter; .... } Grundlagen Programmierung Stephan Kleuker 675 Erinnerung: Uni-Code • Java als Sprache des Internets nutzt Uni-Code • Uni-Code ist echte Obermenge von ASCII und ISO 8859-1 (Latin 1) • In Java gibt es 8-Bit-Klassen (etwas schneller, einfacher) und 16-Bit-Klassen zum File-Handling (und Klassen, um 8Bit-Welt mit 16-Bit-Welt zu verknüpfen) • In Java hat Byte-Stream und Character-Stream Klassen Byte-Stream Character-Stream FileInputStream FileReader FileOutputStream FileWriter BufferedInputStram BufferedReader BufferedOutputStream BufferedWriter Grundlagen Programmierung Stephan Kleuker 676 Klassenvariablen von System public static final InputStream in The "standard" input stream. This stream is already open and ready to supply input data. Typically this stream corresponds to keyboard input or another input source specified by the host environment or user. public static final PrintStream out The "standard" output stream. This stream is already open and ready to accept output data. Typically this stream corresponds to display output or another output destination specified by the host environment or user. See the println methods in class PrintStream. public static final PrintStream err The "standard" error output stream. This stream is already open and ready to accept output data. Typically this stream corresponds to display output or another output destination specified by the host environment or user. Grundlagen Programmierung Stephan Kleuker 677 Einlesen von der Tastatur public class EinUndAusgabe { public String leseString(){ String ergebnis; BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); try { ergebnis=in.readLine(); } catch (IOException e) { ergebnis=""; } return ergebnis; } public int leseInt(){ int erg; try { erg=Integer.decode(leseString()).intValue(); } catch (NumberFormatException e) { erg=-1; } return erg; Stephan Kleuker Grundlagen Programmierung } 678 Aufzählungen Grundlagen Programmierung Stephan Kleuker 679 Aufzählungen für Anfänger und Klassiker public class Programmiererfahrung { private String[] stufen={"nicht vorhanden", "Grundkenntnisse","alte Projekterfahrung", "Projektmitarbeiter", "Experte"}; private int stufenwert=0; ... } public class Erfahrung { public final static int NICHT_VORHANDEN=0; public final static int GRUNDKENNTNISSE=1; public final static int ALTE_PROJEKTERFAHRUNG=2; public final static int PROJEKTMITARBEITER=3; public final static int EXPERTE=4; } Zugriff mit: int meineErfahrung= Erfahrung.NICHT_VORHANDEN; Grundlagen Programmierung Stephan Kleuker 680 Aufzählungen mit Enum • Enum ist spezielle Art von Klasse (kann damit Methoden beinhalten) • Werte als einfache Texte, beginnend mit Buchstaben aufschreiben public enum Erfahrung { NICHT_VORHANDEN, GRUNDKENNTNISSE, ALTE_PROJEKTERFAHRUNG, PROJEKTMITARBEITER, EXPERTE } Grundlagen Programmierung Stephan Kleuker 681 Aufzählungen mit Enum - Nutzung public class Spielerei { public static void main (String[] s){ Erfahrung ich= Erfahrung.NICHT_VORHANDEN; System.out.println(ich); for(Erfahrung e: Erfahrung.values()){ System.out.println(e); } NICHT_VORHANDEN } NICHT_VORHANDEN } GRUNDKENNTNISSE ALTE_PROJEKTERFAHRUNG PROJEKTMITARBEITER EXPERTE Grundlagen Programmierung Stephan Kleuker 682 Weitere Methoden von enum-“Klassen“ (1/2) Erfahrung ich= Erfahrung.NICHT_VORHANDEN; System.out.println(ich.getClass()); System.out.println(ich.compareTo(Erfahrung.NICHT_VORHANDEN)); System.out.println(ich.compareTo(Erfahrung.EXPERTE)); System.out.println(ich.equals(0)); System.out.println(ich.equals(1)); System.out.println(ich.equals(Erfahrung.NICHT_VORHANDEN)); class Erfahrung 0 -4 false false true Grundlagen Programmierung Stephan Kleuker 683 Weitere Methoden von enum-“Klassen“ (2/2) System.out.println(ich.getDeclaringClass()); System.out.println(ich.name()); System.out.println(ich.ordinal()); System.out.println(Erfahrung.valueOf("EXPERTE")); try{ System.out.println(Erfahrung.valueOf("Experte")); }catch (IllegalArgumentException e){ System.out.println(e); } System.out.println(Erfahrung.valueOf(Erfahrung.class,"EXPERTE")); class Erfahrung NICHT_VORHANDEN 0 EXPERTE java.lang.IllegalArgumentException: No enum const Experte EXPERTE Grundlagen Programmierung Stephan Kleuker 684 Objekte von enum-Klassen • Mit enum werden besondere Klassen definiert, sind final (keine Vererbung möglich), keinen von außen nutzbaren Konstruktor • Durch Erfahrung ich= Erfahrung.NICHT_VORHANDEN; erhält man ein Objekt der Klasse Erfahrung • D. h. Enum-Klassen können zusätzlich „normale“ Exemplarmethoden und Exemplarklassen enthalten (auch z. B. toString()) • Klassenmethodenaufruf Erfahrung.klassenmethode(); • Methodenaufruf: ich.exemplarmethode(); Grundlagen Programmierung Stephan Kleuker 685 Erweiterte Möglichkeiten mit enum (1/2) • Aufzählungswerte können Parameter haben, die im Konstruktor verarbeitet werden public enum Coin { PENNY(1), NICKEL(5), DIME(10), QUARTER(25); private final int value; Coin(int value) { this.value = value; } public int value() { return value; } } Grundlagen Programmierung Stephan Kleuker 686 Erweiterte Möglichkeiten mit enum (2/2) public class CoinAnalyse { private enum CoinColor { COPPER, NICKEL, SILVER } public static void main(String[] args) { for (Coin c : Coin.values()){ System.out.println(c +":"+c.value()+"c "+color(c)); } } PENNY:1c COPPER private static CoinColor color(Coin c) { NICKEL:5c NICKEL DIME:10c SILVER switch(c) { case PENNY: return CoinColor.COPPER; QUARTER:25c SILVER case NICKEL: return CoinColor.NICKEL; case DIME: case QUARTER: return CoinColor.SILVER; default: throw new AssertionError("Unknown coin: " + c); } } }Grundlagen Programmierung Stephan Kleuker 687 Kartenstapel (1/3) public enum Farbe { KARO, HERZ, KREUZ, PIK; @Override public String toString(){ switch(this){ case KARO: return("Karo"); case HERZ: return("Herz"); case KREUZ: return("Kreuz"); case PIK: return("Pik"); default: return(""); } } } Prof. Dr. Stephan Kleuker Stephan Kleuker 688 Kartenstapel (2/3) public enum Wert { SIEBEN("7"), ACHT("8"), NEUN("9"), ZEHN("10"), BUBE("Bube"), DAME("Dame"), KOENIG("Koenig"), AS("As"); private String text; Wert(String text){ this.text=text; } @Override public String toString(){ return text; } } Prof. Dr. Stephan Kleuker Stephan Kleuker 689 Kartenstapel (3/3) public class Karte { private Farbe farbe; private Wert wert; ... public class Kartenstapel { private ArrayList<Karte> stapel=new ArrayList<Karte>(); public static Kartenstapel gibAlleKarten(){ Kartenstapel k= new Kartenstapel(); for(Farbe f: Farbe.values()) for(Wert w: Wert.values()) k.add(new Karte(f,w)); return k; } //... Prof. Dr. Stephan Kleuker Stephan Kleuker 690