Programmierkurs Java Konstruktor, Statische Methoden Packages Prof. Dr. Stefan Fischer Institut für Telematik, Universität zu Lübeck http://www.itm.uni-luebeck.de/people/fischer Initialisierung von Datenstrukturen • Weiteres Problem prozeduraler Programmierung – Initialisierung von Datenstrukturen – Unklare Zuständigkeit • Häufig nur durch Dokumentation ersichtlich – Beispiel: „Beim Verwenden der Datenstruktur Lampe muss zu Beginn die Funktion init_helligkeit(Lampe l); aufgerufen werden“ – Wird häufig vergessen – Führt potenziell zu undefiniertem bzw. ungewolltem Verhalten #2 Wichtiges Prinzip: Konstruktion • Instanzen können bei der Erzeugung automatisch initialisiert werden – Aufruf von speziellen Methoden durch Java – Geschieht bei der Erzeugung mittels new • Diese speziellen Methoden heißen „Konstruktoren“ – Werden automatisch bei der Erzeugung (durch new) aufgerufen – Bringen Instanzen in einen „sicheren“ initialen Zustand • In anderen Programmiersprachen gibt es auch Destruktoren – z.B. Freigeben von Speicher, etc. #3 Umsetzung in Java • Konstruktoren: Methoden mit speziellem Namen und Rückgabetyp – Name der Methode: Klassenname – Rückgabetyp: Keiner, nicht einmal void – Konstruktor sollte alle Attribute initialisieren (guter Stil) • Syntax: Klassenname(Typ1 Name1, Typ2 Name2, …) {…} – Beispiel: Punkt(double x, double y) {...} • Eine Klasse kann mehrere Konstruktoren haben – Gleiches Prinzip wie Überladen von Methoden • Ein Konstruktor kann als erstes anderen Konstruktor aufrufen – Syntax: this(...parameter...); #4 Beispiel • Erzeugung von zwei Punkt-Instanzen in main • Zeile 19 – – – • Kein Parameter an den Konstruktor Aufruf des parameterlosen Konstruktors aus Zeile 6 Dieser ruft Konstruktor in Zeile 10 auf Verwendung von „this“ Zeile 20 – – Zwei doubleParameter Aufruf des Konstruktors in Zeile 10 #5 Statische Methoden und Attribute Statische Methoden • Methoden verändern den Zustand einer Objektinstanz – bzw. liefern Informationen über deren Zustand • Manchmal praktisch, dieses Modell zu durchbrechen – Main-Methode (Programmstart: keine Instanzen) – Mathematische Funktionen (Wurzel, Sinus, Kosinus, etc.) • Primitive Datentypen sind keine Objekte 1.sinus() funktioniert nicht • new Sinus(1).getWert() zu großer Overhead • Beispiele http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html #7 Statische Methoden und Attribute • Schlüsselwort static (unabhängig von Klasseninstanzen) – Es gibt keine „this“-Referenz (keine Instanz verfügbar) – Statische Elemente können nur andere statische Elemente verwenden – Aufruf anderer statischer Methoden oder Verwenden statischer Variablen • Statische Methoden – Definition: static void statischeMethode(...) {...} – Verwendung: Klassenname.methodenname(Parameter) • Statische Attribute – Definition: static int statischesAttribut; – Verwendung: Klassenname.attributname; #8 Beispiel: Standardausgabe • System.out.println(“Hallo“); Klasse „System“ Statisches Attribut „out“ Teil der Java KlassenBibliothek Instanz der Klasse PrintStream Methode „println“ Implementiert in PrintStream #9 Beispiel: Instanzzähler #10 Beispiel statisch/nicht-statisch #11 Packages Probleme großer Projekte • Programme können aus vielen Klassen bestehen – Verschiedene logische Funktionskomponenten – Müssen nicht von einem Hersteller bzw. Programmierer stammen – Normalerweise besteht ein Programm aus Teilen vieler Programmierer (externe Bibliotheken, Teams, ...) • Probleme – Klassennamen doppelt vergeben Eindeutigkeit – Unklare Zuordnung Funktionseinheit Klasse #13 Beispiel: Zwei „Punkt“-Klassen #14 Beispiel: Zwei „Punkt“-Klassen • Wie unterscheidet man die beiden Klassen im gleichen Programm? • Eine Möglichkeit: umbenennen – „PunktRGB“ und „PunktKoordinate“ – Macht Programme oft schlechter lesbar (lange Namen) • Beispiele (Windows API, Ungarische Notation) – RtlWriteDecodedUcsDataIntoSmartLBlobUcsWritingContext – ConvertSecurityDescriptorToStringSecurityDescriptor – EapHostPeerQueryUIBlobFromInteractiveUIInputFields – AccessCheckByTypeResultListAndAuditAlarmByHandle – SetupRemoveInstallSectionFromDiskSpaceList #15 Namensräume • Alternative zu langen Namen • Eingruppieren von Klassen in verschiedene Namensräumen – Unterscheidung von Klassen durch Angabe des Namensraums – Beispiel: Punkt aus „Farbe“ vs. Punkt aus „Mathe“ • Namensräume in Java: sog. „packages“ Namensraum „Farbe“ Namensraum „Mathe“ Punkt Punkt Attribute: - int rot; - int gruen; - int blau Attribute: - double x; - double y; Methoden: Methoden: - void setze(double x, double y); - void verschiebe(double dx, double dy); - void rotiere(double radians); #16 Packages • Es ist üblich, Klassen in Packages zu gruppieren – Bessere Übersichtlichkeit – Vorbeugung von Namenskonflikten – Zusammengehörige Klassen kennzeichnen • Analogie – Klassennamen sind vergleichbar mit einem Vornamen – Package-Name entspräche dann dem Familiennamen • Package-Namen: Gleiche Einschränkungen wie Identifier – z.B. kein „-“ erlaubt – Konvention: Kleinschreibung (also „mathe“ statt „Mathe“) #17 Packages: Beispiel #18 Nested Namespaces • Namespaces können auch ineinander geschachtelt werden • Beispiel – – – – Punkt in „Farbe“ Punkt in „rgb“ in „Farbe“ Punkt in „version1“ in „rgb“ in „Farbe“ Punkt in „cmyk“ in „Farbe“ Namensraum „Farbe“ Punkt Namensraum „rgb“ Namensraum „cmyk“ Namensraum „version1“ Punkt Punkt Punkt #19 Nested Namespaces: Java Beispiel • Einzelne Bestandteile werden durch „.“ getrennt • Beginnt bei der höchsten Hierarchiestufe – Ähnlich wie im Dateisystem – Packages müssen immer „absolut“ angegeben werden (d.h. alle Namensteile müssen vorhanden sein) #20 Packages: Namenswahl • Sinnvoll: Weltweit eindeutige Namen – Üblich sind Internet-Domainnamen in umgekehrter Schreibweise – Damit man Klassen aus verschiedenen Quellen ohne Namenskonflikte nutzen kann • Beispiel: Klassen aus dem ITM – Domainname: itm.uni-luebeck.de – Package de.uni_luebeck.itm (Verwendung von „_“ statt „-“) – Sinnvoll: Anhängen des Projektnames (z.B. „programmieren.ws1213.uebung1.aufgabe2“) – Gesamt: de.uni_luebeck.itm.programmieren.ws1213.uebung1.aufgabe2; #21 Packages: Verwendung • Zwei Varianten zur Verwendung von Klassen aus anderen Packages • Angabe des voll-qualifizierten Namens (Klasse + Package) – package test; ... farbe.rgb.Punkt p = new farbe.rgb.Punkt(); • Importieren bestimmter Klassennamen – Um die Angabe des voll-qualifizierten zu ersparen (Lesbarkeit) – Schlüsselwort: import – import farbe.rgb.Punkt; ... Punkt p = new Punkt(); #22 Packages: Verwendung • Kann natürlich auch gemischt verwendet werden • Beispiel – package test; import farbe.rgb.Punkt; ... Punkt p1 = new Punkt(); farbe.cmyk.Punkt p2 = new farbe.cmyk.Punkt(); farbe.rgb.version1.Punkt p3 = new farbe.rgb.version1.Punkt(); • Es sind nach wie vor verschiedene Klassen – Punkt p1 = new farbe.cmyk.Punkt(); //Fehler!!! #23 Packages: Verwendung • Alternative Variante von import – Importieren ganzer Packages (z.B. import java.util.*;) – Alle Namen aus java.util können ohne Angabe des Packages verwendet werden – Gilt nicht für eventuelle Unterpackages von java.util • Wo/wann benutzt man Packages? – In allen größeren Java-Projekten – Intensiv in der Java-API: http://download.oracle.com/javase/7/docs/api/ (hier sollten sich Java-Programmierer gut auskennen) • In Java ist java.lang.*; implizit immer importiert – Daher kann man auch System.out.println(...); statt java.lang.System.out.println(...); schreiben #24 Klassen ohne Package • In welchem Package waren eigentlich unsere bisherigen Klassen? • Kein Package: sog. default Package – Quasi ein Package ohne Namen – Daher liegen diese auch im Wurzelverzeichnis des Projekts – Sollte man nur bei ganz kleinen Projekten nutzen #25