Studienmaterial Programmieren in Java JAV101 Prof. Dr. Cornelia Heinisch E B O R P LESE 1 Programmieren in Java Einleitung und Lernziele 3 1 Objektorientierung und erstes Programmieren in Java 1.1 Schritt für Schritt zum ersten Java-Programm 1.1.1 Werkzeuge für die Programmierung in Java 1.1.2 Das Programm „Hello, World!“ 1.2 Das objektorientierte Konzept 1.2.1 Die Denkweise in Objekten und Klassen 1.2.2 Objektorientiertes versus funktionsorientiertes Konzept 1.3 Objektorientierung in Java 1.3.1 Klassen und Objekte 1.3.2 Vererbung 1.3.3 Schnittstellen 1.3.4 Pakete 1.3.5 Klassenbibliothek 5 5 5 9 11 11 15 18 18 22 25 28 29 2 Die Programmiersprache Java 2.1 Regeln und Konventionen 2.1.1 Lexikalische Einheiten 2.1.2 Style-Guide-Konventionen 2.1.3 Kommentare 2.2 Datentypen und Variable 2.2.1 Klassifikation der Datentypen in Java 2.2.2 Variable einfacher Typen und Variable von Referenztypen 2.2.3 Array-Typen 2.3 Ausdrücke, Operatoren und Kontrollstrukturen 2.3.1 Ausdruck, Operator, Operand, Anweisung und Kontrollstruktur 2.3.2 Beliebte Fehler bei Ausdrücken und Operatoren 2.3.3 Durchlaufen von Arrays mit der for-each-Schleife 2.4 Blöcke und Methoden 2.4.1 Formale und aktuelle Parameter 2.4.2 Polymorphie von Methoden 2.4.3 Überladen von Methoden 2.5 Klassen und Objekte 2.5.1 Klassenvariable und -methoden 2.5.2 Die this-Referenz 2.5.3 Konstruktoren 2.6 Vererbung und Polymorphie 2.6.1 Aufruf von Konstruktoren der Vaterklasse 2.6.2 Erweitern, Überschreiben und Polymorphie 2.6.3 Die Klasse Object 2.7 Ausnahmebehandlung 2.8 Generizität 33 33 33 34 35 37 37 39 41 44 44 45 46 47 47 49 49 50 50 53 55 57 57 59 63 66 70 Inhaltsverzeichnis å JAV101 2 Copyright AKAD. Die PrivatHochschulen GmbH Ein Unternehmen der Cornelsen-Gruppe. Telefon: (07 11) 8 14 95 - 0 Internet: http://www.akad.de Alle Rechte vorbehalten. Jede Verwertung außerhalb der Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung der AKAD unzulässig und strafbar. Das gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Bearbeitung in elektronischen Systemen. Inhaltsverzeichnis å JAV101 3 Grundlegende Java-Bibliotheken 3.1 Collections 3.2 Ein-/Ausgabe und Streams 73 73 77 Zusammenfassung Antworten zu den Kontrollfragen Literaturverzeichnis Stichwortverzeichnis 82 83 96 97 3 Einleitung und Lernziele Die Nutzung von Software ist schon lange nicht mehr auf Spezialisten oder einzelne Industriezweige beschränkt. Software durchdringt das tägliche Leben eines jeden Einzelnen. Man könnte sich fragen, ob man überhaupt noch eine Aufgabe des täglichen Lebens erledigen kann, ohne dabei Software zu verwenden. Software im Einsatz von morgens bis abends: Da wäre die zeitgesteuerte Warmwasseraufbereitung für die Dusche am Morgen, oder der Kaffee aus der „Pad-Maschine“, Musik hören, Fernsehen, Telefonieren, Einkaufen und die elektronischen Bezahlmöglichkeiten, Wäsche waschen, Auto oder Zug fahren, etc. Selbst wer es bis heute geschafft hat, weder Handy noch Computer zu besitzen, kann sich der Nutzung von Software nicht entziehen. Mit diesem heterogenen Einsatzfeld der Software und der oftmals enormen Komplexität einzelner Systeme ist klar, dass Software entwickeln nicht „nur Programmieren“ bedeutet. Beim Gesamtaufwand einer Software-Entwicklung nimmt die Programmierung nur noch einen kleinen Anteil ein. Bei der Software-Entwicklung geht es im ersten Schritt darum, zu verstehen, welche Aufgabe durch Software unterstützt, verbessert oder überhaupt erst ermöglicht werden soll. Sogenannte Anforderungen werden aufgestellt und sorgfältig analysiert. Die Analyseergebnisse werden in Diagrammen (Modellen) und textuellen Beschreibungen festgehalten. Im nächsten Schritt wird ein Entwurf der zu erstellenden Software auf Basis der Analyseergebnisse angefertigt. Die Entwurfsergebnisse werden wiederum in Diagrammen und textuellen Beschreibungen dokumentiert und erst dann wird auf Basis der Entwurfsergebnisse die Programmierung der Software durchgeführt. Software entwickeln ist mehr als „nur Programmieren“. Für die Programmierung kommen eine oder – bei größeren Systemen – auch mehrere Programmiersprachen zum Einsatz. Die Programmiersprache, die Sie in diesem Studienbrief kennenlernen, ist Java. Java ist neben den Programmiersprachen C, C++ und C# eine der heute am häufigsten eingesetzten Programmiersprachen. Die Programmiersprachen C++, C# und Java sind die dominierenden Repräsentanten der objektorientierten Programmiersprachen. Eine objektorientierte Programmiersprache eignet sich optimal für die Implementierung einer Software, wenn bereits die vorgelagerten Analyse- und Entwurfstätigkeiten nach dem objektorientiert:Konzeptobjektorientierten Konzept erfolgten. Man spricht dann auch von der objektorientierten Modellierung (OOM) und meint damit die Tätigkeiten und die Ergebnisdokumentation in der Analyse- und in der Entwurfsphase. Von objektorientierter Programmierung (OOP) spricht man, wenn die Implementierung der Software in einer objektorientierten Programmiersprache, wie zum Beispiel Java, erfolgt. Objektorientiertes Konzept, Objektorientierte Modellierung (OOM), Objektorientierte Programmierung (OOP) Mit dem objektorientierten Konzept ist unzertrennlich die Unified Modelling Language (UML) (OESTEREICH, 2009) verbunden. Die Unified Modelling Language standardisiert alle Diagramme, die im Rahmen einer objektorientierten Modellierung erstellt werden. Ein Großteil der Ergebnisdokumentation in der Analyse- und Entwurfsphase bei einer objektorientierten Modellierung sind UML-Diagramme. Ein Programmierer hat nun die Aufgabe, die UML-Diagramme aus der Entwurfsphase – unter Einbezug der ergänzenden textuellen Dokumentation – in eine objektorientierte Programmiersprache zu übersetzen. Als Java-Programmierer müssen Sie also nicht nur lernen, in der Programmiersprache Java „zu sprechen“, sondern Sie müssen auch die UML „lesen“ und objektorientiert „denken“ können. Unified Modelling Language (UML) Einleitung/Lernziele å JAV101 4 Entsprechend werden Sie in diesem Studienbrief folgende Fertigkeiten erwerben: P in der Programmiersprache Java „zu sprechen“, P essenzielle Notationselemente und Diagramme der UML „zu lesen“ und diese in die Programmiersprache Java zu übersetzen, P objektorientiert „zu denken“, um die objektorientierten Konzepte in der Programmiersprache Java abzubilden. Der Studienbrief ist in drei Kapitel untergliedert: P Das erste Kapitel „Objektorientierung und erstes Programmieren in Java“ vermittelt einen leichten und schnellen Einstieg in die Objektorientierung und in die Programmierung mit Java. Zu Beginn geht es darum, die „Werkzeuge“, die Sie benötigen, um Java-Programme zu erstellen und auszuführen, kennenzulernen. Im zweiten Schritt lernen Sie das objektorientierte Konzept und die UML-Notationselemente für Klasse und Objekt kennen. Sie beginnen objektorientiert zu „denken“ und lernen, wie man diese Gedanken in UML „notieren“ kann. Abschließend wird Ihnen in diesem Kapitel am Beispiel einer Bibliotheksverwaltung gezeigt, wie die objektorientierten Konzepte in der Programmiersprache Java umgesetzt sind. P Im zweiten Kapitel „Die Programmiersprache Java“ lernen Sie Java genauer kennen und verfeinern Ihre Programmierfähigkeiten. Das Beispiel der Bibliotheksverwaltung wird hierzu Kapitel für Kapitel erweitert und auch immer wieder „umgebaut“. Zu Beginn lernen Sie einige Regeln und Richtlinien für das korrekte Erstellen von Java-Programmen. Es geht weiter mit „Datentypen und Variablen“, „Ausdrücken, Operatoren und Kontrollstrukturen“, „Klassen und Objekten“, „Vererbung und Polymorphie“, „Ausnahmebehandlung“ und „Generizität“. Nach Abschluss dieses Kapitels haben Sie alle Sprachkonstrukte von Java kennen gelernt. P Im dritten Kapitel „Grundlegende Java-Bibliotheken“ lernen Sie Klassenbibliotheken kennen, die in der Programmiersprache Java geschrieben sind. Diese Klassenbibliotheken sind Bestandteil der Entwicklungsumgebung und werden mit der Programmiersprache Java ausgeliefert. Ein erfahrener Java-Programmierer unterscheidet sich von einem Einsteiger durch eine umfassende Kenntnis von Klassenbibliotheken. Sollten Sie später als Java-Programmierer arbeiten, so werden Sie kontinuierlich neue Klassenbibliotheken kennenlernen bzw. selbst schreiben. Konkret lernen Sie die Klassenbibliothek der Collections und die Klassenbibliothek für die Ein- und Ausgabe kennen. Dieser Studienbrief orientiert sich an dem Buch „Java als erste Programmiersprache“ (HEINISCH, et al., 2010). Er bietet ergänzende Informationen zu den Kapiteln 1 – 14, sowie den Kapiteln 16 – 18 des Lehrbuches. Den optimalen Lernerfolg erzielen Sie, wenn Sie ergänzend zum Studienbrief das entsprechende Kapitel im Buch durcharbeiten. Über die Autorin dieses Studienbriefs Prof. Dr. CORNELIA HEINISCH studierte Softwaretechnik an der Hochschule Esslingen und promovierte an der Universität Tübingen. Seit mehr als 10 Jahren begleitet sie in der Automobilindustrie große SW-Projekte als Beraterin. In ihren Dozententätigkeiten an mehreren Hochschulen lag und liegt ihr Schwerpunkt auf den Themengebieten Software-Engineering und objektorientierte Programmierung. Seit Mitte 2012 hat sie eine Professur für Wirtschafts-Informatik an der FOM-Hochschule für Ökonomie und Management. Als Autorin des Lehrbuches „Java als erste Programmiersprache“ ist Frau Prof. Dr. HEINISCH mit der objektorientierten Programmierung in Java bestens vertraut. Einleitung/Lernziele å JAV101 5 1 Objektorientierung und erstes Programmieren in Java 1.1 Schritt für Schritt zum ersten Java-Programm Um Java-Programme schreiben und ausführen zu können, benötigen Sie einige „Werkzeuge“ auf ihrem Rechner. In Kapitel 1.1.1 werden Sie zuerst lernen, was Sie benötigen und dann wird Ihnen Schritt für Schritt gezeigt, wie Sie die benötigten Werkzeuge auf Ihrem Rechner installieren. In Kapitel 1.1.2 schreiben Sie bereits ihr erstes sehr einfaches Java-Programm und bringen es zur Ausführung. 1.1.1 Werkzeuge für die Programmierung in Java Damit Sie Java-Programme schreiben und ausführen können, benötigen Sie Folgendes: P einen Editor, um ein Java-Programm einzutippen – bzw. den Java-Quellcode zu erstellen; P einen Java-Compiler, um den im Editor eingetippten Java-Quellcode in Java-Bytecode zu übersetzen; P die Java-Klassenbibliothek, welche ausprogrammierte Funktionalitäten – zur Verwendung in den eigenen Java-Programmen – zur Verfügung stellt; P einen Java-Interpreter, um den Java-Bytecode auf der jeweiligen Rechner-Plattform auszuführen. Hierzu übersetzt der Java-Interpreter den Java-Bytecode in Maschinencode und bringt diesen direkt zur Ausführung. Als Rechner-Plattform wird hier die Kombination von Betriebssystem und zugehöriger Rechner-Hardware verstanden. Definition Rechner-Plattform Java-Compiler, Java-Interpreter und die Java-Klassenbibliothek werden folgendermaßen unter dem Begriff der Java-Plattform zusammengefasst: Zu einer Java-Plattform gehören, neben der Programmiersprache Java, Werkzeuge wie Definition Java-Plattform P der Java-Compiler (javac), P die Java Virtuelle Maschine (JVM) – in anderen Worten der Java-BytecodeInterpreter (java) – für eine Rechner-Plattform P und eine umfassende Klassenbibliothek. Kapitel 1 å JAV101 6 Die Java-Plattform wird von Oracle – ehemals Sun Microsystems – in verschiedenen Ausführungen zur Verfügung gestellt. Es werden beispielsweise folgende Ausführungen unterschieden: P Standard Edition (Java SE) P Enterprise Edition (Java EE) P Micro Edition (Java ME) Die Ausführungen unterscheiden sich im Wesentlichen in Art und Umfang der Klassenbibliothek und durch die zur Verfügung gestellten Werkzeuge. Die unterschiedlichen Ausführungen sind für den Einsatz von Java-Programmen auf unterschiedlichen Endgeräten gedacht. Für diesen Studienbrief benötigen Sie eine Java-Plattform in der Standard Edition. In den folgenden beiden Unterkapiteln werden zwei Möglichkeiten gezeigt, mit einer Java-Plattform zu arbeiten. In Kapitel 1.1.1.1 lernen Sie mit dem Java Development Kit eine Java-Plattform kennen. In Kapitel 1.1.1.2 lernen Sie die integrierte Entwicklungsumgebung Eclipse kennen, die eine Java-Plattform, einen Editor und weitere Hilfswerkzeuge bereits unter einer gemeinsamen Oberfläche zur Verfügung stellt. Die erste Möglichkeit ist für diejenigen geeignet, die wenig Erfahrung mit Entwicklungsumgebungen haben und sich erst einmal auf die Programmiersprache Java konzentrieren möchten. Die zweite Möglichkeit ist für diejenigen gedacht, die bereits andere Entwicklungsumgebungen – oder vielleicht sogar Eclipse – kennen und auf die Komfortfunktionen einer Entwicklungsumgebung nicht verzichten möchten. 1.1.1.1 Java Development Kit Das Java Development Kit (JDK) wird von der Firma Oracle zur Verfügung gestellt und ist die meistgenutzte Java-Plattform, um Java-Programme zu entwickeln und auszuführen. Definition: Java Development Kit (JDK) Das JDK ist eine Java-Plattform mit einem für die jeweilige Rechner-Plattform spezifischen Java-Bytecode-Interpreter. Um Java-Programme entwickeln und ausführen zu können, benötigen Sie also ein JDK. Für jede Ausführung (zum Beispiel Java SE oder Java EE) existiert für jede unterstützte Rechner-Plattform ein JDK. Sie müssen sich also im ersten Schritt für eine Ausführung entscheiden (in diesem Studienbrief benötigen Sie die Java SE) und im zweiten Schritt müssen Sie festlegen, auf welcher Rechner-Plattform Sie Java-Programme entwickeln und ausführen möchten. Mit diesem Wissen können Sie nun auf folgender Webseite http://www.oracle.com/technetwork/java/javase/downloads/index.html das passende JDK herunterladen. Zuerst wählen Sie dort die Java SE aus, und dann suchen Sie unter Downloads die Rechner-Plattform, auf der Sie entwickeln möchten. Beispielsweise wählen Sie „Windows x86“ aus, wenn Sie Windows als 32-BitBetriebssystem installiert haben, oder „Windows x64“, wenn Sie Windows als 64-BitBetriebssystem installiert haben. Falls Sie sich unsicher sind, ob Sie Windows als 32- oder als 64-Bit-Betriebssystem installiert haben, schauen Sie bitte in der Systemsteuerung unter System nach. Unter Systemtyp finden Sie dort die benötigte Angabe. Kapitel 1 å JAV101 7 Laden Sie die entsprechende Datei auf Ihren Rechner und starten Sie die Installation. Achten Sie während der Installation auf den Installationspfad, damit Sie wissen, wo das JDK installiert wurde. Unter Windows erfolgt die Installation typischerweise unter: C:\Programme\Java. Nach der Installation befinden sich darin die beiden Verzeichnisse jre7 und jdk1.7.0_xx. Das xx steht hierbei stellvertretend für die UpdateVersion, wie beispielsweise 02. Im Verzeichnis jdk1.7.0_xx werden mehrere Verzeichnisse angelegt, unter anderem ein Verzeichnis namens bin. In diesem Verzeichnis befinden sich die Werkzeuge javac.exe (Java-Compiler) und java.exe (Java-Bytecode-Interpreter), die Sie zum Übersetzen und Ausführen Ihrer Java-Programme benötigen. Im Unterverzeichnis jre\lib befindet sich – auf mehrere Archive aufgeteilt – die Java-Klassenbibliothek. Die Unterscheidung JRE und JDK, die Sie auch in den installierten Verzeichnissen wiederfinden, hat die folgende Bedeutung: Eine Java Runtime Environment (JRE) beinhaltet nur diejenigen Bestandteile eines JDKs, welche zum Ausführen von Java-Programmen benötigt werden. Damit besteht eine JRE aus einem Bytecode-Interpreter für die jeweilige RechnerPlattform und der Java-Klassenbibliothek. Definition: Java Runtime Environment (JRE) Um zu testen, ob nach der Installation noch Konfigurationen auf Ihrem Betriebssystem erforderlich sind, öffnen Sie eine Kommandozeile (Eingabeaufforderung) und geben bitte Folgendes in separaten Zeilen ein: java -version javac -version Als Ausgabe sollten Sie jeweils eine Versionsangabe – wie beispielsweise 1.7.0_xx – erhalten. Sollten die Befehle nicht gefunden werden, die ausgegebene Version nicht derjenigen entsprechen, die Sie installiert haben oder die Versionsangaben unterschiedlich sein, müssen Sie die Umgebungsvariablen JAVA_HOME, PATH oder CLASSPATH überprüfen und gegebenenfalls explizit setzen. Für das Setzen der Umgebungsvariablen JAVA_HOME, PATH oder CLASSPATH sehen Sie bitte in (HEINISCH et al., 2010) nach. Durch Nachschlagen der Stichwörter JAVA_HOME, PATH oder CLASSPATH im Index finden Sie die richtige Stelle im Buch. Falls alles passt, können Sie nun unmittelbar mit Kapitel 1.1.2 fortfahren, um das erste Java-Programm in einem Editor zu erstellen und auszuführen. Falls Sie nach dem Erstellen und Ausführen des ersten Java-Programmes neugierig sind, wie man ein JavaProgramm in der Entwicklungsumgebung Eclipse erstellt und zum Laufen bringt, kehren Sie einfach zu Kapitel 1.1.1.2 zurück. 1.1.1.2 Entwicklungsumgebung Eclipse Eclipse ist eine Entwicklungsumgebung, die – über eine komfortable grafische Bedienoberfläche – dem Programmierer einfachen und direkten Zugriff auf alle benötigten Entwicklungswerkzeuge bietet, um Java-Programme zu schreiben und auszuführen. So findet sich in Eclipse integriert ein komfortabler Editor, um Java-Programme einzutippen, sowie Bedienelemente, um Java-Programme direkt auszuführen oder zu debuggen. Auf Syntaxfehler im Java-Programm wird der Programmierer bereits beim Eintippen hingewiesen und beim Speichern des Programmes wird automatisch der Java-Compiler Kapitel 1 å JAV101 8 aufgerufen. Da viele Dinge automatisch erfolgen, ist es für einen Anfänger oftmals schwer zu erkennen, was wirklich passiert. Was für einen erfahrenen Programmierer Komfort darstellt, wirkt für den Einsteiger aufgrund der vielfältigen Möglichkeiten, die zu Beginn auch gar nicht benötigt werden, verwirrend. Für Programmierer, die bereits mit Entwicklungsumgebungen gearbeitet haben, oder vielleicht sogar Eclipse beim Programmieren in anderen Programmiersprachen schon kennen gelernt haben, bietet es sich natürlich an, den Studienbrief unter Einsatz der Entwicklungsumgebung Eclipse durchzuarbeiten, um auf den gewohnten Komfort nicht verzichten zu müssen. Die Entwicklungsumgebung Eclipse können Sie kostenlos unter folgendem Link heruntergeladen: http://www.eclipse.org/ Unter „Download Eclipse“ und danach „Eclipse IDE for Java Developers“ können Sie unter Angabe Ihrer Rechner-Plattform Eclipse auf Ihren Rechner laden. Zur Installation müssen Sie das heruntergeladene Archiv in einen Ordner ihrer Wahl extrahieren und können dann die Anwendung eclipse.exe direkt starten. Abbildung 1 zeigt die grafische Bedienoberfläche von Eclipse nachdem das Beispielprogramm im folgenden Kapitel 1.1.2 eingetippt und gespeichert wurde. Unterhalb des Editor-Fensters wird nach dem Ausführen die Ausgabe des Programmes angezeigt. Die Ausführung eines Java-Programmes in Eclipse erfolgt durch Drücken des weißen Pfeiles, der nach rechts zeigt und sich in einem grün ausgefüllten Kreis befindet. Im Hintergrund wird dann der Java-Bytecode-Interpreter java aufgerufen. Abbildung 1: Grafische Bedienoberfläche der Entwicklungsumgebung Eclipse Neben Eclipse gibt es noch eine Vielzahl weiterer Entwicklungsumgebungen, um JavaProgramme zu entwickeln. Einige seien hier exemplarisch genannt: P BlueJ ist eine Entwicklungsumgebung zur Einführung in die Programmiersprache Java. Weitere Informationen finden Sie unter http://www.bluej.org/. Kapitel 1 å JAV101 9 P JBuilder (http://www.borland.com) ist eine kommerzielle Entwicklungsumgebung. P JCreator (http://www.jcreator.com) ist ebenfalls eine kommerzielle Entwicklungsumgebung. Zum Durcharbeiten des Studienbriefs können Sie – neben dem JDK – eine der genannten oder eine andere Entwicklungsumgebung für Java verwenden. 1.1.2 Das Programm „Hello, World!“ Nach dem Exkurs zu den benötigten Werkzeugen werden Sie hier lernen, wie Sie ein Java-Programm im Editor schreiben und wie Sie den Java-Compiler (javac) und den Java-Bytecode-Interpreter (java) des JKDs einsetzen. Öffnen Sie einen Editor ihrer Wahl und geben Sie den Text ein, den Sie im folgenden Bild sehen: Abbildung 2: Editor Notepad unter Windows mit dem „Hello, world!“-Programm Bitte achten Sie beim Eintippen des Programms im Text-Editor und bei der Vergabe des Dateinamens auf die Groß- und Kleinschreibung, da in Java zwischen Groß- und Kleinbuchstaben unterschieden wird. Man sagt auch: Java ist case sensitiv. Java ist case sensitiv. Die genaue Bedeutung des Java-Quellcodes – wie class, public, static oder System.out.println() – werden Sie im Laufe des Studienbriefs noch kennenlernen. Wichtig ist im ersten Schritt, dass Sie Programme mithilfe von Compiler und Interpeter zur Ausführung bringen können. Speichern Sie das Programm unter dem Dateinamen HelloWorld.java ab. Achten Sie beim Speichern darauf, dass nicht eine zusätzliche Endung – wie beispielsweise .txt – hinzugefügt wird. Im nächsten Schritt müssen Sie das erstellte Programm durch den Compiler javac in Java-Bytecode übersetzen. Hierzu öffnen Sie eine Kommandozeile (Eingabeaufforderung), wechseln in das Verzeichnis, in welchem Sie die Datei HelloWorld.java abgespeichert haben, und geben Folgendes ein: javac HelloWorld.java Danach drücken Sie die <RETURN>-Taste. Der javac-Compiler übersetzt dann den Java-Quellcode in der Datei HelloWorld.java in Java-Bytecode und legt diesen in der Datei HelloWorld.class ab. Zur Ausführung des Bytecodes der Datei HelloWorld.class rufen Sie – durch Eingabe von java HelloWorld Kapitel 1 å JAV101 10 und anschließendem Drücken der <RETURN>-Taste – den Interpreter auf. Der BytecodeInterpreter übersetzt nun den Bytecode in der Datei HelloWorld.class in Maschinencode und bringt diesen direkt zur Ausführung. Bitte beachten Sie, dass der Interpreter java den Klassennamen HelloWorld und nicht den vollständigen Dateinamen HelloWorld.class verlangt. Der Aufruf von Compiler und Interpreter sieht in der Windows-Eingabeaufforderung wie folgt aus: Abbildung 3: Kompilieren und Starten über Kommandos in der Windows-Konsole Das erste Programm macht nichts anderes, als Hello, world! auf dem Bildschirm auszugeben. Schreiben Sie das Programm so um, dass ein beliebiger anderer Text ausgegeben wird. Speichern Sie Ihr Programm und übersetzen Sie es erneut. Danach bringen Sie das Programm nochmals zur Ausführung, um die Veränderung in der Textausgabe zu überprüfen. P Um Java-Programme schreiben und ausführen zu können, benötigen Sie einen Editor und eine Java-Plattform, die p einen Java-Compiler (javac) p die Java-Klassenbibliothek p einen Java-Interpreter (java) enthält. P Das Java Development Kit (JDK) von der Firma Oracle ist eine Java-Plattform mit einem für die jeweilige Rechner-Plattform spezifischen Java-Bytecode-Interpreter. P Eclipse ist eine Entwicklungsumgebung, die Zugriff auf alle benötigten Entwicklungswerkzeuge bietet. K [1] K [10] K [6] Kapitel 1 å JAV101 Was benötigt man, um ein Java-Programm zu schreiben und auszuführen? Versuchen Sie, bei Ihrer Antwort die folgenden Begriffe zu verwenden und diese in einen logischen Zusammenhang zu bringen: Editor, Java-Quellcode, Java-Compiler, Java-Bytecode, Java-Klassenbibliothek und Java-Interpreter. Analysieren Sie Ihr „Hello, World!“-Programm. An welcher Stelle im Programm verwenden Sie bereits die Java-Klassenbibliothek? Falls Sie diese Frage noch nicht beantworten können, notieren Sie einfach ihre Vermutung und verifizieren Sie diese nach dem Durcharbeiten von weiteren Kapiteln. Recherchieren Sie in (HEINISCH et al., 2010) nach dem Stichwort Bytecode. Finden Sie heraus, welche Vorteile die Übersetzung in einen Zwischencode – den Bytecode – hat. 11 1.2 Das objektorientierte Konzept Das „Handwerkszeug“ zum Programmieren in Java haben Sie nun kennen gelernt. Sie sollen in Java aber nicht „nur programmieren“, sondern Sie sollen objektorientiert programmieren. Aus diesem Grund müssen Sie verstehen, was sich hinter dem objektorientierten Konzept (alternative Begriffe: objektorientierter Ansatz, objektorientiertes Paradigma oder einfach Objektorientierung) verbirgt. Das objektorientierte Konzept beeinflusst nicht nur die Programmierung, sondern auch die Tätigkeiten in Analyse und Entwurf, die der Implementierung vorgelagert sind. Abbildung 4 setzt die Begriffe, die Ihnen im Rahmen des objektorientierten Konzeptes begegnen, zueinander in Beziehung. objektorientiertes Konzept Objektorientierte Modellierung (OOM) Analyse Entwurf Notation: Unified Modelling Language (UML) Objektorientierte Programmierung (OOP) Abbildung 4: Das objektorientierte Konzept und damit verbundene Begriffe Implementierung Programmiersprache: Java, C++, C#, … Erfolgen die Tätigkeiten in Analyse und Entwurf nach dem objektorientierten Konzept und die Ergebnisdokumentation in UML, so spricht man von einer objektorientierten Modellierung. Erfolgt die Implementierung konform zum objektorientierten Konzept in einer objektorientierten Programmiersprache, so spricht man von einer objektorientierten Programmierung. Während die objektorientierte Modellierung dem Software-Engineering zugeordnet wird, wird die objektorientierte Programmierung typischerweise im Rahmen einer objektorientierten Programmiersprache gelehrt. 1.2.1 Die Denkweise in Objekten und Klassen Für das objektorientierte Konzept ist das Denken in Objekten und Klassen von zentraler Bedeutung. Möchte man Aufgaben, die bisher manuell erledigt wurden, durch den Einsatz eines EDV-Systems unterstützen, so stellt man sich beim objektorientierten Ansatz folgende Fragen: P Mit welchen Objekten hat man es beim Erledigen der Aufgaben zu tun? P Welche Eigenschaften dieser Objekte sind im Rahmen der zu erledigenden Aufgaben von Bedeutung? P Was wird mit den Objekten gemacht? Diese drei Fragestellungen werden in den folgenden Unterkapiteln beleuchtet. Kapitel 1 å JAV101 12 1.2.1.1 Finden der relevanten Objekte und Klassen Möchte man beispielsweise die Aufgaben einer Bibliothek – die bisher mithilfe von Karteikarten und manuell gepflegten Listen durchgeführt wurden – durch Einsatz eines EDV-Systems unterstützen, so werden mit Sicherheit die vielen „Buch-Objekte“, die es in der Bibliothek gibt, ins Auge fallen. Jedes in der Bibliothek existente Buch ist in der Objektorientierung ein eigenes „Buch-Objekt“, das beispielsweise ausgeliehen und wieder zurückgegeben werden kann. Objekte können nicht nur Gegenstände sein (wie die konkret existenten Bücher), sondern auch Wesen, die im Rahmen der Aufgaben von Bedeutung sind. Stellt man sich als Beobachter in die Bibliothek, so kann man sehen, wie Personen in die Bibliothek kommen und Bücher „mitnehmen“ bzw. „zurückbringen“. Bei genauem Betrachten der Personen, und der von ihnen durchgeführten Tätigkeiten, erkennt man recht schnell, dass es sich nicht um beliebige Personen handelt, sondern um Personen, die in der Bibliothek registriert sind und einen Bibliotheksausweis besitzen. Personen, die einen Bibliotheksausweis besitzen, werden fortan als „Ausleiher-Objekte“ bezeichnet. Damit wären die wichtigsten Objekte – die „Buch-Objekte“ und die „Ausleiher-Objekte“ – für die zukünftige Bibliotheksverwaltung bereits gefunden. Was kann zum Objekt werden? Neben existenten Gegenständen in der realen Welt (wie z. B. Bücher) können auch Wesen (wie z. B. Ausleiher oder Mitarbeiter) oder Konzepte (wie z. B. Versicherungsverträge oder Rechnungen) relevante Objekte darstellen. Hat man die relevanten Objekte gefunden, so ist es ein ganz kleiner Schritt zu den Klassen. Für die vielen „Buch-Objekte“ wird die Klasse Buch eingeführt und für die vielen „Ausleiher-Objekte“ wird die Klasse Ausleiher eingeführt. Unter einer Klasse werden alle gleichartigen Objekte zusammengefasst. Aus Sicht einer objektorientierten Programmiersprache ergibt sich folgende Definition: Definition: Klasse und Objekt Klassen stellen die Baupläne für Objekte dar. Die Klassen sind die Datentypen, die Objekte die Variablen (Instanzen) dieser Datentypen. Ein Objekt wird gemäß dem Bauplan der Klasse erzeugt. Aus der Programmiersprache C kennen Sie beispielsweise den Datentyp int. Von diesem Datentyp können Variablen (z. B. int i oder int j) erzeugt und den Variablen können individuelle Werte (z. B. i = 5 und j = 6) aus dem Wertebereich des Datentyps int zugewiesen werden. In Analogie zu diesem einfachen Datentyp – den es auch in Java gibt – stellt eine Klasse nichts anderes als einen zusammengesetzten, selbst definierten Datentyp dar. Im Rahmen der Bibliotheksverwaltung führen wir also die neuen Datentypen Buch und Ausleiher ein. Von diesen Datentypen können dann beliebig viele Variablen (Objekte, Instanzen) erzeugt und mit den für das konkrete Buch- oder Ausleiher-Objekt charakteristischen Werten initialisiert werden. Damit man eine Klasse in der Form eines Datentyps beschreiben kann, muss man sich überlegen, aus welchen Daten (alternative Begriffe: Eigenschaften, Datenfeldern, Attributen) sich der Datentyp zusammensetzen soll. Mit dieser Frage werden Sie sich im nächsten Kapitel beschäftigen. Kapitel 1 å JAV101 13 1.2.1.2 Finden relevanter Eigenschaften von Objekten bzw. Klassen Die relevanten Eigenschaften eines Objektes bzw. einer Klasse werden in objektorientierten Programmiersprachen typischerweise als Datenfelder bezeichnet. Es ist also die Frage zu beantworten, welche Datenfelder – im Rahmen der zu automatisierenden Aufgaben – für die gefundenen Klassen von Bedeutung sind. Für die betrachtete Klasse Buch könnten dies unter anderem sein: Buchnummer, ISBN, Titel, Autor und Auflage. Für die betrachtete Klasse Ausleiher könnten dies unter anderem sein: Ausleihernummer, Vorname, Name und Anschrift. Die Darstellung der Klasse Buch in der UML könnte nach ersten Überlegungen wie folgt aussehen: – – – – – – Abbildung 5: Klasse Buch mit ersten privaten Datenfeldern Klassenname Buch Buch buchNummer ISBN titel autoren auflage erscheinungsjahr private Datenfelder Die UML ist – wie bereits erwähnt – die grafische Notationssprache, die für das objektorientierte Konzept eingesetzt wird. Klassen – wie auch Objekte – werden in der UML durch ein Rechteck dargestellt. Bei einer Klasse steht oben im Rechteck der Klassenname in Fettdruck. Es folgen die Datenfelder. In Abbildung 5 steht vor den Datenfeldern ein kleiner Strich. Der kleine Strich bedeutet, dass das jeweilige Datenfeld nur von den Methoden der eigenen Klasse verändert werden kann. Man sagt auch, die Datenfelder sind privat. Wie die relevanten Methoden gefunden werden können, wird im nächsten Kapitel erläutert. Die Darstellung eines exemplarischen Objektes buch1 der Klasse Buch sieht in der UML wie folgt aus: buch1:Buch buchNummer = AF1001 ISBN = 978-3-8348-0656-7 titel = Java als erste Programmiersprache autoren = Heinisch, Müller-Hofmann, Goll auflage = 6 erscheinungsjahr = 2010 Objektname buch1 Klassenname Buch Datenfelder mit individuellen Werten für das Objekt buch1 In der UML-Notation steht bei einem Objekt oben im Rechteck der Objektname gefolgt von einem Doppelpunkt. Hinter dem Doppelpunkt steht der Name jener Klasse, von welcher das Objekt erzeugt wurde. Handelt es sich um ein ganz konkretes Objekt, so wird Objektname:Klassenname unterstrichen. Wäre ein beliebiges Objekt der Klasse Buch gemeint, so würde man nur :Buch (ohne Unterstreichung) in das Rechteck schreiben. In diesem Fall wären die Datenfelder auch nicht mit individuellen Werten belegt. Abbildung 6: Objekt buch1 der Klasse Buch mit individuellen Werten Unterscheidung konkretes und beliebiges Objekt in der UML Kapitel 1 å JAV101 14 1.2.1.3 Finden relevanter Methoden von Objekten bzw. Klassen Zu einer Klasse bzw. zu einem Objekt gehören nicht nur Datenfelder, sondern auch Methoden. Zum Finden der relevanten Methoden ist folgende Frage zu beantworten: Was kann man mit den Objekten machen? Konkret auf unser Beispiel bezogen lautet die Frage: Was kann man mit den „Buch-Objekten“ in der Bibliothek machen bzw. was tun die „Ausleiher-Objekte“ in der Bibliothek? Stellt man sich als Beobachter in die Bibliothek, so sieht man Folgendes: Ein Buch wird von einem Ausleiher ausgeliehen, ein Buch wird von einem Ausleiher zurückgegeben, ein Buch wird in die Bibliothek aufgenommen, ein Buch wird durch den Bibliothekar in ein Regal gestellt, ein Buch wird durch den Ausleiher aus einem Regal geholt, usw. Damit die relevanten Methoden für die Objekte gefunden werden, muss man sich nun die Frage stellen, welche der beobachtbaren Vorgänge, bzw. welche Teile der beobachtbaren Vorgänge tatsächlich automatisiert werden sollen. Unterscheidung Geschäftsprozess und Anwendungsfall Durch Beobachten der Abläufe in der Bibliothek werden die sogenannten Geschäftsprozesse identifiziert. Für die spätere Programmierung sind jedoch die sogenannten Anwendungsfälle relevant. Die Anwendungsfälle werden gefunden, indem man die Geschäftsprozesse genau analysiert und festlegt, welche Teile durch das neue System automatisiert werden sollen. Der Geschäftsprozess „Buch ausleihen“ lässt sich beispielsweise in folgende Schritte zerlegen: P P P P P Buchrecherche durchführen Buchverfügbarkeit prüfen Buch aus Regal holen Ausleiher identifizieren Buch für Ausleiher als entliehen buchen Für die Schritte „Buchrecherche durchführen“, „Buchverfügbarkeit prüfen“, „Ausleiher identifizieren“ und „Buch für Ausleiher als entliehen buchen“ wird man weiter prüfen, inwiefern diese automatisiert werden können. Prinzipiell kann auch der Schritt „Buch aus Regal holen“ automatisiert werden. Der tatsächliche Automatisierungsgrad ist – je nach Projekt und Projektbudget, sowie den Zielen des Auftraggebers – individuell festzulegen. Für jeden zu automatisierenden Schritt ist zu prüfen, welche Objekte mit welchen Methoden hier unterstützen können. Analysieren wir beispielhaft das „Buch-Objekt“: Ein einzelnes „Buch-Objekt“ kann keine Recherche durchführen, aber ein einzelnes „Buch-Objekt“ kann seine Daten für die Buch-Recherche zur Verfügung stellen. Es bietet beispielsweise eine Methode getData() oder spezifischer getTitel() usw. an. Um die Verfügbarkeit eines Buches zu prüfen, benötigt ein Buch einerseits das Wissen, wie viele Exemplare des Buches überhaupt in der Bibliothek geführt werden, und andererseits eine Möglichkeit, die verfügbaren Buchexemplare abzufragen. Durch diese Überlegung wird erkannt, dass für das „Buch-Objekt“ zum einen ein neues Datenfeld anzahlExemplare und zum anderen eine Methode getAnzahlExemplare() benötigt wird. Schritt für Schritt werden über die Analyse der zu automatisierenden Aufgaben – in anderen Worten durch die Analyse der Anwendungsfälle – neue Methoden und Datenfelder gefunden. Nach einigen Überlegungen könnte die UML-Notation der Klasse Buch wie folgt aussehen: Kapitel 1 å JAV101 15 Buch – – – – – – – – buchNummer ISBN titel autoren auflage erscheinungsjahr anzahlExemplare anzahlVerliehen getTitel() getISBN() isVerfügbar() getAnzahlExemplare() Klassenname Buch Abbildung 7: Klasse Buch mit Datenfeldern und Methoden private Datenfelder Methoden Identifiziert man Vorgänge, die man keiner bereits bekannten Klasse als Methoden zuordnen kann, so muss man überlegen, ob eine neue Klasse benötigt wird. Das systematische Analysieren der Anwendungsfälle und das Finden von benötigten Klassen, Datenfeldern und Methoden ist Kernaufgabe der objektorientierten Modellierung. Auf die Einzelheiten der objektorientierten Modellierung kann hier nicht vertieft eingegangen werden. Sie müssen jedoch die grundlegenden Zusammenhänge verstehen: Im objektorientierten Konzept werden Objekte, sowie deren Datenfelder und Methoden, durch Beobachten der Realität gefunden. Das – während der Analysetätigkeiten – erstellte – und später durch die Entwurfstätigkeiten verfeinerte – Modell wird im Rahmen der objektorientierten Programmierung in eine objektorientierte Programmiersprache übersetzt. Um gute objektorientierte Programme zu schreiben, genügt es nicht, eine objektorientierte Programmiersprache zu beherrschen, ausschlaggebend ist, dass zuvor das richtige objektorientierte Modell erstellt wird. 1.2.2 Objektorientiertes versus funktionsorientiertes Konzept Welche Unterschiede gibt es zwischen dem klassischen funktionsorientierten und dem objektorientierten Konzept? Um diese Frage zu beantworten, vorab eine kurze Wiederholung, was unter dem funktionsorientierten Konzept verstanden wird: Für das funktionsorientierte Konzept ist kennzeichnend, dass im Entwurf eine Zerlegung des Systems in Haupt- und Unterprogramme erfolgt. Anstatt von Haupt- bzw. Unterprogrammen, wird auch von Funktionen bzw. Prozeduren gesprochen. Für die Implementierung kommen prozedurale Programmiersprachen – wie beispielsweise C – zum Einsatz. Definition: Funktionsorientiertes Konzept Die folgenden Argumente (GOLL, 2011) sollen einen Einblick in die essenziellen Unterschiede zwischen funktionsorientiertem und objektorientiertem Konzept geben: P (Mangelnder) Schutz der Daten: Im funktionsorientierten Konzept werden die Daten von Funktion zu Funktion weitergereicht und innerhalb der Funktionen verändert. Unter Umständen wird sogar mit globalen Daten gearbeitet, die in allen Funktionen verändert werden können. Bei dieser Vorgehensweise verliert man leicht den Über- Schutz der Daten Kapitel 1 å JAV101 16 blick, welche Auswirkungen eine Datenänderung auf andere Funktionen hat und welche Funktion für eventuell fehlerhafte Daten verantwortlich ist. Im objektorientierten Konzept werden Daten und zugehörige Methoden als eine Einheit betrachtet. Eine Klasse bzw. ein Objekt beinhaltet sowohl die relevanten Daten als auch die Methoden, welche auf diesen Daten arbeiten. Die Daten können nur von den Methoden der eigenen Klasse verändert werden. Man sagt auch, die Daten sind vor dem „Zugriff von außen“ geschützt. Verständlichkeit gegenüber dem Kunden P (Mangelnde) Verständlichkeit gegenüber dem Kunden: Die Trennung von Daten und Funktionen im funktionsorientierten Konzept führt dazu, dass der Auftraggeber seine Aufgabenstellung in den Analyse- und Entwurfsmodellen nicht mehr erkennen kann. Der Entwickler beginnt oftmals unverzüglich im Lösungsbereich zu denken. Die Begriffswelt und die Modelle des Lösungsbereichs sind für den Auftraggeber aber nicht verständlich. Im objektorientierten Konzept erfolgt die Modellierung in der Begriffswelt des Kunden. Die Objekte aus der Begriffswelt des Kunden werden mit ihren Eigenschaften und Methoden in ein Modell transferiert und später in einer objektorientierten Programmiersprache programmiert. Dies führt dazu, dass der Auftraggeber die Modelle besser verstehen kann. Hierdurch kann einfacher sichergestellt werden, dass die Entwickler genau das System bauen, welches der Kunde benötigt. Zusammenhang zwischen Systemanalyse und Systementwurf P (Mangelnder) Zusammenhang zwischen Systemanalyse und Systementwurf: Im funktionsorientierten Ansatz gibt es keine eindeutige Abbildung der Datenflussdiagramme der strukturierten Analyse in den Systementwurf. Dieser Methodenbruch macht es schwierig, nachzuvollziehen, ob die Ergebnisse der Systemanalyse korrekt in den Systementwurf und den Programmcode überführt worden sind. Im objektorientierten Konzept gibt es keinen Methodenbruch. Mit Beginn des Projektes wird in Klassen und Objekten gedacht. In Systemanalyse und -entwurf werden die Modelle kontinuierlich erweitert und vervollständigt. Das letzte Modell des Entwurfs ist die Grundlage für die Implementierung. Es ist sogar möglich, die objektorientierten Entwurfsmodelle so genau zu beschreiben, dass eine automatische Code-Generierung durchgeführt werden kann. Übersicht bei großen Systemen P (Mangelnde) Übersicht bei großen Systemen: Im funktionsorientierten Ansatz können mehrere Anweisungen zu Funktionen gebündelt werden. Bei komplexen und umfangreichen Systemen erhält man sehr viele Funktionen. Mit zunehmender Systemgröße wird es damit immer schwieriger, den Überblick zu behalten. Im objektorientierten Konzept stehen mit Klassen und Paketen größere Strukturierungseinheiten zur Verfügung. Bei einer korrekten Verwendung von Klassen und Paketen lässt sich die Komplexität von großen Systemen damit besser beherrschen. Wiederverwendbarkeit von Quellcode P (Mangelnde) Wiederverwendbarkeit von Quellcode: Gekoppelt mit der mangelnden Übersicht ist eine mangelnde Wiederverwendbarkeit im funktionsorientierten Ansatz. Erkennt man aufgrund der hohen Komplexität vorhandene Bausteine nicht, kann man sie auch nicht verwenden. Oftmals lohnt sich die Suche nach wiederverwendbaren Teilen nicht, da Suchaufwand und Nutzen – aufgrund der geringen Größe der Bausteine – nicht in einem vernünftigen Verhältnis stehen. Für die Wiederverwendbarkeit im objektorientierten Konzept ist ausschlaggebend, dass Klassen modelliert werden, die zusammengehörige Daten und Methoden in eine Einheit packen. Als weiterer Strukturierungsbaustein werden dann Pakete gebündelt, die zusammengehörige Klassen in eine Einheit packen. Auf der Basis gut durchdachter Klassen, können dann weitere Mechanismen – wie Komposition, Aggregation, Vererbung und Polymorphie eingesetzt werden, um eine optimale Wiederverwendbarkeit zu erlangen. Kapitel 1 å JAV101 17 Es ist jedoch falsch, zu glauben, dass man durch Einsatz der Objektorientierung automatisch eine höhere Wiederverwendung erhält. Dies ist nur dann der Fall, wenn die Entwickler in der Lage sind, Klassen zu entwerfen, die zusammengehörige Daten und Methoden bündeln sowie klare und wohl definierte Schnittstellen besitzen. P (Mangelnde) Stabilität: Ein Entwurf in der funktionsorientierten Vorgehensweise ist sehr empfindlich gegenüber nachträglichen Änderungen. Daten und Funktionen sind getrennt. Kommen neue Funktionen oder Daten hinzu, so kann dies erhebliche Änderungen des Programmgefüges nach sich ziehen. Es kann sein, dass die Aufrufhierarchie komplett neu entworfen werden muss. Im objektorientierten Konzept beschränken sich Änderungen oftmals nur auf einzelne Klassen. Bleiben die Schnittstellen einer Klasse stabil (das sind die nach außen sichtbaren Methoden), dann können beispielsweise innerhalb der Klasse die Algorithmen komplett geändert werden, ohne dass andere Klassen angepasst werden müssen. Man erhält allerdings – ebenso wie bei der Wiederverwendbarkeit – nur dann eine sehr gute Stabilität, wenn die Klassen sorgfältig und durchdacht entworfen wurden. Stabilität Das objektorientierte Konzept ermöglicht das Denken in Objekten vom Start des Projektes bis zur Programmierung. Damit existiert ein durchgängiges Denkschema von der realen Welt über die „Welt der Modellierung“ bis in die „Welt der Programmierung“. Beim Schritt von der realen Welt in die „Welt der Modellierung“ muss man festlegen, was von der realen Welt für die zu bauende Software von Interesse ist. Beim Schritt von der „Welt der Modellierung“ in die „Welt der Programmierung“ wird das Modell auf die Sprachkonstrukte der Programmiersprache abgebildet. Welche Sprachkonstrukte die objektorientierte Programmiersprache Java hierfür zur Verfügung stellt, werden Sie im nächsten Kapitel erfahren. P Bei einer objektorientierten Modellierung erfolgen die Tätigkeiten in Analyse und Entwurf nach dem objektorientierten Konzept und die Ergebnisse werden in UML dokumentiert. P Bei der objektorientierten Programmierung erfolgt die Implementierung konform zum objektorientierten Konzept in einer objektorientierten Programmiersprache. P Fragestellungen des objektorientierten Ansatzes sind: p Welche Objekte bzw. Klassen sind relevant? p Welche relevanten Eigenschaften besitzen die Objekte bzw. Klassen? p Was wird mit den Objekten gemacht? Welche Methoden sind für die Objekte bzw. Klassen relevant? P Gegenstände der realen Welt, Wesen oder Konzepte können Objekte darstellen. P Klassen stellen die Baupläne für Objekte dar, ein Objekt wird gemäß diesem Bauplan erzeugt. Zeichnen Sie in der UML-Notation eine Klasse Ausleiher mit den Datenfeldern ausleiherNummer, name, vorname, strasse, hausNummer, plz und ort sowie den exemplarischen Methoden getAusleiherNummer() und getName(). Zeichnen Sie ferner ein beliebiges Objekt der Klasse Ausleiher und ein spezifisches Objekt der Klasse Ausleiher. Belegen Sie die Datenfelder des spezifischen Objektes mit beispielhaften Werten und vergeben Sie den Objektnamen ausleiher1. K [2] Kapitel 1 å JAV101 18 K [35] Was ist der Unterschied zwischen einer Klasse und einem Objekt? K [23] Wie werden im objektorientierten Konzept Klassen bzw. Objekte, Datenfelder und Methoden gefunden? K [22] Was ist die Grundlage dafür, dass im objektorientierten Konzept eine höhere Wiederverwendbarkeit und eine bessere Stabilität als im funktionsorientierten Konzept erreicht werden kann? 1.3 Objektorientierung in Java Dieses Kapitel soll folgende Frage beantworten: Wie ist das objektorientierte Konzept in der Programmiersprache Java abgebildet? Sie lernen in diesem Kapitel, wie Klassen programmiert und Objekte erzeugt werden. Darüber hinaus begegnen Sie dem Konzept der Vererbung, den Schnittstellen und den Paketen. Abschließend werden Sie noch lernen, wie Sie die Java-Klassenbibliothek in Ihren eigenen Programmen verwenden können. 1.3.1 Klassen und Objekte Klassen bzw. Objekte sind die wichtigsten Bausteine im objektorientierten Konzept. Deshalb werden Sie zuallererst eine Klasse Person programmieren und von der Klasse Person mehrere Objekte erzeugen. Öffnen Sie einen Editor und erstellen Sie die folgenden beiden Java-Quellcode-Dateien in einem Ordner beispiele. In dem Ordner beispiele sollten sich dann die beiden Dateien Person.java und TestPerson.java befinden. // Datei: Person.java public class Person // Klassendeklaration der Klasse Person { private String name; // privates Datenfeld name private String vorname; // privates Datenfeld vorname // Methode, um den Namen zu setzen. public void setName (String n) { name = n; } // Methode, um den Vornamen zu setzen. public void setVorname (String v) { vorname = v; } // Methode, um den Namen abzufragen. public String getName() { return name; } Kapitel 1 å JAV101 19 // Methode, um den Vornamen abzufragen. public String getVorname() { return vorname; } } // Datei: TestPerson.java public class TestPerson { public static void main (String[] args) { // Objekt der Klasse Person anlegen. Person p1 = new Person(); // Datenfelder mit Werten belegen. p1.setName ("Mustermann"); p1.setVorname ("Max"); // Nochmal ein Objekt der Klasse Person anlegen. Person p2; p2 = new Person(); // Datenfelder mit Werten belegen. p2.setName ("Meister"); p2.setVorname ("Ralf"); // Name und Vorname der Personen ausgeben. System.out.println (p1.getName() + " " + p1.getVorname()); System.out.println (p2.getName() + " " + p2.getVorname()); } } Öffnen Sie eine Eingabeaufforderung und wechseln Sie in Ihr Verzeichnis beispiele. Prüfen Sie, dass sich dort nun die beiden Dateien Person.java und TestPerson.java befinden. Als nächstes müssen Sie die beiden Java-Quellcode-Dateien mithilfe des Java-Compilers javac in Java-Bytecode übersetzen. Hierzu genügt es, wenn Sie Folgendes in der Kommandozeile eingeben: javac TestPerson.java Der Compiler javac übersetzt dann die Datei TestPerson.java in die JavaBytecode-Datei TestPerson.class. Der Compiler erkennt automatisch, dass innerhalb des Quellcodes der Datei TestPerson.java eine Klasse Person verwendet wird und sucht im aktuellen Verzeichnis, ob eine entsprechende Datei zu finden ist. Findet der Compiler eine Datei Person.java, so wird diese automatisch auch übersetzt und der zugehörige Bytecode wird in der Datei Person.class abgelegt. Existiert bereits eine Datei Person.class, so wird geprüft, ob die Datei Person.class älter ist als die Datei Person.java. Ist dies der Fall, so wird die Datei Person.java erneut übersetzt. Dieser Automatismus funktioniert allerdings nur dann, wenn Sie darauf achten, dass jede Klasse in einer eigenen Datei abgespeichert wird und dass Dateinamen und Klassennamen identisch sind. Es gehört in Java zu einem guten Programmierstil, diese Regel zu befolgen. Kapitel 1 å JAV101 20 Sollte der Compiler Ihnen Fehlermeldungen anzeigen, so müssen Sie den Quellcode nochmals sorgfältig studieren und die Fehler beseitigen. Erst wenn der Compiler keine Fehler mehr anzeigt – und sich im Verzeichnis beispiele zusätzlich die beiden Dateien Person.class und TestPerson.class befinden – ist der Übersetzungsvorgang abgeschlossen und Sie können Ihr Programm mit dem Java-Interpreter java zur Ausführung bringen. Geben Sie hierzu Folgendes in der Kommandozeile ein: java TestPerson Nun sollten Sie folgende Ausgabe erhalten: Mustermann Max Meister Ralf Bevor es weitergeht, noch ein paar Hintergrundinformationen zum ersten objektorientierten Java-Programm: P Eine Erläuterung hinter einem Doppelschrägstrich ist ein Kommentar. Ein Kommentar dient der Dokumentation und hat keinen Einfluss auf die Ausführung des Programmes. P Eine Klasse wird in Java durch das Schlüsselwort class deklariert. Hinter dem Schlüsselwort class steht der Klassenname. Üblicherweise wird die Klasse als public deklariert. Dies bedeutet, dass die Klasse für alle anderen Klassen sichtbar (und damit verwendbar) ist. P Innerhalb der geschweiften Klammern { } folgt die sogenannte Klassendefinition mit den Datenfeldern und Methoden. Die UML-Notation für eine Klasse bestehend aus Klassennamen, Datenfeldern und Methoden lässt sich im Quellcode gut wiedererkennen. P Datenfelder werden mit dem Schlüsselwort private als privat gekennzeichnet. Das Schlüsselwort private entspricht in der UML-Darstellung dem Minuszeichen vor einem Datenfeldnamen. Auf private Datenfelder können nur die Methoden der eigenen Klasse zugreifen. P Methoden werden üblicherweise mit dem Schlüsselwort public als öffentlich sichtbar gekennzeichnet. Methoden, die mit public gekennzeichnet sind, können von anderen Klassen aus aufgerufen werden. Innerhalb der Klasse TestPerson können beispielsweise die Methoden getName() und setName() der Klasse Person aufgerufen werden. P Damit man die Methoden einer Klasse aufrufen kann, muss man zuerst ein Objekt erzeugen. Die Klasse ist ja nur der Bauplan (der Datentyp) für die Objekte (Variablen). Ein Objekt kann in Java nur durch den new-Operator erzeugt werden. Nach dem Anlegen eines Objektes können den einzelnen Datenfeldern für dieses Objekt individuelle Werte zugewiesen werden. Ein Methodenaufruf erfolgt immer auf ein Objekt bezogen 1, da die Methoden die individuellen Werte des Objekts lesen oder verändern. 1 Diese Aussage gilt nur für Instanzmethoden. Klassenmethoden können auch ohne die Existenz eines Objektes aufgerufen werden. Klassenmethoden – mit Ausnahme der Methode main() – lernen Sie allerdings erst in Kapitel 2.5 kennen. Kapitel 1 å JAV101 21 P Die Datenfelder name und vorname sind vom Datentyp String. In einer Variablen vom Datentyp String (z. B. name oder vorname) kann eine Zeichenkette abgelegt werden. Zeichenketten vom Datentyp String können über den Operator + miteinander verkettet werden. Diese Verkettungsfunktion kommt bei der Ausgabe mithilfe von System.out.println() zum Einsatz. P Es wird als guter Programmierstil angesehen, wenn man zum Test einer Klasse eine eigene Testklasse schreibt. Mit diesem Vorgehen ist der eigentliche Programmcode stets vom Programmcode für den Test separiert. Die Testklassen können dann bei einer späteren Auslieferung der Software einfach weggelassen werden und verbrauchen keinen unnötigen Speicherplatz. P Die Methode main() ist eine ganz besondere Methode. Jede Java-Anwendung benötigt eine Methode main(), da sie mit dem Aufruf der main()-Methode ihre Ausführung beginnt. Beim Aufruf des Java-Interpreters mit java TestPerson wird vom Interpreter in der Klasse TestPerson die Methode main() gesucht und ausgeführt. Fehlt die Methode main(), oder ist diese nicht public, oder nicht static, so bricht der Interpreter mit einer Fehlermeldung ab. Das Schlüsselwort static kennzeichnet die Methode main() als Klassenmethode. Dies bedeutet, dass die Methode main() – ohne die Existenz eines Objektes – direkt (durch den Interpreter) aufgerufen werden kann. Jetzt haben Sie schon jede Menge über Java gelernt. Bevor es weiter geht, soll an dieser Stelle noch der Begriff der Referenzvariablen in Java erläutert werden. Sie haben Folgendes gelernt: Eine Klasse ist ein Datentyp und ein Objekt ist eine Variable. Ein Objekt kann in Java nur mithilfe des new-Operators erzeugt werden. Mit new Person(); wird ein Objekt der Klasse Person angelegt. Damit man mit diesem Objekt etwas machen kann, benötigt man einen „Zeiger“ auf dieses Objekt. Dieser Zeiger wird in Java Referenz bzw. Referenzvariable genannt. Eine Referenzvariable wird beispielsweise angelegt durch: Person p1; Die Referenzvariable p1 vom Datentyp Person – man sagt vereinfacht „vom Typ Person“ – kann nun auf ein beliebiges Objekt vom Typ Person zeigen. Mit p1 = new Person(); wird der Referenzvariablen p1 als Wert die Adresse zugewiesen, an welcher das Objekt vom Typ Person durch den new-Operator angelegt wurde. In Java wird eine Referenzvariable benötigt, um auf Objekte zuzugreifen, die mithilfe des new-Operators im Speicher angelegt wurden. In einer Referenzvariablen wird als Wert die Adresse abgelegt, an welcher sich das Objekt im Speicher befindet. Definition: Referenzvariable Kapitel 1 å JAV101 22 K [33] Zeichnen Sie die Klasse Person – und die beiden in der Klasse TestPerson erzeugten Objekte – in der UML-Notation. K [38] Ersetzen Sie das Schlüsselwort public vor den Methoden in der Klasse Person durch das Schlüsselwort private. Übersetzen Sie den geänderten Quellcode und versuchen Sie das Programm durch Aufruf des Interpreters java TestPerson auszuführen. Was passiert? Begründen Sie Ihre Beobachtung. K [21] Erweitern Sie die Klasse TestPerson wie folgt: P Erzeugen Sie ein drittes Objekt der Klasse Person. Initialisieren Sie dieses und geben Sie Name und Vorname der dritten Person auf dem Bildschirm aus. P Nach der Ausgabe auf dem Bildschirm verändern Sie Vor- und Nachname einer der Personen durch Aufruf der jeweiligen set()-Methoden. P Zur Kontrolle geben Sie Vor- und Nachname der geänderten Person noch einmal auf dem Bildschirm aus. Nachdem Sie alle Änderungen vorgenommen haben, speichern Sie den geänderten Quellcode, übersetzen den Quellcode und bringen den Bytecode zur Ausführung. 1.3.2 Vererbung Die Vererbung stellt in der Objektorientierung eine Möglichkeit dar, Programmcode wiederzuverwenden. Damit eine Klasse von einer anderen Klasse etwas erben kann, muss man erst einmal zwei Klassen finden, die vieles gemeinsam haben und die beide innerhalb des Programmes eine eigene Bedeutung haben. Dies sei am Beispiel der Klasse Person und der Klasse Ausleiher erläutert. Ein Ausleiher ist eine Person, die einen Bibliotheksausweis besitzt. Diese Erkenntnis würde im ersten Schritt genügen, um zwischen der Klasse Person und der Klasse Ausleiher eine Vererbungsbeziehung (auch „is-a“-Beziehung genannt) einzuzeichnen. In der UML-Notation sieht dies wie folgt aus: Abbildung 8: Vererbungsbeziehung zwischen der Klasse Ausleiher und der Klasse Person Person Ausleiher Alle Datenfelder und Methoden, die für eine Person und einen Ausleiher identisch sind, gehören zur Klasse Person und jene Datenfelder und Methoden, die für den Ausleiher spezifisch sind, gehören zur Klasse Ausleiher. Die Gemeinsamkeiten befinden sich damit in der Vaterklasse (Superklasse, Basisklasse oder auch ableitende Klasse genannt) und die Spezifika in der Sohnklasse (Subklasse oder auch abgeleitete Klasse genannt). Kapitel 1 å JAV101 23 Die folgende UML-Darstellung zeigt exemplarisch gemeinsame Datenfelder und Methoden in der Klasse Person und spezifische Datenfelder und Methoden in der Klasse Ausleiher. Person String name String vorname Abbildung 9: Gemeinsamkeiten in der Vaterklasse und Spezifika in der Sohnklasse getName() getVorname() setName() setVorname() Ausleiher int ausleiherNummer getAusleiherNummer() setAusleiherNummer() Oft wird vergessen, sich die Frage zu stellen, ob die Klasse Person im Rahmen der Bibliotheksverwaltung überhaupt benötigt wird. Falls man zum Ergebnis kommt, dass im Rahmen der Bibliotheksverwaltung nur Ausleiher von Interesse sind, sollte man auch von der Vererbungsbeziehung keinen Gebrauch machen. Vererbungsbeziehungen, die nicht wirklich im Rahmen der Anwendung benötigt werden, erzeugen eine unnötige Komplexität. Die Klasse Ausleiher würde – ohne den Einsatz einer Vererbungsbeziehung – auch die Datenfelder und Methoden besitzen, die in Abbildung 9 der Klasse Person angehören. Bevor Sie sich die Frage stellen, warum Sie etwas lernen sollen, was Sie kaum einsetzen können, folgen jetzt die Einsatzbereiche, in denen die Vererbung eine sehr wichtige Rolle spielt. Die Vererbung ist bedeutsam bei der Konstruktion von Klassenbibliotheken. Je universeller eine Klassenbibliothek einsetzbar sein soll, desto häufiger findet sich die Vererbungsbeziehung in der Klassenbibliothek. Je spezifischer die Aufgabe ist, die durch ein Programm automatisiert werden soll, desto seltener ist die Vererbungsbeziehung zu finden – es sei denn, es soll eine Klassenbibliothek erstellt werden, die von anderen zur Erstellung von ähnlichen Anwendungen genutzt werden soll. Damit Sie Klassenbibliotheken in Ihre Programme einbinden können, müssen Sie zuerst deren Aufbau verstehen. Um den Aufbau einer objektorientierten Klassenbibliothek zu verstehen (einen Einblick in umfangreiche Klassenbibliotheken erhalten Sie in Kapitel 3), müssen Sie die Vererbungsbeziehung verstanden haben. Deshalb folgt ein einfaches Beispiel für die Vererbungsbeziehung anhand der Klassen Person und Ausleiher. Die Klasse Person haben Sie bereits in Kapitel 1.3.1 erstellt und in der Datei Person.java abgespeichert. Es wird also nur noch die Klasse Ausleiher und eine Testklasse TestAusleiher benötigt. Erstellen Sie die beiden Java-Quellcode-Dateien wie folgt und speichern Sie diese ebenfalls im Ordner beispiele ab. Kapitel 1 å JAV101 24 // Datei: Ausleiher.java public class Ausleiher extends Person { private int ausleiherNummer; public int getAusleiherNummer() { return ausleiherNummer; } public void setAusleiherNummer(int nummer) { ausleiherNummer = nummer; } } // Datei: TestAusleiher.java public class TestAusleiher { public static void main (String[] args) { Ausleiher a1 = new Ausleiher(); // Aufruf der geerbten Methoden für den Ausleiher. a1.setName ("Mustermann"); a1.setVorname ("Max"); a1.setAusleiherNummer (100); System.out.println (a1.getName() + " " + a1.getVorname()); System.out.println ("mit Nummer: " + a1.getAusleiherNummer()); } } Übersetzen Sie die beiden Quellcode-Dateien und bringen Sie die Klasse TestAusleiher zur Ausführung. Als Ausgabe erhalten Sie dann: Mustermann Max mit Nummer: 100 Die Wiederverwendung von Quellcode durch Vererbung ist in der Tat sehr einfach. Durch die Angabe von extends Person hinter dem Klassennamen Ausleiher in der Klassendeklaration können Sie den kompletten Programmcode der Klasse Person in der Klasse Ausleiher wiederverwenden. Für ein Objekt der Klasse Ausleiher können dann sowohl die geerbten Methoden der Klasse Student als auch die eigenen Methoden der Klasse Ausleiher aufgerufen werden. Im Zusammenhang mit der Vererbung stehen auch Begriffe wie Polymorphie und „Überschreiben von Methoden“. Diese Konzepte werden Sie später in Kapitel 2.6 kennenlernen. K [31] Kapitel 1 å JAV101 Erläutern Sie folgende Aussage: „Vererbungsbeziehungen sollten nicht überall eingeführt werden, wo diese möglich sind, sondern nur dort, wo diese auch tatsächlich benötigt werden.“ 25 1.3.3 Schnittstellen Objektorientierte Programme sollen eine höhere Wiederverwendbarkeit und Stabilität im Vergleich zu prozeduralen Programmen besitzen. Die höhere Wiederverwendbarkeit und Stabilität entsteht aber nur dann, wenn objektorientierte Programme durchdacht entworfen werden. Hierbei ist der Entwurf der sogenannten Schnittstellen von zentraler Bedeutung. Als Schnittstelle einer Klasse werden die nach außen sichtbaren Methoden bezeichnet. Bleibt die Schnittstelle einer Klasse – bei einer Änderung innerhalb der Klasse – stabil, so müssen aufgrund der Änderung keine weiteren Klassen angepasst werden. Die nach außen sichtbaren – das heißt die öffentlichen bzw. mit dem Schlüsselwort public gekennzeichneten Methoden – bilden die Schnittstelle einer Klasse. In Java erfolgt jedoch eine noch strengere Separierung der Schnittstelle von einer Klasse durch die Einführung eines Schnittstellen-Typs. Dies bedeutet, dass Methoden einer Klasse, die nach außen sichtbar sein sollen, in einem eigenen Schnittstellen-Typ beschrieben werden können. Schnittstelle einer Klasse In Java gibt es einen Schnittstellen-Typ. Stellen Sie sich Folgendes vor: In der Bibliotheksverwaltung sollen nicht nur Bücher, sondern auch Zeitschriften entliehen werden können. Sowohl Bücher als auch Zeitschriften sollen in einer Bestandsanzeige am Bildschirm ausgegeben werden können. Zeitschriften und Bücher sollen deshalb eine Methode besitzen, um den Titel, eine eindeutige Nummer und die Anzahl der in der Bibliothek geführten Exemplare auszugeben. Diese Anforderung von der Bestandsanzeige an die unterschiedlichen „Medien“ in der Bibliothek, könnte wie folgt in einer Schnittstelle formuliert werden: // Datei: Ausgebbar.java public interface Ausgebbar { // Titel, eindeutige Nummer und Anzahl ausgeben. public void ausgeben(); } Es wird hiermit eine Schnittstelle mit dem Namen Ausgebbar definiert, die den Methodenkopf einer Methode ausgeben() beinhaltet. In einer Schnittstelle befinden sich immer nur die Methodenköpfe. Die Implementierung der Methode befindet sich im vorliegenden Beispiel in den verschiedenen Medien – nämlich in der Klasse Buch und in der Klasse Zeitschrift: // Datei: Buch.java public class Buch implements Ausgebbar { private String titel; private String unterTitel; private String isbn; private int anzahlExemplare; // Konstruktor für die Klasse zur Initialisierung der // Datenfelder. public Buch (String t, String u, String i, int anzahl) { titel = t; Kapitel 1 å JAV101 26 unterTitel = u; isbn = i; anzahlExemplare = anzahl; } public void ausgeben() { System.out.println ("[Buch] " + titel + " mit ISBN: " + isbn + ", Bestand: " + anzahlExemplare); } } // Datei: Zeitschrift.java public class Zeitschrift implements Ausgebbar { private String titel; private String unterTitel; private String issn; private int anzahlExemplare; // Konstruktor für die Klasse zur Initialisierung der // Datenfelder. public Zeitschrift (String t, String u, String i, int anzahl) { titel = t; unterTitel = u; issn = i; anzahlExemplare = anzahl; } public void ausgeben() { System.out.println ("[Zeitschrift] " + titel + " mit ISSN: " + issn + ", Bestand: " + anzahlExemplare); } } In der Bestandsausgabe interessiert von den verschiedenen Medien in der Bibliothek nur, dass alle Medien die Schnittstelle Ausgebbar implementieren und damit eine individuelle Implementierung der Methode ausgeben() besitzen. In folgendem Testprogramm wird dies deutlich: // Datei: TestBestandsausgabe.java public class TestBestandsausgabe { public static void main (String args[]) { Ausgebbar ref1 = new Buch("Java als erste Programmiersprache", "Vom Einsteiger zum Profi", "978-3-8348-0656-7", 5); Ausgebbar ref2 = new Zeitschrift ("Informatik Spektrum", "Java Modeling Language", "0170-6012", 2); // Programmcode für die Bestandsausgabe ref1.ausgeben(); ref2.ausgeben(); Kapitel 1 å JAV101 27 } } Erstellen Sie den Quellcode für die Klassen Buch, Zeitschrift und TestBestandsausgabe, sowie für die Schnittstelle Ausgebbar, kompilieren Sie den Quellcode und bringen Sie die Klasse TestBestandsausgabe zur Ausführung. Als Ergebnis erhalten Sie folgende Ausgabe: [Buch] Java als erste Programmiersprache mit ISBN: 978-3-8348-0656-7, Bestand: 5 [Zeitschrift] Informatik Spektrum mit ISSN: 0170-6012, Bestand: 2 Zu den Besonderheiten im Programm: P In den Klassen Buch und Zeitschrift wurde erstmalig ein sogenannter Konstruktor geschrieben. Methoden in einer Klasse, die gleich heißen wie die Klasse selbst und keinen Rückgabetyp besitzen, sind sogenannte Konstruktoren. Ein Konstruktor wird automatisch aufgerufen, nachdem der new-Operator das Objekt im Speicher angelegt hat. Ein Konstruktor dient zum Initialisieren der Datenfelder. Einsatz von Konstruktoren zur Initialisierung P Mit Ausgebbar ref; wird eine Referenzvariable eines Schnittstellen-Typs angelegt. Von einem Schnittstellen-Typ können nur Referenzvariable angelegt werden, es können keine Objekte erzeugt werden. Eine Referenzvariable eines SchnittstellenTyps kann ausschließlich auf ein Objekt zeigen, dessen Klasse die Schnittstelle implementiert! Eine Referenzvariable vom Typ Ausgebbar kann im Beispiel also auf ein Objekt vom Typ Buch oder auf ein Objekt vom Typ Zeitschrift zeigen. Referenzvariable eines Schnittstellen-Typs Die Implementierung der Methode ausgeben() kann nun in den Klassen Buch und Zeitschrift geändert werden, ohne dass der Programmcode für die Bestandsausgabe angepasst werden muss. Dies gilt natürlich nur solange, wie die Schnittstelle Ausgebbar stabil – das heißt, unverändert – bleibt. Es können sogar neue Medien – wie beispielsweise eine Klasse DVD – hinzugefügt werden und der Programmcode für die Bestandsausgabe muss nicht geändert werden. Alle Medien müssen lediglich die Schnittstelle Ausgebbar implementieren. Sie werden im Laufe dieses Studienbriefs – nachdem Sie Schleifen und Arrays kennen gelernt haben – noch elegantere Implementierungen für die Bestandsausgabe kennenlernen, so dass die Vorteile dieser Vorgehensweise noch deutlicher in den Vordergrund treten. Beschreiben Sie, was man mit einer Referenzvariablen eines Schnittstellen-Typs machen kann. K [20] Recherchieren Sie, wie eine Schnittstelle in UML dargestellt wird. Finden Sie heraus, wie man in UML darstellen kann, dass eine Schnittstelle von einer Klasse implementiert wird. Zeichnen Sie als Ergebnis Ihrer Recherche ein UML-Diagramm, das die Klassen Buch, Zeitschrift sowie die Schnittstelle Ausgebbar zueinander in Beziehung setzt. K [5] Kapitel 1 å JAV101 28 1.3.4 Pakete Pakete dienen der Strukturierung des Programmcodes Pakete dienen der Strukturierung von Klassen und Schnittstellen und bilden damit die Grundlage für die Erstellung wiederverwendbarer Klassenbibliotheken. Ihr Programmcode sollte – wie auch ein jedes Dokument – eine gute Struktur bzw. eine gut durchdachte Gliederung besitzen. Die Struktur dient dazu, sich in einer großen Menge von Klassen und Schnittstellen besser zurechtzufinden. Bei einem Dokument ist es zielführend, auf eine logische Struktur zu achten. Dasselbe gilt auch für die Pakete: Logisch zusammengehörende Klassen und Schnittstellen werden in ein Paket „gepackt“. Darüber hinaus bieten Pakete die Möglichkeit, gezielt zu steuern, welche Klassen bzw. Schnittstellen eines Paketes nach außen sichtbar sind. Es sollten nur gut durchdachte Schnittstellen und wenige Klassen nach außen sichtbar sein. Damit besteht für den Programmierer eines Paketes die Möglichkeit, Änderungen innerhalb eines Paketes durchzuführen, ohne dass die Nutzer des Paketes ihren Programmcode anpassen müssen. Voraussetzung hierfür ist wiederum, dass die nach außen sichtbaren Schnittstellen eines Paketes stabil bleiben. Eine erste einfache Verwendung von Paketen soll anhand der Klassen Buch und Zeitschrift, sowie der Schnittstelle Ausgebbar aufgezeigt werden. Die beiden Klassen sowie die Schnittstelle sollen in ein Paket mit Namen entitäten „gepackt“ werden. Als Entität bezeichnet man in der Programmierung typischerweise ein datentragendes Objekt, dessen Daten persistent (dauerhaft) gespeichert werden müssen. Da Bücher und Zeitschriften innerhalb der Bibliotheksverwaltung mit Sicherheit persistent gespeichert werden müssen, scheint dieser Name im ersten Schritt zutreffend zu sein. Um eine Klasse bzw. eine Schnittstelle einem Paket hinzuzufügen, müssen Sie folgende Dinge tun: P Sie müssen ein Verzeichnis mit dem Paketnamen auf ihrem Rechner anlegen. P Sie müssen die Quellcode-Dateien der Klassen und Schnittstellen, die in das Paket „gepackt“ werden sollen, in dem entsprechenden Verzeichnis ablegen. P Sie müssen im Quellcode einer jeden Datei, die in das Paket „gepackt“ werden soll, eine entsprechende package-Deklaration hinzufügen. Für unser Beispiel bedeutet dies: P Legen Sie im Verzeichnis beispiele ein Unterverzeichnis entitäten an. P Verschieben Sie die Dateien Buch.java, Zeitschrift.java und Ausgebbar.java in das Unterverzeichnis entitäten. Löschen Sie die entsprechenden .class-Dateien aus dem Verzeichnis beispiele. P Öffnen Sie die drei Quellcode-Dateien und ergänzen Sie direkt unterhalb des ersten Kommentars die folgende package-Deklaration: package entitäten; Die Quellcode-Datei Buch.java beginnt dann beispielsweise wie folgt: // Datei: Buch.java package entitäten; public class Buch implements Ausgebbar ... Kapitel 1 å JAV101 29 Damit die Klasse TestBestandsausgabe, weiß, wo sich die Typen Buch, Zeitschrift und Ausgebbar befinden, wird die import-Vereinbarung benötigt. Öffnen Sie die Quellcode-Datei TestBestandsausgabe.java und ergänzen Sie ganz zu Beginn folgende import-Vereinbarung: // Datei: TestBestandsausgabe.java import entitäten.*; public class TestBestandsausgabe ... Danach öffnen Sie eine Eingabeaufforderung, wechseln in das Verzeichnis beispiele und übersetzen die Dateien mittels javac TestBestandsausgabe.java erneut. Nach erfolgreicher Umstrukturierung testen Sie die Klasse TestBestandsausgabe durch Aufruf des Interpreters java TestBestandsausgabe, um zu überprüfen, ob noch alles so funktioniert wie früher. Für welchen Zweck gibt es Pakete in Java? K [32] Erklären Sie, für welchen Zweck die package-Deklaration und die import-Vereinbarung benötigt werden. K [3] 1.3.5 Klassenbibliothek Pakete bilden in Java die Grundlage für die Erstellung von Klassenbibliotheken. Schnittstellen und Klassen, die in Paketen strukturiert sind und für die Verwendung in anderen Java-Programmen zur Verfügung gestellt werden, bilden eine Klassenbibliothek. Eine umfangreiche Java-Klassenbibliothek wird mit der Programmiersprache Java – im Rahmen des JDKs – ausgeliefert. Da Sie ein JDK auf Ihrem Rechner installiert haben, besitzen Sie auch eine umfangreiche Java-Klassenbibliothek. Der Bytecode für alle Klassen der Java-Klassenbibliothek, die Sie in Ihre eigenen Programme einbinden können, befindet sich in einem Archiv mit dem Namen rt.jar im Verzeichnis jdk1.7.0_xx\jre\lib. Was ist eine Klassenbibliothek in Java? Nun wäre es natürlich interessant zu wissen, welche Funktionalität durch die Java-Klassenbibliothek bereits zur Verfügung gestellt wird. Die Dokumentation für die JavaKlassenbibliothek finden Sie online im Internet unter folgendem Link: http://docs.oracle.com/javase/7/docs/api/index.html Damit Sie die Dokumentation jederzeit offline einsehen können, empfiehlt es sich, die komplette Dokumentation der Java-Klassenbibliothek in der Standard Edition auf Ihren Rechner herunterzuladen. Diese finden Sie auf der gleichen Seite im Internet wie das JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html Scrollen Sie auf der Seite so lange nach unten, bis Sie zur „Java SE 7 Documentation“ gelangen. Speichern Sie die gepackte Datei auf Ihrem Rechner und entpacken Sie diese in ein Verzeichnis Ihrer Wahl. Im Verzeichnis docs\api haben Sie nun direkten Bezugsquelle Dokumentation Java-Klassenbibliothek Kapitel 1 å JAV101 30 Zugriff auf die Dokumentation der Java-Klassenbibliothek, indem Sie die Datei index.html öffnen. Abbildung 10 zeigt einen Ausschnitt dieser Startseite für die Dokumentation der Java-Klassenbibliothek: Abbildung 10: Ausschnitt Startseite der Dokumentation der Java-Klassenbibliothek Suchen Sie das Paket java.lang in der Dokumentation der Java-Klassenbibliothek. Innerhalb des Paketes java.lang finden Sie beispielsweise die Klasse System, die Sie bereits für die Ausgabe auf dem Bildschirm mit System.out.println() eingesetzt haben. Bei der Dokumentationsseite der Klasse System finden Sie unter "Field Summary" die Klassenvariable out. Die Klassenvariable out ist vom Typ PrintStream. Durch Klicken auf den Typ PrintStream gelangen Sie zur Dokumentation der Klasse PrintStream. Dort finden Sie unter "Method Summary" die verschiedenen Ausprägungen der Methode println(), die Sie zur Ausgabe auf dem Bildschirm bereits verwendet haben. Der Datentyp String ist in Java eine Klasse, die sich ebenfalls im Paket java.lang befindet. Suchen Sie die Klasse String in der Java-Klassenbibliothek und verschaffen Sie sich einen Überblick über die bereitgestellten Methoden. Das Paket java.lang wird automatisch durch den Compiler eingebunden. Kapitel 1 å JAV101 Ohne es bislang zu wissen, haben Sie in Ihren Beispielprogrammen bereits zwei Klassen aus der Java-Klassenbibliothek verwendet. Beide Klassen befinden sich im Paket java.lang. Der aufmerksame Leser mag sich die Frage stellen, warum es dann nicht notwendig war, zu Beginn einer jeden Java-Quellcode-Datei, in welcher die Klassen String oder System verwendet wurden, mittels der import-Vereinbarung das Paket java.lang einzubinden. Dies liegt daran, dass das Paket java.lang – da es so häufig benötigt wird – automatisch durch den Compiler in die entsprechende Bytecode-Datei integriert wird. Diesen Automatismus gibt es allerdings nur für das Paket java.lang. Falls Sie auf Klassen oder Schnittstellen eines anderen Paketes aus der Java-Klassenbibliothek zugreifen wollen, müssen Sie hierfür die import-Vereinbarung verwenden. 31 P Eine Klasse wird in Java durch das Schlüsselwort class deklariert. P Der Compiler javac übersetzt eine Datei Name.java in die Java-BytecodeDatei Name.class. P Mit public gekennzeichnete Klassen bzw. Methoden sind öffentlich sichtbar und können von anderen Klassen verwendet werden. P Auf Datenfelder, die mit private gekennzeichnet sind, können nur die Methoden der eigenen Klasse zugreifen. P Ein Methodenaufruf erfolgt immer auf ein Objekt bezogen. P Es wird als guter Programmierstil angesehen, wenn man zum Test einer Klasse eine eigene Testklasse schreibt. P Die Ausführung einer Java-Anwendung beginnt mit dem Aufruf der Methode main(). Diese kann direkt – ohne die Existenz eines Objekts – durch den Interpreter aufgerufen werden. P In Java wird eine Referenzvariable benötigt, um auf Objekte zuzugreifen, die mithilfe des new-Operators im Speicher angelegt wurden. P Die Vererbung stellt eine Möglichkeit dar, Programmcode wiederzuverwenden. Klassen, die viel gemeinsam haben, können von einer gemeinsamen Vaterklasse abgeleitet werden. Diese Vaterklasse enthält dann die Gemeinsamkeiten, während die Sohnklassen die jeweiligen Spezifika enthalten. P Als Schnittstellen einer Klasse werden die nach außen sichtbaren Methoden bezeichnet. Diese Methoden können in Java in einem eigenen Schnittstellen-Typ beschrieben werden. P Pakete dienen der Strukturierung von Klassen und Schnittstellen. Sie bilden die Grundlage für die Erstellung von Klassenbibliotheken. Suchen Sie in der Dokumentation der Java-Klassenbibliothek die Klasse Scanner im Paket java.util. Schreiben Sie ein Programm in Java, das zwei Zahlen von der Tastatur einliest, diese addiert und das Ergebnis auf dem Bildschirm ausgibt. Für das Einlesen der Zahlen verwenden Sie bitte die Methode nextInt() der Klasse Scanner. Vervollständigen Sie den folgenden Coderahmen für das Programm: K [16] // Datei: EingabeTest.java import java.util.Scanner; public class EingabeTest { public static void main (String[] args) { Scanner eingabe = new Scanner (System.in); System.out.print ("Erste Zahl eingeben: "); int zahl1 = ... System.out.print ("Zweite Zahl eingeben: "); Kapitel 1 å JAV101 32 int zahl2 = ... int summe = ... System.out.println (zahl1 + " + " + zahl2 + " = " + summe); } } K [26] Kapitel 1 å JAV101 Arbeiten Sie die Beispielprogramme in (HEINISCH et al., 2010) aus Kapitel 4 durch. Nachdem Sie damit fertig sind, überprüfen Sie Ihre Programmierfähigkeiten durch die Übungen am Ende von Kapitel 4. Die Lösungen zu diesen Übungen finden Sie auf der CD, die dem Buch beigefügt ist.