Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Prof. Dr. Max Mühlhäuser Dr. Guido Rößling

Ähnliche Präsentationen


Präsentation zum Thema: "Prof. Dr. Max Mühlhäuser Dr. Guido Rößling"—  Präsentation transkript:

1 Prof. Dr. Max Mühlhäuser Dr. Guido Rößling
Grundlagen der Informatik I Thema 12: Einführung in die objektorientierte Programmierung mit Java Prof. Dr. Max Mühlhäuser Dr. Guido Rößling

2 Inhaltsverzeichnis Objektorientierter Entwurf in aller Kürze; Klassen und Objekte in Java Interpreter, Compiler, virtuelle Maschinen; Java- Übersetzungs- und -Laufzeitumgebung Sichtbarkeit von Variablen in Java Packages Einführung in das Testen mit JUnit und Eclipse

3 Objektorientierte Programmierung
Eines der existierenden Programmierparadigmen Organisiert die zu modellierende Welt als eine Menge kooperierender Objekte (OO-Systeme) Dabei gilt: Ein Objekt ist zuständig für einen spezifischen wohldefinierten Teil der Berechnung Kapselt die Definition der dafür benötigten Daten und Operationen, welche diese Daten verarbeiten Nimmt Dienste anderer ihm bekannter Objekte in Anspruch Jedes Objekt ist eine Instanz (Exemplar) einer Klasse Klassen sind in einer Vererbungshierarchie organisiert Bilden Begriffshierarchien der zu modellierenden Welt nach

4 Objektorientierte Programmierung
Beispiel: Modellierung der Immobilienfirma Nobel&Teuer Objekte repräsentieren Häuser, Mitarbeiter und Kunden Für jedes Haus sollen Informationen über den betreuenden Mitarbeiter, den Besitzer… verwaltet werden Für jeden Kunden sind die zu verwaltenden Häuser, Name und Telefonnummer… zu verwalten Mitarbeiter haben Namen, Telefonnummer, verwaltete Häuser Verschiedene Typen von Häusern Ein- und Mehrfamilienhäuser Verschiedene Typen von Haus-Objekten werden in Erben der Klasse Haus spezifiziert

5 Objektorientierte Programmierung
Mitarbeiter Manager Wichtig Die Welt von Nobel&Teuer Schmidt Müller verwaltet Besitzer verwaltet Reich Besitzer

6 Objektorientierte Programmierung
Die Welt der Immobilienfirmen Ur-Objekt-Typ besitzt * Person Haus verwaltet 0..2 zuständig für 2..10 Mitarbeiter Kunde Einfamilien- haus Mehrfamilien- haus Manager Verwalter Begriffe & Kategorisierung

7 Objektorientierte Programmierung
Die Welt der Immobilienfirmen Instanziierung besitzt * Person Haus 0..2 zuständig für 2..10 Mitarbeiter Kunde Einfamilien- haus Mehrfamilien- haus Manager Verwalter verwaltet

8 Klassen Allgemein: Eine Klasse fasst Gemeinsamkeiten einer Gruppe von Objekten (Instanzen) zusammen mit denselben Eigenschaften (Attributen) mit demselben Verhalten (Operationen) Daten (Variablen) Methoden Konstruktionsvorschrift (Schablone) für Objekte; beschreibt deren Struktur und Dienste (Schnittstelle).

9 Klassen in Java Der Definitionsblock einer Klasse besteht aus
<KlassenDefinition> = class Klassen-Name [extends SuperKlassenName] <KlassenDefinitionBlock> <KlassenDefinitionsBlock> = { <MitgliedDefinition> ... <MitgliedDefinition> } <MietgliedDefinition> = <InstanzvariablenDeklaration> | <OperationsDefiniton> | <KonstruktorDefinition> Der Definitionsblock einer Klasse besteht aus einer Menge von Variablendeklarationen Attribute, Instanzvariablen, Felder einer Menge von Operationsdefinitionen Konstruktordefinitionen class Counter { ... }

10 Instanzvariablen (Felder)
Instanzvariablen modellieren Eigenschaften von Objekten z.B. aktueller Wert eines Zählers, aktueller Stand eines Kontos, … Haben einen Namen, einen Typ und einen Wert Der Name wird meistens klein geschrieben Der Wert ändert sich während der Ausführung Zur Erinnerung: int ist ein so genannter primitiver Typ in Java. Stellt die Klasse der natürlichen Zahlen zwischen   und dar class Counter { int currentVal; ... } Name Typ class Counter { int currentVal = 10; ... } (define (make-counter) (local ( (define currentVal 10) ... ) Wert

11 Konstruktor-Operationen
Ein Konstruktor definiert mit Hilfe der Parameter eine generische Initialisierungsvorschrift In Java sind Konstruktoren spezielle Operationen: haben den gleichen Namen wie die Klasse selbst haben keinen Rückgabewert Formaler Parameter des Konstruktors class Counter { int currentVal; ... Counter(int initVal) { currentVal = initVal; } Initialisierung der Felder mit den aktuellen Parametern eines Konstruktor-Aufrufs In welcher Position soll der Roboter ursprünglich sein, wie viele Piepser soll er ursprünglich in der Tasche haben ... (define (make-counter initVal) (local ( (define currentVal initVal) ... )

12 Die Konstruktor-Operationen
Eine Initialisierungsvorschrift wird einmal in einer Klasse definiert und mehrfach benutzt Erzeugung mehrerer Zählerexemplare des gleichen Typs mit unterschiedlich initialisierten Instanzvariablen ... Counter c1 = new Counter(3); Counter c2 = new Counter(6); Schlüsselwort für die Erzeugung von Objektinstanzen ... (define c1 (make-counter 3)) (define c2 (make-counter 6))

13 Die Java-Klasse Counter
class Counter { int currentVal; public Counter(int initVal) { currentVal = initVal; } /** * Effect: Increases the current value of counter by 1 */ public int inc() { currentVal = currentVal + 1; return currentVal; * Effect: Decreases the current value of counter by 1 public int dec() { currentVal = currentVal - 1; the current value of the counter public int getCurrentVal() { Sichtbar außerhalb der Definition von Counter JavaDoc Kommentar. Hier aus Platzmangel verkürzt.

14 Klassen in Scheme und Java
Klassen werden in Scheme durch Konstruktor-Funktionen (make-XXX) modelliert Spielen die Rolle der Java-Klassen und -Konstruktoren Geben Dispatcher-Funktionen zurück Der Dispatcher kombiniert und versteckt alle Dienstfunktionen In Java gibt es ein spezielles Konstrukt für Klassen Klassen sind nicht wirklich erstklassige Werte Klassen können mehrere Konstruktoren haben Dispatch-Mechanismus implizit in der Sprache Der Dispatcher ist Teil der Sprachsemantik und muss nicht programmiert werden (später mehr)

15 Klassenschnittstellen in Java
Service Managers (dispatchers) in Scheme sind Schnittstellenfunktionen, die Symbole auf Funktionen verschiedener Typen abbilden Die Schnittstelle einer Java-Klasse ergibt sich aus der Menge der Operationen, die als public deklariert sind Nicht-öffentliche Operationen sind von außen unsichtbar Wir gehen fürs erste davon aus, dass sie nur von Methoden der gleichen Klasse aufgerufen werden können Das stimmt nicht ganz; wir betrachten es später genauer Der Begriff einer Klassenschnittstelle als eine Funktion, die Symbole auf Operationen mit einem bestimmten Vertrag abbildet, bleibt jedoch gültig An address-book is an interface: 'add :: symbol number -> void 'search :: symbol -> number

16 Einkapselung (Information Hiding)
class Counter { int currentVal; ... } Felder und Operationen eines Objekts können versteckt werden. Auf sie kann nur innerhalb der Implementierung der (öffentlichen) Operationen der Klasse zugegriffen werden. public static void main(String[] args) { Counter c1 = new Counter(2); int current = c1.currentVal; current = c1.getCurrentVal(); // OK }

17 Geheimnisprinzip (Information Hiding)
Generelle Design-Idee: Details eines Programm-Moduls verstecken (z.B. Klasse oder Funktion) Mächtige Idee: reduziert die Komplexität von Anwendungen Keine Notwendigkeit, die versteckten Details des Moduls zu verstehen, um es zu verwenden. Reduziert die Kopplung zwischen Modulen Man kann die versteckte Implementierung ändern, ohne die Klienten unwirksam zu machen. Modul-Schnittstelle als Vertrag. Wir kennen diese Design-Idee schon Datenabstraktion: Repräsentation des Datentyps verstecken Make-Funktionen verstecken lokale Objektdefinitionen

18 Kapselung Idee: Kombination von Elementen, um größere Einheiten zu erzeugen und dabei die Details der Komposition zu verstecken. Kapselung ist ein Mechanismus, um Informationen zu verstecken. Der Begriff wird manchmal in einem gröberen Sinn verwendet. Als Synonym für information hiding Der Begriff wird manchmal in einem spezifischeren Sinn verwendet “Daten und Operationen zusammen”

19 Klassen als zweifache Abstraktion…
…beschreiben nur solche Felder und Dienste von realen Objekten, die relevant für die zu entwickelnde Software sind. In der Definition einer Klasse werden unwichtige Unterschiede zwischen allen möglichen Elementen (Objekten) einer Klasse außer Acht gelassen Beispiel: Unterschiede in den aktuellen Werten der Zähler

20 Klassen und Objekte Klassen in Java sind statische Beschreibungen ("auf Papier" bzw. "in der Datei")  Pläne (engl. blueprints) Objekte sind Laufzeitelemente eines Programms  Werte dynamisch (sind zur Programmausführungszeit im Hauptspeicher des Rechners) Es kann mehrere Objekte einer Klasse geben, jedes mit eigener Identität und eigenem Zustand Objekte sind über einen Namen ansprechbar Jedes Objekt gehört einer Klasse an und kennt seine Klasse Die Klasse kennt ihre Objekte in der Regel nicht

21 Charakteristika eines Objekts

22 Berechnungen durchführen
Jede Berechnung in einem OO-Programm geschieht als Folge des Aufrufs einer Operation auf einem vorher erzeugten Objekt Beachten Sie die „Punkt-Notation“ für den Aufruf von Methoden public class CounterConsumer { Counter c1 = new Counter(3); Counter c2 = new Counter(6); public void doSomethingWithCounters() { c1.inc(); c1.dec(); System.out.println(c1.getCurrentVal()); c2.inc(); c2.dec(); System.out.println(c2.getCurrentVal()); } (begin (inc c1) (dec c1)) (begin (inc c2) (dec c2)) (getCurrentVal c1) (getCurrentVal c2)

23 Berechnungen durchführen
Die Aufgabe wird in Dienstanweisungen zerlegt Formuliert als Nachrichten (Operationsaufruf) an Objekte Jede Nachricht enthält: Name des Empfängerobjektes: c1 im Beispiel Namen des Dienstes (der Operation), der (die) vom Empfänger ausgeführt werden soll inc(), dec(), ... Die Operation muss in der Schnittstelle des Empfängers enthalten sein Es wird nur eine Nachricht mit einer Dienstanweisung auf einmal geschickt Wenn mehrere Objekte vorhanden sind, können sie Botschaften aneinander senden Teilaufgaben an bekannte Objekte delegieren

24 Zur Erinnerung: Wie alles anfängt…
Die „ausgezeichnete“ Methode namens main wird aufgerufen, wenn ein Java-Programm ausgeführt wird… public class CounterTest { // ... public static void main(String[] args) { CounterConsumer cc = new CounterConsumer(); cc.doSomethingWithCounters(); } CounterTest.java Java- Compiler javac CounterTest.java java CounterTest Java- Bytecode-Interpreter

25 Inhaltsverzeichnis Objektorientierter Entwurf in aller Kürze; Klassen und Objekte in Java Interpreter, Compiler, virtuelle Maschinen; Java- Übersetzungs- und -Laufzeitumgebung Sichtbarkeit von Variablen in Java Packages Einführung in das Testen mit JUnit und Eclipse

26 Interpreter Ein Interpreter ist ein Programm, das ein Programm einer bestimmten Programmiersprache direkt ausführt. Arbeitsweise eines Interpreters (inpExpr ist der aktueller Ausdruck des auszuführenden Programms) Syntaktische Analyse von inpExpr Überführung von inpExpr in eine Befehlsfolge der Maschinensprache, oder der Sprache, in der das Interpreterprogramm selbst geschrieben ist (outExpr) Ausführung von outExpr Wiederholung der Schritte (1) bis (3) für die nächste Anweisung.

27 Definition eines Übersetzers
Ein Übersetzer (Compiler) ist ein Programm, das Programme aus einer Programmiersprache A in eine Programmiersprache B übersetzt Quellprogramm P1 Programm in der Sprache A Programm in der Sprache B Übersetzer Ausführung A  Quellsprache B  Zielsprache Zielprogramm P2 Semantische Korrektheit Jedem Quellprogramm P1 in A wird genau ein Zielprogramm P2 in B zugeordnet. Das dem Quellprogramm P1 zugeordnete Zielprogramm P2 muss die gleiche Bedeutung (Semantik) wie P1 besitzen.

28 Übersetzer (Compiler)
Konteradmiral Grace Murray Hopper (1906–1992) Nach eigener Aussage hat sie den Compiler aus Faulheit erfunden, und weil sie hoffte, dass "Programmierer wieder Mathematiker werden" könnten.

29 Übersetzungsphasen Quellprogramm wird in eine Folge von Worten zerlegt
Lexikalische Analyse Quellprogramm wird in eine Folge von Worten zerlegt Testet, ob das Quellprogramm den Syntaxregeln der Quellsprache entspricht. Strukturiert Worte in gültige Sätze. Syntaktische Analyse Testet, ob alle im Quellprogramm benutzten Namen deklariert wurden und ihrem Typ entsprechend verwendet werden, usw. Semantische Analyse Code-Generierung Zielprogramm wird erzeugt

30 Traditionelle Übersetzung
Quelltext in Sprache A Compiler für Sprache A und Prozessor X Compiler für Sprache A und Prozessor Y Compiler für Sprache A und Prozessor Z Ausführbares Programm (Binärcode) für Prozessor X Ausführbares Programm (Binärcode) für Prozessor Y Ausführbares Programm (Binärcode) für Prozessor Z Sun PC Apple Pascal Smalltalk Java Prolog C++ N Sprachen M Plattformen N*M Compiler

31 Vor- und Nachteile traditioneller Übersetzung
Vorteil: Optimale Ausnutzung der jeweiligen Prozessor-Eigenschaften Hohe Abarbeitungsgeschwindigkeit der übersetzten Programme Nachteil: Plattformabhängigkeit Ein Programm, das in einer höheren Programmiersprache geschrieben ist, kann theoretisch nach der Anwendung der entsprechenden Übersetzer auf jeder Maschine laufen... „The difference between theory and practice is that in theory, there is no difference between theory and practice, but in practice there is.“

32 Vor- und Nachteile traditioneller Übersetzung
Das übersetzte Programm läuft nur auf dem jeweiligen Prozessortyp Für jeden Prozessortyp und jedes Betriebssystem muss das Programm mit einem anderen Compiler neu übersetzt werden. Windows auf PC != Linux auf PC Plattformabhängigkeit: es gibt unterschiedliche Dialekte einer Sprache Bestimmte Eigenschaften der Maschine beeinträchtigen den Compiler-Entwurf Z.B. Größe der Register oder Speicherzellen beeinträchtigt die maximale Länge der Zahlen, die manipuliert werden können. Daher gibt es oft verschiedene Dialekte einer Programmiersprache

33 Virtuelle Maschinen (VM)
Eine virtuelle Maschine ist ein Programm, das die Arbeit eines Prozessors in Software simuliert Programme einer höheren Sprache werden in eine Assembler-ähnliche Zwischensprache übersetzt Der simulierte Hardware-Prozessor nutzt diese Zwischensprache und besitzt einige Software-Register Die Anweisungen der Zwischensprache nennt man auch Byte-Code Die Zwischensprache wird von der Virtuellen Maschine interpretiert Eine virtuelle Maschine versteckt die spezifischen Eigenschaften eines konkreten Prozessors  eine neue Abstraktionsschicht auf der Hardware-Ebene!

34 Vor- und Nachteile von Interpretern
Vorteil: es lassen sich relativ schnell lauffähige Programmversionen erstellen  Prototyping Schnelle Änderbarkeit: geänderte Anweisungen / Deklarationen des Quellprogramms sind sofort ausführbar Neuübersetzung nicht notwendig Nachteil: Längere Ausführungszeit Werden Anweisungen des Quellprogramms k-mal verwendet (z.B. bei Schleifen), werden sie k-mal analysiert und überführt Bei Zugriffen auf Variablen müssen die zugeordneten Adressen immer wieder bestimmt werden.

35 Virtuelle Maschinen (VM)
N Sprachen M Plattformen N + M Compiler Pascal Sun Smalltalk Virtuelle Maschine PC Java Prolog Apple C++ Eine VM verdeckt die speziellen Eigenschaften des jeweiligen Prozessortyps  Abstraktionsschicht!

36 Vor- und Nachteile der VM-Technologie
Vorteile: Übersetzte Programme einer Sprache laufen auf allen Prozessortypen, für die es einen Byte-Code Interpreter gibt Es wird nur ein Compiler benötigt  Die Sprache wird plattformunabhängig Natürlich braucht man eine VM pro Prozessortyp! Nachteil: Byte-Code Programme sind langsamer als Maschinenprogramme just-in-time-compiler (JIT): Übersetzen den Byte-Code in ein Objekt-Programm für einen speziellen Prozessortyp sobald es geladen wird, oder nach der ersten Ausführung

37 Java-Übersetzungs- und -Laufzeitumgebung
Übersetzungsumgebung Laufzeitumgebung Class Loader Bytecode Verifier Java Klassen- bibliothek Java Source (.java) Java Bytecode aus Dateisystem oder Netz Java VM Java Interpreter Just-in-time Compiler Java Compiler (javac) Java Laufzeitumgebung Java Bytecode (.class) Wichtige Festlegungen der JVM-Spezifikation Befehlsatz, Registerarchitektur Struktur einer class-Datei (auch Class File Format genannt) Stack, Garbage-collected heap, Speicher-Layout Bei der Implementierung der JVM für eine Hardware-/ Betriebssystemarchitektur müssen bestimmte Java-APIs auf die vorhandene System-Call-Schnittstelle abgebildet werden Datei- und Netzwerkzugriffe, GUI Betriebssystem Hardware

38 Struktur eines Java-Programms
Ein Java-Programm kann aus beliebig vielen Klassen bestehen, von denen mindestens eine die main-Operation besitzen muss (Hauptprogrammklasse). Aufgaben von main: Objekterzeugung  der Aufbau einer anfangs minimalen Welt Aufruf der ersten Operation Sollte in der Regel keinen weitergehenden Kontrollfluss des Java-Programms enthalten Der Kontrollfluss wird innerhalb der Objektoperationen realisiert Nicht vergessen! Berechnung als Kooperation von vielen Objekten, wobei jedes Objekt nur eine kleine Teilaufgabe erledigt! main wird mit Hilfe des Java-Interpreters gestartet und ausgeführt args ist eine Tabelle mit Zeichenketten und wird benutzt um dem Programm beim Start Parameter zu übergeben Eingabeparameter stehen zunächst nur als Zeichenketten zur Verfügung Möchte man eine Zahl übergeben, so muss die entsprechende Zeichenkette (programmintern) in eine Zahl (z.B. vom Typ int) konvertiert werden  mehr dazu später Statt args kann ein beliebiger Name benutzt werden, die Verwendung von args ist aber üblich

39 Java-Laufzeitumgebung
Java Interpreter: Programm zur Ausführung des Java-Bytecodes auf dem konkreten Rechner Just-In-Time-Compiler (JIT-Compiler) Eine Klasse kann (optimal) nach dem Laden direkt in Maschinen-Code der jeweiligen Maschine übersetzt werden Falls die vorliegende Java-Installation keinen JIT-Compiler besitzt, wird der Bytecode vom Java-Interpreter direkt ausgeführt Runtime-System: Stellt einem Java-Programm wichtige Ressourcen zur Verfügung Bytecode Verifier: überprüft, ob die geladenen Bytecodes der JVM-Spezifikation entsprechen Klassen können über das Netz oder aus dem lokalen Dateisystem zur Laufzeit einer Java-Anwendung in das Laufzeitsystem nachgeladen werden Ein Teil der Sicherheitsmaßnahmen wird durch den Bytecode Verifier realisiert

40 Java-Übersetzung (Wiederholung)
Java-Compiler Eingabe: Java-Quelltextdatei, Datei.java, die eine oder mehrere Klassendefinitionen enthält Eine derartige Datei nennt man eine Übersetzungseinheit Ausgabe: pro Klasse Bsp wird genau eine Datei Bsp.class erzeugt, die das Bytecode-Format der Klasse enthält Bsp1.class class Bsp1 {...} class Bsp2 {...} class Datei {...} Datei.java Bsp2.class Java Compiler Datei.class

41 Inhaltsverzeichnis Objektorientierter Entwurf in aller Kürze; Klassen und Objekte in Java Interpreter, Compiler, virtuelle Maschinen; Java- Übersetzungs- und –Laufzeitumgebung Sichtbarkeit von Variablen in Java Packages Einführung in das Testen mit JUnit und Eclipse

42 Sichtbarkeit von Variablen in Java
Der gleiche Variablenname kann mehrfach verwendet werden, z.B. Instanzvariable, Parameter, lokale Variable einer Methode oder eines Blocks. Wie in Scheme, lexical scoping: innere Deklarationen haben immer Vorrang vor äußeren Deklarationen. Auf äußere Deklarationen kann man nicht mehr direkt zugreifen Mit this.<attribute-name> kann man auf Instanzvariablen zugreifen Lokale Variablen und Parameter können nicht re-deklariert werden Redeklaration beeinflusst die Existenz der äußeren Variablen nicht Fehlende Sichtbarkeit bedeutet kein fehlendes Vorhandensein! Außerhalb des Deklarationsblocks ist die äußere Variable wieder sichtbar Unsichtbarkeit bedeutet nicht Nicht-Existenz.

43 Sichtbarkeit von Variablen in Java Klassen
Lexical scoping a la Java class Example { int i; char c; void g(int n) { int i, j; for (char c... ) { int k; … i … k … c … n … this.i … } … c … Klassen-Scope Scope von Methode g Scope der for-Schleife

44 Inhaltsverzeichnis Objektorientierter Entwurf in aller Kürze; Klassen und Objekte in Java Interpreter, Compiler, virtuelle Maschinen; Java- Übersetzungs- und –Laufzeitumgebung Sichtbarkeit von Variablen in Java Packages Einführung in das Testen mit JUnit und Eclipse

45 Packages Packages bündeln Klassen, die im Hinblick auf Zuständigkeit zusammen gehören. Hilft Namenskonflikte zu vermeiden. Klassennamen müssen eindeutig sein (aber nur in einem Package) Mehrere Klassen können den gleichen (nicht public) Namen haben, z.B. List Versteckt Klassen, die nur interne Zwecke haben und die nach außen nicht sichtbar sein sollen.

46 Package Hierarchien Packages sind hierarchisch organisiert
 Ein Package kann andere Packages enthalten, die wieder mehr Packages enthalten, usw. Punkt-Notation für Package Namen package.subpackage.subsubpackage.Class Der Kopf einer Java Datei gibt an, mit welchem Package die folgenden Klassen verbunden sind.

47 Namenskonventionen für Packages
Der Package Name spiegelt den Internet Domain Namen des Herstellers in umgekehrter Reihenfolge Schräg- und Bindestriche sind nicht erlaubt: SUN URL: sun.com SUN class: com.sun.p1.p2.Class TUD URL: informatik.tu-darmstadt.de TUD class: de.tu_darmstadt.informatik.p1.Class Die Konvention erlaubt die Definition weltweit eindeutiger Klassennamen.

48 Deklaration von Packages
Der gleiche Package Name kann in mehreren Dateien verwendet werden Ein Package kann über mehrere Dateien verteilt sein  schnellere (Re-)Compilierung  Unterstützt die Arbeitsteilung in größeren Projekten Der volle Name einer Klasse enthält immer den Package Namen (packagename.ClassName) Shortcut Notation mit nur dem Klassennamen ist nur innerhalb des selben Packages möglich oder wenn das Package bzw. die Klasse importiert wurde.

49 Struktur einer Java Datei
<Source-File> ::= <Package-Declaration> <Import-Declarations> <Type-Definitions> <Package-Declaration> ::= package <Package-name> ; | ε <Package-Name> ::= <Identifier> {. <Package-Name>} Nur Kommentare oder leere Zeilen dürfen vor der Package Deklaration stehen. Nur ein Package Name pro Datei Ohne eine Package-Deklaration werden die enthaltenen Klassen einem anonymen Standard Package hinzugefügt.

50 import static <Package-Name>.<Class-Name>.<Methode>;
Package Import <Import-Declaration> ::= import <Package-Name> (<Class-Name> | *) ; Eine Klassendefinition nach einer import-Anweisung kann auf die importierte Klasse zugreifen, ohne den vollständigen Namen zu nennen. Wenn "*" (wild card) benutzt wird, kann man auf alle Klassen des Packages zugreifen. Falls nur Klassenmethoden (static) importiert werden sollen, langt auch folgende Notation: import static <Package-Name>.<Class-Name>.<Methode>;

51 Verwendung von Packages
Verwendung der vollständigen Kennzeichnung (full qualification) java.util.Random numberGenerator = new java.util.Random(); Verwendung von import import java.util.Random; ... Random numberGenerator = new Random();

52 Package Import Das Importieren von Klassen mit dem selben Namen erzeugt einen Namenskonflikt import java.awt.*; // hat Klasse List import java.util.*; // hat Klasse List ... java.util.List list; // verwende den // Package-Namen, um // eine auszuwaehlen Zwei Packages werden automatisch importiert Das aktuelle Package Das vordefinierte Package java.lang, das grundlegende Klassen wie Object, String, usw. enthält.

53 Package Import Die Java API enthält eine große Zahl vordefinierter Packages (alle Teil vom JDK), unter anderem java.applet Applet-Unterstützung java.io Input/Output, Dateien java.net Netzwerk-Unterstützung java.util Utility Typen, z.B. Containertypen java.util.zip Unterstützung für .zip Archive

54 Namensgebung für Packages
Package-Namen und Verzeichnisstrukturen Die Stellen der Dateien, die ein Package definieren, spiegelt die hierarchische Struktur des Packages wieder. Punkte müssen ersetzt werden durch: UNIX  Slash " / " Windows  Backslash " \ " Beispiel: Name des Packages: kilian.hobby.raytracer zugehörige UNIX Verzeichnis-Struktur: kilian/hobby/raytracer

55 Packages einbinden Packages und "CLASSPATH"
Ein Package Name wird als relativer Pfad verstanden Die Umgebungsvariable CLASSPATH enthält alle Verzeichnisse, die nach Klassen und Packages durchsucht werden. Darüber hinaus kann ein CLASSPATH auch auf ZIP und JAR-Archive verweisen, die Klassen enthalten UNIX Beispiel CLASSPATH=.:/home/joe/classes:/usr/classes.zip Aktuelles Verzeichnis Weitere Verzeichnisse

56 Packages einbinden Packages und "CLASSPATH"
Die Verzeichnisse aus CLASSPATH sind die Startpunkte für die relativen Pfade zu den Packages Die Suchreihenfolge ist von links nach rechts Es ist möglich, dass ein Package Name mehrere Verzeichnisse bezeichnet. Keine gute Idee, da die Auswahl der Packages dann von der Reihenfolge des Auftretens dieser Verzeichnisse im CLASSPATH abhängt.

57 Inhaltsverzeichnis Objektorientierter Entwurf in aller Kürze; Klassen und Objekte in Java Interpreter, Compiler, virtuelle Maschinen; Java- Übersetzungs- und –Laufzeitumgebung Sichtbarkeit von Variablen in Java Packages Einführung in das Testen mit JUnit und Eclipse

58 Testen mit JUnit und Eclipse
Test-first programming  Unsere Entwurfsrezepte verlangen, dass wir Tests schreiben, bevor wir mit dem Programmieren anfangen JUnit ist ein Programm (framework), das das Schreiben und Ausführen von Tests teilweise automatisiert JUnit ist bereits in Eclipse integriert Der Ärmste... wir hätten ihm bei der Einstellung sagen sollen, dass er zuerst testen und dann programmieren soll.

59 Motivation für JUnit Wir verwenden ein Framework, hier JUnit
Analog zu unseren Testfällen in Scheme wollen wir auch in Java unsere Programme testen können Wir schreiben dazu ein Testprogramm, welches die Operationen mit Beispiel-Daten benutzt und die Ergebnisse auswertet Testprogramm wird zur Entwicklungszeit zum eigentlichen Programm parallel weiterentwickelt und ausgeführt Immer dann, wenn wir wissen möchten, ob gewisse Testfälle noch laufen Wir verwenden ein Framework, hier JUnit - für automatisierte Unit-Tests

60 Annotationen Bevor wir uns JUnit widmen, möchten wir einen Blick auf Annotationen werfen Die neueste Fassung von JUnit nutzt Annotationen Annotationen liefern Metadaten über den Programmcode Java 1.5+ definiert 7 Annotationen Möglichkeit zur Ergänzung durch nutzerdefinierte Annotationen 3 „echte“ Annotationen 4 Meta-Annotationen Annotationen werden mit im Programm-Code markiert Zum Annotationen verweisen auf eines der folgenden Elemente Element = Code-Zeile, Methode, … Ich habe “Annotations” mal mit “Anmerkungen” übersetzt, vermutlich wäre es auch möglich den Begriff “Annotations” einfach zu verwenden.

61 Echte Annotationen @Override @Deprecated @SuppressWarnings
Zeigt an, wenn eine Methode aus der Basisklasse durch eine andere Methode überschrieben wird. Kann verwendet werden, um auf Tipfehler und Fehler in den Signaturen von Methoden zu testen. @Deprecated Verursacht eine Compiler-Warnung, wenn das folgende Element verwendet wird @SuppressWarnings Unterdrückt Compiler-Warnungen für das folgende Element Wie übersetzt man „Typos“ am besten? Ich hätte den Begriff beibehalten…

62 Meta-Annotationen @Target(args) @Retention(args) @Documented
Wo können Annotationen verwendet werden? Zusätzliche Argumente: CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE @Retention(args) Wie lange sollen Annotationen behalten werden? SOURCE = Vom Compiler verworfen CLASS = Verfügbar in Klassen-Datei, zur Laufzeit verworfen RUNTIME = Von Virtual Machine für die Laufzeit-Nutzung beibehalten @Documented Schließt Annotation in JavaDoc ein @Inherited Erlaubt es Unterklassen, Annotation zu erben Wie lange sollen Anmerkungen behalten werden? --- Alternativ: Wie lange sollen Anmerkungen verfügbar sein? Schließt Anmerkung in JavaDoc ein -> Vllt nicht die optimalste Übersetzung

63 Annotationen: Beispiel
Die können genutzt werden, um neue Annotationen zu definieren Neue Annotationen werden wie Interfaces definiert mit dem Beispiel: @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) UseCase { public int id(); public String description() default "no description"; }

64 Annotationen: Beispiel
Wie können vorausgegangene Annotationen genutzt werden, um “Use Cases” zu generieren? public class PasswordUtils { @UseCase(id = 47, description = "Password must have one number") public boolean validatePassword() { // ... } @UseCase(id = 48) public String encryptPassword() {

65 Annotationen und JUnit
Die aktuelle Version von JUnit basiert auf Annotationen Testfälle werden mit der markiert Frühere Versionen brauchten spezielle Konventionen bei den Namen der Test-Klassen In JUnit 4 ist das nicht mehr notwendig JUnit-Demo, aber im Vorfeld noch ein paar Worte zum Testen

66 Teststadien Kunden- wünsche Abnahmetest Anforderungen Systemtest
Entwicklungsphasen mit zugehörigen Tests Kunden- wünsche Abnahmetest Anforderungen Systemtest Entwurf Integrationstest Code Unittests X Y A wird vor B ausgeführt A B X findet Fehler in Y

67 Teststadien Sich anbietende Teststrategien
Unit Test: Test von Codekomponenten, z.B. Code einer Methode, einer Klasse  strukturelles Testen Integrationstest: Test des Zusammenwirkens mehrerer Codekomponenten  strukturelles Testen Systemtest: Test des gesamten Systems gegen die Anforderungen  funktionales Testen Abnahmetest: Test des gesamten Systems mit echten Daten des Kunden

68 Entwicklungsprozess & Testen
Ein ungewollter Teufelskreis … Zeitdruck Mehr Zeitdruck Mehr Fehler Weniger Tests

69 Entwicklungsprozess & Testen: „Agile“ Prozessmethoden
Entwicklung und Testen als verschränkter Prozess Testentwicklung vor Produktentwicklung! Werkzeugunterstützung benötigt... Ein wenig programmieren Ein wenig testen

70 Motivation Testen: Zusammenfassung
In der Praxis unverzichtbar Je früher Fehler gefunden werden, desto besser (kostengünstiger) Entwicklung ist deshalb typischerweise ein iterativer, rückgekoppelter Prozess Qualität nicht nur überprüfen, sondern, wenn möglich, „hineinkonstruieren“ Systematische Verfahren  Software Engineering

71 Testen mit JUnit 4.4 Auf den nächsten Folien testen wir einen Taschenrechner Die Implementierung ist relativ einfach Der Taschenrechner arbeitet nur auf int-Werten Er ist sehr einfach und ineffizient Außerdem hat er ein paar Bugs Wir werden sehen, ob JUnit uns bei den Bugs helfen kann!

72 Die Calculator Klasse (Teil I)
package calc; public class Calculator { private static int result; // Statische Variable fuer Speicherung des Ergebnisses public void add(int n) { result = result + n; } public void substract(int n) { result = result - 1; // Bug: sollte lauten result = result - n public void multiply(int n) { // noch nicht implementiert... public void divide(int n) { result = result / n; public void square(int n) { result = n * n;

73 Die Calculator Klasse (Teil II)
public void squareRoot(int n) { // implementieren wir spaeter… for (; ;) ; // Bug: unendliche Schleife } public void clear() { // Ergebnis loeschen auf 0 result = 0; public void switchOn() { // Display anschalten, “Hallo” anzeigen, piepen... // Was so Geraete heute eben alles tun koennen! public void switchOff() { // Anzeigen “Tschuess", piepen, Display ausschalten public int getResult() { return result;

74 Wie testen wir den Calculator?
Wir wollen jede Operation separat testen Add Substract Divide Multiply Square Root – erst einmal aufgeschoben (Endlosschleife!) Wir schreiben eine Testmethode pro Test Die Methoden kommen in eine Klasse CalculatorTest Tests werden annotiert vor dem „public” Wir müssen den Rechner vor jedem Test initialisieren Müssen “clear()” aufrufen, damit der Wert 0 ist Sonst kriegen wir ggf. Folgefehler!

75 Die CalculatorTest Klasse (Teil I)
Packagename ist hier beliebig package junit4demo; import calc.Calculator; import junit.framework.JUnit4TestAdapter; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; /** * Basic test annotation * as well as assert keyword and assertEqual methods */ public class CalculatorTest { private static Calculator calculator = new Calculator(); // this is our calculator! // Used for backward compatibility (IDEs, Ant and JUnit 3 text runner) public static junit.framework.Test suite() { return new JUnit4TestAdapter(CalculatorTest.class); } Das ist unser Taschenrechner Einige Importe für JUnit Wir nutzen nur die statische Methode „assertEquals“ Nötig für ältere Umgebungen

76 Die CalculatorTest Klasse (Teil II)
@Before // must be public not protected like the setup public void clearCalculator() { calculator.clear(); // reset value to 0 } //================================== // Test public void add() { calculator.add(1); assertEquals(calculator.getResult(), 2); @Before: vor jedem Test ausgeführt; Calculator ist damit 0 vor jedem Test @Test: Annotation für eine auszuführende Testmethode. Hier wird überprüft, ob 1+1 = 2 gilt.

77 Die CalculatorTest Klasse (Teil III)
public void subtract() { calculator.add(10); calculator.substract(2); assertEquals(calculator.getResult(), 8); } public void divide() { calculator.add(8); calculator.divide(2); assertEquals(calculator.getResult(), 5); – deactivated, as it will cause an error (division by 0); more in T16 public void divideByZero() { calculator.divide(0); Hier wird getestet auf 10-2 = 8 (Fehlschlag durch Bug) Soll testen auf 8/2=5 (Fehlschlag, da inkorrekt!) Division durch 0 muss einen Fehler liefern, sonst schlägt der Test fehl

78 Die CalculatorTest Klasse (Teil IV)
hat einen String-Parameter, der eine nicht testbereit") public void multiply() { calculator.add(10); calculator.multiply(10); assertEquals(calculator.getResult(), 100); } Ignoriere den Test von multiply, da der Code noch nicht fertig ist. Kopieren Sie die Klassen von der Homepage Stellen Sie sicher, dass JUnit 4.4 installiert ist und als “External JAR” zum Projekt zugefügt wurde Selektieren Sie die Klasse CalculatorTest und wählen Sie Run As  JUnit Test Die Ausgabe sehen Sie auf den nächsten Folien

79 JUnit in Eclipse: Assert-Methoden etc.

80 JUnit in Eclipse: Als Testfall starten

81 Fehlerausgabe von JUnit
Kurzfassung der Ergebnisse Logbuch der Tests 10-2=8 schlug fehl

82 Fortgeschrittene Tests
Wir haben den „divideByZero“-Test nicht genutzt Wenn wir dies tun, kommt eine (erwartete) Fehlermeldung! Wie man auf das Vorhandensein erwarteter Fehler testet, folgt zusammen mit der Fehlerbehandlung in T16. Wir haben die squareRoot Methode nicht getestet Wäre auch keine gute Idee durch die Endlosschleife… Wir brauchen eine einmalige allgemeine Initialisierung Lege Instanz des Calculator an und schalte ihn an vor den Tests Ausschalten, wenn alle Tests fertig sind und freigeben (=null) Der nachfolgende Code illustriert das Vorgehen Gegenüber der Webseite leicht vereinfacht

83 Fortgeschrittene Tests: Set-Up
package junit4demo; import calc.Calculator; import junit.framework.JUnit4TestAdapter; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * This test uses advanced fixture and timeout */ public class AdvancedTest { private static Calculator calculator; // Used for backward compatibility (IDEs, Ant and JUnit 3 text runner) public static junit.framework.Test suite() { return new JUnit4TestAdapter(AdvancedTest.class); } Externe Klasse sichtbar machen (-> T15) Einmal ausführen, wenn alle Tests fertig Ausführen vor jedem Test Einmal ausführen vor dem ersten Test

84 Test-Initialisierung und Beendigung
@BeforeClass // must be public and static public static void switchOnCalculator() { System.out.println("\tSwitch on calculator"); calculator = new Calculator(); calculator.switchOn(); public static void switchOffCalculator() { System.out.println("\tSwitch off calculator"); calculator.switchOff(); calculator = null; Einmal ausführen bevor Testen beginnt: Rechner anlegen und anschalten Einmal ausführen, wenn alle Tests fertig sind: ausschalten und Rechner freigeben

85 Testen mit Timeout //================================== //= Test = 1000) public void squareRoot() { calculator.squareRoot(2); public void square2() { calculator.square(2); assertEquals(4, calculator.getResult()); // two more tests skipped Test wird fehlschlagen, wenn nicht in 1000ms fertig (Endlosschleifen!) Testen auf die Quadrate von 4 & 5

86 Testausgabe mit Timeout
Testen von squareRoot schlug fehl wegen Timeout

87 Mehr zu JUnit... JUnit kann (viel) mehr als hier gezeigt
Das ist aber jenseits des Stoffs der Vorlesung! Ein Blick in die Doku lohnt sich Mitgeliefertes JavaDoc für JUnit Gute Referenz (und Basis dieser Folien): Antonio Goncalves, Get Acquainted with the New Advanced Features of JUnit 4


Herunterladen ppt "Prof. Dr. Max Mühlhäuser Dr. Guido Rößling"

Ähnliche Präsentationen


Google-Anzeigen