Lese- und Lernhilfe Java für OO2026 (Entwurf, V. 2026/6/1)
| |
|
|
Copyright 2025, 2026 Prof. Dr. Josef L. Staud |
|
|
|
Autor: Josef L. Staud |
|
Umfang des gedruckten Textes: ca. 140 Seiten |
|
Dieser Text gibt Erläuterungen zu den Java-Beispielen in [Staud 2025]. Er stellt keine Einführung in Java dar, vgl. dazu die Bücher im Literaturverzeichnis, soll aber eine Beziehung zwischen den UML-Konstrukten und einer objektorientierten Programmiersprache herstellen. |
|
Diese HTML-Seiten wurden mit Hilfe eines von mir erstellten Programms erzeugt: WebGenerator2 (Version 2023). Es setzt Texte in HTML-Seiten um und wird ständig weiterentwickelt. Die "maschinelle" Erstellung erlaubt es, nach jeder Änderung des Textes diesen unmittelbar neu in HTML-Seiten umzusetzen. Da es nicht möglich ist, nach jeder Neuerstellung alle Seiten zu prüfen, ist es durchaus möglich, dass irgendwo auf einer "abgelegenen" Seite Fehler auftreten. Ich bitte dafür um Verzeihung und um Hinweise (hs@staud.info). |
|
Die Veröffentlichung im Web erfolgt ab 2022 in zwei Versionen: Mit und ohne Frame-Technologien. Zu meinem Bedauern wird die Frame-Technologie inzwischen von den Verantwortlichen als unerwünscht angesehen und es häufen sich die Hinweise, dass bestimmte Browser Frame-basierte Seiten nicht mehr korrekt interpretieren können. Deshalb habe ich eine zweite Version meines Programms WebGenerator erstellt, die ohne Frames realisiert ist. |
|
Urheberrecht |
|
Dieser Text ist urheberrechtlich geschützt. Die dadurch begründeten Rechte, insbesondere die der Übersetzung, des Nachdrucks, des Vortrags, der Entnahme von Abbildungen und Tabellen oder der Vervielfältigung auf anderen Wegen und der Speicherung in Datenverarbeitungsanlagen, bleiben, auch bei nur auszugsweiser Verwertung, vorbehalten. Eine Vervielfältigung dieses Textes oder von Teilen dieses Textes ist auch im Einzelfall nur in den Grenzen der gesetzlichen Bestimmungen des Urheberrechtsgesetzes der Bundesrepublik Deutschland vom 9. September 1965 in der jeweils geltenden Fassung zulässig. Sie ist grundsätzlich vergütungspflichtig. Zuwiderhandlungen unterliegen den Strafbestimmungen des Urheberrechtsgesetzes. |
|
Warenzeichen und Markenschutz |
|
Alle in diesem Text genannten Gebrauchsnamen, Handelsnamen, Marken, Produktnamen, usw. unterliegen warenzeichen-, marken- oder patentrechtlichem Schutz bzw. sind Warenzeichen oder eingetragene Warenzeichen der jeweiligen Inhaber. Die Wiedergabe solcher Namen und Bezeichnungen in diesem Text berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Gesetzgebung zu Warenzeichen und Markenschutz als frei zu betrachten wären und daher von jedermann benutzt werden dürften. |
|
|
|

|
|
|
|
Prof. Dr. Josef Ludwig Staud |
|
|
|
Vorwort, Inhalt, Abkürzungen
| |
Vorwort |
|
Der Gegensatz von Struktur und Verhalten ist in der IT (bei den Digitalisierungsbemühungen) allgegenwärtig. Denken wir nur Programme und Datenbanken. Oder an Geschäftsprozesse vs. Datenbanken. Für Struktur in diesem Sinne wurden vor Jahrzehnten ausgefeilte Datenbanktechniken entwickelt, die derzeit mit NoSQL-Datenbanken eine an die Anforderungen des Internetzeitalters angepasste Form gefunden haben. Für Verhalten in diesem Sinne wurden die Programmiersprachen entwickelt, die schon immer erlaubten, Verarbeitungsvorgänge zu erfassen (dafür wurden sie geschaffen), und die es heute erlauben, die Dynamik ganzer Geschäftsprozesse in Programmen darzustellen. |
Struktur und Verhalten |
In der UML 2.5 sind die Strukturaspekte betont, vgl. [Staud 2025]. Hier soll nun gezeigt werden, wie diese in Java umgesetzt werden können. |
|
|
|
Inhaltsverzeichnis der Druckversion |
|
Vorwort, Inhalt, Abkürzungen.. 2 |
|
1 Einleitung.. 8 |
|
1.1 Konzept 8 |
|
1.2 Bibliotheken. 8 |
|
1.3 Packages. 9 |
|
2 Grundlagen. 10 |
|
2.1 Datentypen. 10 |
|
2.2 Attribute. 10 |
|
2.3 Logische Operatoren. 11 |
|
3 Konsolenarbeit. 12 |
|
3.1 Ausgeben auf Konsole. 12 |
|
3.2 Lesen von der Konsole. 12 |
|
4 Klassen, Objekte, Methoden. 14 |
|
4.1 Klassen einrichten. 14 |
|
4.1.1 Grundlagen. 14 |
|
4.1.2 Sichtbarkeit 15 |
|
4.2 Objekte einrichten - Konstruktoren. 15 |
|
4.3 Record-Klassen. 17 |
|
4.4 Aufruf von Methoden und Attributen. 17 |
|
5 Prozedurales. 19 |
|
5.1 Schleifen und Verzweigungen. 19 |
|
5.2 Das Try/Catch-Konstrukt 20 |
|
6 Textdateien bearbeiten. 22 |
|
6.1 Paket java.io. 22 |
|
6.2 Zugriffe mit Streams. 22 |
|
6.3 Klasse File. 23 |
|
7 Exceptions. 26 |
|
8 Projekt HS1. 27 |
|
8.1 Klasse HP. 27 |
|
8.2 Klasse Stud. 29 |
|
8.3 Programmlauf 31 |
|
9 Projekt HS2. 33 |
|
9.1 Klasse HP. 33 |
|
9.2 Klasse Stud. 37 |
|
9.3 Beispielhafter Programmlauf 37 |
|
9.4 Anmerkungen zum Programm.. 38 |
|
10 Projekt HS3. 40 |
|
10.1 Klasse HP. 40 |
|
10.2 Klasse Stud. 44 |
|
10.3 Programmlauf 45 |
|
10.4 Beschreibung des Programms. 46 |
|
11 Projekt HS4. 48 |
|
11.1 Klasse HP. 48 |
|
11.2 Klasse Noten. 49 |
|
11.3 Klasse Stud. 50 |
|
11.4 Programmlauf 51 |
|
11.5 Beschreibung des Programms. 52 |
|
12 Projekt HS5. 54 |
|
12.1 Klasse HP. 54 |
|
12.2 Klasse Stud. 56 |
|
12.3 Beispielhafter Programmlauf 57 |
|
12.4 Anmerkungen zum Programm.. 57 |
|
13 Exkurs - Nachrichtenverkehr. 58 |
|
14 Projekt HS6. 59 |
|
14.1 Klasse HP. 59 |
|
14.2 Klasse Stud. 61 |
|
14.3 Beispielhafter Programmlauf 61 |
|
14.4 Projektbeschreibung. 62 |
|
14.5 Exkurs - Record vs. Klasse. 63 |
|
14.6 Exkurs - Methode hashCode() 64 |
|
15 Projekt HS7 - Vererbung, Attribute. 66 |
|
15.1 Klasse Fahrzeuge. 66 |
|
15.2 Klasse PKW... 67 |
|
15.3 Klasse LKW... 68 |
|
15.4 Klasse VAN.. 69 |
|
15.5 Klasse HP. 70 |
|
15.6 Programmlauf 75 |
|
15.7 Projektbeschreibung. 77 |
|
15.7.1 Ziel des Projekts. 77 |
|
15.7.2 Aufbau des Projekts. 77 |
|
15.7.3 Beschreibung der einzelnen Klassen. 78 |
|
15.7.4 Ablauf des Programms. 79 |
|
16 Projekt HS7a. 81 |
|
16.1 Klasse HP. 81 |
|
16.2 Klasse Fahrzeuge. 81 |
|
16.3 Klasse PKW... 81 |
|
16.4 Programmlauf 82 |
|
16.5 Exkurs: Override vs. Overload. 82 |
|
17 Projekt HS8 - Kapselung.. 84 |
|
17.1 Klasse HP. 84 |
|
17.2 Klasse Stud. 85 |
|
17.3 Programmlauf 87 |
|
17.4 Projektbeschreibung. 87 |
|
18 Projekt HS9. 89 |
|
18.1 Klasse HP. 89 |
|
18.2 Klasse Stud. 89 |
|
18.3 Klasse Noten. 90 |
|
18.4 Programmlauf 91 |
|
18.5 Erläuterungen zum Programm.. 91 |
|
19 Projekt hsdaten. 92 |
|
19.1 Klasse Erstellen. 92 |
|
19.2 Klasse Schreiben. 94 |
|
19.3 Klasse Schreiben2. 95 |
|
19.4 Klasse Lesen. 96 |
|
19.5 Klasse Anhaengen. 98 |
|
19.6 Klasse Loeschen. 100 |
|
19.7 Klasse ErzeugLoesch. 101 |
|
19.8 Klasse EinlesenCSV.. 104 |
|
20 Übungsaufgaben zu OOP mit Java. 108 |
|
20.1 Aufgabe 1 - Klasse und Objekt (HS1) 108 |
|
20.1.1 Aufgabe. 108 |
|
20.1.2 Lösung. 109 |
|
20.2 Aufgabe 2 - Referenzen. 109 |
|
20.2.1 Aufgabe. 109 |
|
20.2.2 Lösung. 110 |
|
20.3 Aufgabe 3 - Arrays. 110 |
|
20.3.1 Aufgabe. 110 |
|
20.3.2 Lösung mit Erläuterungen. 111 |
|
20.3.3 Lösung ohne Erläuterungen. 111 |
|
20.4 Aufgabe 4 - Mehrere Klassen. 111 |
|
20.4.1 Aufgabe. 111 |
|
20.4.2 Lösung. 113 |
|
20.4.3 Programmbeschreibung. 114 |
|
20.5 Aufgabe 5 - Eingabe. 115 |
|
20.5.1 Aufgabe. 115 |
|
20.5.2 Lösung. 116 |
|
20.6 Aufgabe 6 - Record. 116 |
|
20.6.1 Aufgabe. 116 |
|
20.6.2 Lösung. 118 |
|
20.6.3 Exkurs: Wiederholung zu records. 118 |
|
20.7 Aufgabe 7 - Vererbung. 119 |
|
20.7.1 Lösung. 120 |
|
20.7.2 Erläuterung. 121 |
|
20.8 Aufgabe 8 - Kapselung. 122 |
|
20.8.1 Aufgabe. 122 |
|
20.8.2 Lösung. 122 |
|
20.8.3 Erläuterung. 123 |
|
20.9 Aufgabe 9 - Overload. 124 |
|
20.9.1 Aufgabe. 124 |
|
20.9.2 Lösung. 124 |
|
20.9.3 Erläuterung. 126 |
|
21 Weitere Übungsaufgaben. 127 |
|
21.1 Aufgabe 10 - Erste Klasse und erstes Objekt 127 |
|
21.1.1 Aufgabenstellung. 127 |
|
21.1.2 Lösung. 127 |
|
21.2 Aufgabe 11 - Konstruktor 127 |
|
21.2.1 Aufgabenstellung. 127 |
|
21.2.2 Lösung. 128 |
|
21.3 Aufgabe 12 - Array von Objekten. 128 |
|
21.3.1 Aufgabenstellung. 128 |
|
21.3.2 Lösung. 128 |
|
21.4 Aufgabe 13 - Kapselung. 129 |
|
21.4.1 Aufgabenstellung. 129 |
|
21.4.2 Lösung. 129 |
|
21.5 Aufgabe 14 - Vererbung. 129 |
|
21.5.1 Aufgabenstellung. 129 |
|
21.5.2 Lösung. 129 |
|
21.6 Aufgabe 15 - Override. 130 |
|
21.6.1 Aufgabenstellung. 130 |
|
21.6.2 Lösung. 130 |
|
21.7 Aufgabe 16 - Polymorphie. 131 |
|
21.7.1 Aufgabenstellung. 131 |
|
21.7.2 Lösung. 131 |
|
21.8 Aufgabe 17 - Abstrakte Klasse. 132 |
|
21.8.1 Aufgabenstellung. 132 |
|
21.8.2 Lösung. 132 |
|
21.8.3 Exkurs - Abstrakte Klasse. 132 |
|
21.9 Aufgabe 18 - Interface. 133 |
|
21.9.1 Aufgabenstellung. 133 |
|
21.9.2 Lösung. 133 |
|
21.9.3 Exkurs - Interface. 133 |
|
21.10 Aufgabe 19 - Zusammenspiel mehrerer Klassen. 134 |
|
21.10.1 Aufgabenstellung. 134 |
|
21.10.2 Lösung. 134 |
|
21.10.3 Exkurs - Verknüpfung. 135 |
|
21.11 Aufgabe 20 - vom Klassendiagramm zu Java. 135 |
|
21.11.1 Aufgabe. 135 |
|
21.11.2 Lösung. 136 |
|
22 Literatur. 141 |
|
|
|
Abkürzungsverzeichnis |
|
| Abkürzung |
|
| API |
Application Programming Interface |
| HS |
Hochschule |
| IT |
Informationstechnologie/n |
| JDBC |
Java Database Connectivity |
| JDK |
Java Development Kit. OpenJDK |
| JRE |
Java Runtime Environment |
| KI |
Künstliche Intelligenz |
| OCL |
Object Constraint Language |
| OID |
Objektidentifizierer |
| RDBS |
Relationale Datenbanksysteme |
| UML |
Unified Modeling Language |
| VM |
Virtual Machine. Laufzeitumgebung. Java-Interpreter |
| |
|
|
|
|
|
|
1 Einleitung |
|
|
|
1.1 Konzept |
|
Wie oben schon ausgeführt, ist dieser Text ein Begleittext zu [Staud 2025], den man auf dieser Web-Seite in der Zeile darüber ansteuern kann und der wichtige Teile der UML 2.5 beschreibt. Dort sind einige Java-Programme eingefügt, die aufzuzeigen, wie wichtige Elemente der objektorientierten Theorie in einer objektorientierten Programmiersprache umgesetzt sind. Es geht also um die Umsetzung ausgewählter Konstrukte und Konzepte der objektorientierten Theorie in einer objektorientierten Sprache (dafür wurde Java gewählt) und somit um die Frage: |
Begleittext zu [Staud 2025]
(oben) |
Wie sind die objektorientierten Konzepte und Konstrukte der UML 2.5 in Java umgesetzt? |
|
In diesem Begleittext werden genau die Elemente von Java erläutert, die für das Verständnis obiger Programme notwendig sind. So sollte z.B. jemand, der objektorientierte oder prozedurale Programmiererfahrung hat, die Java-Programme in [Staud 2025] nachvollziehen können. |
|
Nicht verwirren lassen: In objektorientierten Programmen (im Gegensatz zu objektorientierten Datenbanken) wird unter Objekten auch die Zusammenstellung von Programmfragmenten für spezifische Aufgaben verstanden. Hier z.B. bei der Klasse File und vielen weiteren (z.B. den sog. Stromklassen, vgl. unten). Es sollten also inhaltlich bedeutsame Objektklassen (Angestellte, ihre Attribute und die mit ihnen zusammenhängenden Methoden) und programmtechnisch notwendige Klassen unterschieden werden. In Java ist dies besonders ausgeprägt. Die gesamte Anwendung besteht aus Klassen, d.h. es müssen auch Vorgänge wie Dateien einrichten/Löschen, in Dateien schreib en, aus Dateien lesen in das Klassen- und Objektkonzept abgebildet werden. Vgl. die Beispiele unten, zu letzterem v.a. die in hsdaten. |
Inhaltlich vs. programm-technisch |
Dies gilt auch für das Hauptprogramm (main), das aus objektorientierter Sicht eine statische Funktion ist. Auch dieses wird, vgl. die Beispiele unten, in eine eigene Klasse gepackt. |
Main |
Keine Einführung in Java |
|
Dieser Text ist keine Einführung in Java. Dafür gibt es umfassende Literatur, siehe z.B. die Literaturliste. Eine umfassende Darstellung, auch mit kleinen Beispielen, findet sich in der API-Dokumentation von Oracle: |
|
https://docs.oracle. com/en/java/java se/21/docs/api/java.base/java/util/regex/Pattern.html |
|
Sollte die Suchmaschine mit der langen Adresse nicht klarkommen, einfach mit |
|
https://docs.oracle.com/en/ |
|
beginnen und im Oracle-Menü weitergehen. |
|
1.2 Bibliotheken |
|
Wie in den Beispielen zu sehen ist, sind in Java viele der benötigten Programmleistungen in Bibliotheken ausgelagert, die bei Bedarf importiert werden können. Zum Beispiel so: |
|
|
import javax.swing.JOptionPane;
|
|
Die wichtigste ist die Java-Standardbibliothek. Ihre einzelnen Pakete (vgl. unten) sind hierarchisch in einer Baumstruktur angeordnet. Die Wurzel ist java, bzw. javax. Danach folgen z.B.: |
|
- java.awt (Abstract Windowing Toolkit). Klassen zur Arbeit mit grafischen Oberflächen.
- java.math. Paket für mathematische Methoden.
- java.util. "Bietet Typen für Datenstrukturen, Raum und Zeit sowie für Teile der Internationalisierung sowie für Zufallszahlen." [Ullenboom 2024, S. 1579]. In den Beispielen hier wird die Klasse java.util.Scanner sehr oft benötigt.
- java.sql und javax.sql. Zur Arbeit mit relationalen Datenbanksystemen.
- java.io und java.nio. "Möglichkeiten zur Ein- und Ausgabe. Dateien werden als Objekte repräsentiert. Datenströme erlauben den sequentiellen Zugriff auf Dateiinhalte." [Ullenboom 2024, S. 1578].
- java.lang. Dieses Paket ist automatisch eingebunden. Enthält u.a. die String-Klasse, die oft benötigt wird.
- javax.swing. Stellt Komponenten für grafische Oberflächen zur Verfügung. Hier wird javax.swing.JoptionPane oft genutzt.
|
|
1.3 Packages |
|
Für die Programmerstellung und -ausführung werden neben dem Java-Compiler eine Vielzahl von Programmbibliotheken benötigt. Diese sind in Paketen organisiert. Pakete bestehen aus inhaltlich zusammenhängenden Klassen für bestimmte Aufgaben, z.B. Bildschirmeingabe, Dateibearbeitung, mathematische Aufgaben. Diese Pakete und/oder Klassen werden mittels Import-Befehlen zum jeweiligen Programm dazugeladen. Vgl. die Programme unten. |
|
Auch die Quellcodedateien eines Projekts werden in Packages zusammengefasst. Entweder durch einen Befehl in der ersten Zeile des Quellprogramms oder, falls dies unterbleibt, in einem default package. Vgl. die Programme unten. |
|
2 Grundlagen |
|
In den Beispielen wird meist der Anwendungsbereich Hochschule gewählt. Abgekürzt mit HS. Klassen sind dann z.B. Studierende (Stud), Attribute sind matrikelNr, name, vName, usw. Siehe die Programmbeispiele unten. |
|
|
|
2.1 Datentypen |
|
Die Datentypen in Java können wie folgt unterschieden werden: |
|
- Elementare Typen: Die elementaren (primitiven) Typen sind in Java eingebaute Datentypen für Zahlen, Unicode-Zeichen und Wahrheitswerte.
- Referenztypen: Mit diesen lassen sich Objektverweise etwa auf Zeichenketten, Datenstrukturen, usw. realisieren.
|
|
Die hier verwendeten elementaren Datentypen von Java sind die Folgenden: |
|
Ganzzahlen |
|
- Byte (Länge 8 Bit)
- Short (16 Bit)
- Int (32 Bit)
- Long ( 64 Bit)
|
|
Fließkommazahlen |
|
- Float (32 Bit)
- Double (64 Bit)
|
|
Sonstige Datentypen |
|
- Boolean (1 Bit)
- Char (16 Bit)
|
|
Nicht-elementare Datentypen |
|
Strings |
|
Sie spielen eine wichtige Rolle, sind aber keine elementaren Datentypen, sondern Verweise auf Objekte. |
|
Arrays |
|
Ein Array (auf deutsch Feld) ist ein Datentyp, der mehrere gleich definierte Werte (Attributsausprägungen, Objekte, ...) zu einer Einheit zusammenfasst. Z.B. mit elementaren Datentypen, aber auch mit komplexeren. In Projekt HS3 wird ein Array genutzt, um zufällig generierte Objekte zu verwalten. Soll das Array mehrdimensional sein, wird an jeder Position des Array ein weiteres Array gespeichert. |
|
2.2 Attribute |
|
Instanzenattribute |
|
In der objektorientierten Theorie sind Attribute meist mit Objekten (Instanzen) verknüpft. Da bedeutet z.B. |
|
|
s100.name
|
|
|
s100.vName
|
|
|
s100.anzSem
|
|
|
s100.gebTag
|
|
dass es eine Klasse Stud (Studierende) gibt mit einer Studierenden (einem Objekt, einer Instanz) s100 und den Attributen name, vName, anzSem (Anzahl Semester) sowie gebTag (Geburtstag) gibt. Der jeweilige Datentyp wird in der Klassendefinition festgelegt. Vgl. Projekt HS5. |
|
Natürlich kann solch ein Instanzenattribut auch im Programm beschrieben werden. Die Variable ii soll hier die Semesteranzahl darstellen. |
|
|
S100.anzSem = ii;
|
|
Die Bedeutung ist wie folgt: das Attribut anzSem (Anzahl Semester) von Objekt s100 erhält den Wert ii. |
|
Klassenattribute |
|
Wie in der UML vorgesehen, kennt Java auch Klassenattribute. Deren Attributsausprägungen beziehen sich auf die jeweilige Klasse als Ganze. In den Beispielen unten wird das Klassenattribut anzSem (Anzahl Semeseter)sehr oft eingesetzt. |
|
|
static int anzStud = 0;
|
|
Obiges ist dann die Deklaration eines Klassenattributs mit Anfangswert. |
|
Variablen |
|
Der Umgang mit Variablen entspricht weitgehend dem der prozeduralen Programmiersprachen. Die folgenden Situationen kommen in den Beispielprogrammen vor: |
|
|
int i = 0; //Integer-Variable
|
|
|
short ii = (short) i; //Umwandlung integer in short integer
|
|
|
boolean fertig = false; //boolesche Variable
|
|
2.3 Logische Operatoren |
|
In den Beispielen werden vereinzelt auch die logischen Operatoren benötigt. Ihre Notation weicht nicht von der üblichen ab: |
|
- Nicht (!)
- Und (zwei kaufmännische Und)
- Oder (||)
- XOR (^)
|
|
3 Konsolenarbeit |
|
|
|
3.1 Ausgeben auf Konsole |
|
Die Ausgabe von Daten auf der Konsole erfolgt mit dem Befehl System.out.print in seinen Varianten, z.B.: |
|
|
System.out.print("Matrikelnummer: "); //ohne Zeilenvorschub
|
|
|
System.out.println(); //mit Zeilenvorschub
|
|
|
System.out.printf("MNr: " + mNr);
|
|
Printf bedeutet: als erstes wird ein String verlangt, dann können beliebig viele weitere Übergabewerte folgen. Vgl. [Ullenboom 2024, S. 471]. |
|
Die Ausgabe von Objektdaten auf der Konsole erfolgt entsprechend: |
|
|
System.out.println(stud.matrikelNr);
|
|
|
System.out.println(stud.vName + " " + stud.name);
|
|
|
System.out.println(stud.plz + " " + stud.ort);
|
|
|
System.out.println(stud.strasse + " " + stud.hausnummer);
|
|
Oben: Das Objekt stud mit einigen seiner Attribute. Vgl. zur Klasse Stud die Programme unten, z.B. HS1. |
|
3.2 Lesen von der Konsole |
|
Mit java.util.scanner |
|
Für das Lesen von der Konsole (z.B. Benutzerangaben) gibt es unterschiedliche Varianten. Die einfachste ist die mit der Klasse java.util.Scanner. Eine einfache zeilenweise Konsoleneingabe mit Einlesen der Eingabe in eine Variable kann mit ... |
|
|
java.util.Scanner(System.in)
|
|
realisiert werden. Der Quellcode sieht dann z.B. so aus (vgl. HS5): |
|
|
...
|
|
|
System.out.println("Objekt eingeben (j/n): ");
|
|
|
String s = new java.util.Scanner(System.in).nextLine();
|
|
|
|
|
|
switch(s) {
|
|
|
case "j":
|
|
|
System.out.println("Eingabe:");
|
|
|
System.out.print("Matrikelnummer: ");
|
|
|
int mNr = new java.util.Scanner(System.in).nextInt();
|
|
|
...
|
|
Auf dem Bildschirm ergibt sich das mit Windows 11 wie folgt: |
|

|
|
Weitere Beispiele |
|
|
String e1 = new java.util.Scanner(System.in).nextLine();//String einlesen
|
|
|
int int i = new java.util.Scanner(System.in).nextInt();
|
|
|
double dd = new java.util.Scanner(System.in).nextDouble();//Datentyp double einlesen
|
|
Zu beachten ist die zum Datentyp passende Methodenbezeichnung. |
|
Mit dem Swing-Paket |
|
Das Swing-Paket erlaubt grafisch gestaltete Eingabefenster. Im Quellcode muss folgendes eingegeben werden: |
|
|
import javax.swing.JOptionPane;
|
|
... |
|
|
String eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Ihre Wahl");
|
|
Dann sieht das Eingabefenster so aus: |
|

|
|
Varianten: |
|
|
eingabe = JOptionPane.showInputDialog("Welcher Student (0 / 1)?");
|
|
|
int nr = Integer.parseInt(eingabe);
|
|
Dabei liefert parseInt die Umwandlung der Stringvariablen in eine Integervariable. |
|
Anmerkung |
|
Diese Option steht nur zur Verfügung, falls in Eclipse das module-info.java eingerichtet ist: |
|

|
|
In der Datei steht, bei diesem Beispiel und im einfachsten Fall: |
|
|
/**
|
|
|
*
|
|
|
*/
|
|
|
/**
|
|
|
*
|
|
|
*/
|
|
|
module HS1 {
|
|
|
requires java.desktop;
|
|
|
}
|
|
4 Klassen, Objekte, Methoden |
|
Hier nun ein Blick auf das Einrichten von Klassen, das Instanziieren von Objekten und den Einsatz von Methoden. |
|
|
|
4.1 Klassen einrichten |
|
4.1.1 Grundlagen |
|
Mit Angabe der Attribute (Instanzvariablen) und dem Standardkonstruktor, einfachste Form (vgl. HS2, Stud.java): |
|
|
public class Studierende {
|
|
|
public String matrikelNr;
|
|
|
public String name;
|
|
|
public String vName; //Vorname
|
|
|
public String plz;
|
|
|
public String ort;
|
|
|
public String strasse;
|
|
|
public int hausnummer;
|
|
|
}
|
|
Mit Instanzattributen, einem Klassenattribut, einem ausgewiesenen Konstruktor und einer Methode (vgl. HS1, Stud.java): |
|
|
public class Stud { //Beginn der Klassendefinition
|
|
|
public int mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName; //Vorname
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
|
|
|
Klassenattribut/statisches Attribut mit Anfangswert. Static bedeutet: Es ist ein Klassenattribut. D.h. seine Attributsausprägungen beziehen sich auf die Klasse als Ganzes, nicht auf einzelne Objekte. Programmiertechnisch bedeutet dies, dass seine Werte ohne Objektaufruf bearbeitet und aufgerufen werden können. |
|
|
static int anzStud = 0
|
|
|
|
|
Konstruktor, bei dem das Klassenatttribut für die Anzahl der Objekte der Klasse hochgezählt wird. |
|
|
public Stud () {
|
|
|
anzStud++;
|
|
|
}
|
|
|
|
|
Instanzmethode zum Ausgeben der Daten eines Objekts: |
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
4.1.2 Sichtbarkeit |
|
Wie in der UML vorgesehen, kann auch in Java der Zugriff auf die Attribute und Methoden einer Klasse durch Sichtbarkeitsmodifizierer kontrolliert werden: |
Modifier |
- Public (öffentliches Attribut, öffentliche Variable, öffentliche Methode) bedeutet, auf die Klasse kann vom Paket aus, von abgeleiteten Klassen und von außerhalb zugegriffen werden.
- Protected (internes Attribut, interne Variable, interne Methode) bedeutet, es kann vom Paket aus und von von abgeleiteten Klassen zugegriffen werden.
- Paketsichtbar (package-private) ist eingestellt, falls kein Modifizierer angegeben wird. Diese Sichtbarket bedeutet, dass nur von anderen Klassen im gleichen Paket auf die Klasse zugegriffen werden kann.
- Private (privates Attribut, private Variable, private Methode) bedeutet, es kann nur innerhalb der Klasse zugegriffen werden.
|
|
Damit ist auch ein zentrales Anliegen der objektorientierten Theorie, die Möglichkeit der Methoden- und Datenkapselung, erfüllt. Daten, die auf Attributen/Variablen beruhen, und Methoden sollten nicht unberechtigt geändert bzw. aufgerufen werden können. Die Modifier Protected und Private erlauben dies in adäquater abgestufter Form. |
Kapseln |
Das Ganze wird noch verfeinert durch die Getter- und Setter-Methoden, die sozusagen trotz Kapselung den Zugriff über definierte Methoden erlauben: |
Getter, Setter |
- Eine Getter-Methode erlaubt trotz Zugriffsbeschränkungen den Zugriff auf die aktuelle Attributsausprägung eines Objekts.
- Eine Setter-Methode erlaubt trotz Zugriffsbeschränkungen das Beschreiben einer Attributsausprägung eines Objekts.
|
|
Beidesmal über Methoden, die bei der Klasse definiert sein müssen. Betrachten wir beispielhaft eine Klasse Stud (Studierende), wie sie unten in den Programmen sehr häufig vorkommt: |
Vgl. auch Projekt HS8 |
|
public class Stud {
|
|
|
public String mNr; //Matrikelnummer
|
|
|
private String name;
|
|
... |
|
Hier soll der Namen mit private gekapselt sein. Bei der Klasse werden dann die Getter- und Setter-Methoden in einfachster Form so hinterlegt: |
|
|
//Getter
|
|
|
public String getName(){
|
|
|
return name;
|
|
|
}
|
|
|
//Setter
|
|
|
public void setName(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
Dann kann im Hauptprogramm (also im selben Paket) der Name mit den Methoden getName() bzw. setName() gelesen oder überschrieben werden. Vgl. Projekt HS8. |
|
Pakete: Zusammenfassung der Klassen eines Projekts. Vgl. die Programme unten. Das Schlüsselwort ist package, die Deklaration erfolgt in der ersten Zeile des Programms, z.B. mit package hochschule. |
|
4.2 Objekte einrichten - Konstruktoren |
|
Hier einige Beispiele für Konstruktoren aus den folgenden Programmen. |
|
(1) Der Standardkonstruktor (vgl. HS4), der automatisch aufgerufen wird: |
|
|
Noten n1 = new Noten();
|
|
n1 ist die Bezeichnung des neuen Objekts. |
|
(2) Ein Konstruktor mit einer Klassenvariablen, die bei jeder Objekterzeugung hochgezählt wird (anzStud = Anzahl Studierende): |
|
|
public Stud () {
|
|
|
anzStud++;
|
|
|
}
|
|
(3) Der Standardkonstruktor mit anschließendem Beschreiben des Objekts: |
|
|
public class HS2 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s0 = new Stud(); //Aufruf Konstruktor
|
|
|
s0.mNr = 12345;
|
|
|
s0.name = "Sauer";
|
|
|
s0.vName = "Otto";
|
|
|
s0.anzSem = 5;
|
|
|
s0.gebTag = "21.09.2002";
|
|
|
|
|
(4) Instanziierung mit Beschreiben des Objekts beim Aufruf des Konstruktors (vgl. HS4, HP): |
|
Aufruf im HP: |
|
|
Stud s0 = new Stud("1111", "Maier", "Klara", 5, "21.09.2002");
|
|
Konstruktor in Klasse Stud: |
|
|
public Stud (String mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
anzStud++;
|
|
|
}
|
|
Zu beachten ist das keyword this, das die Zuordnung der Parameterwerte auf die Attribute des Objektes realisiert. |
|
(5) Verschachtelte Konstruktoren: |
|
|
stud1 = new BufferedReader (new FileReader("C:/Meine Dateien/" + dateiBez + ".txt"));
|
|
Der eine Konstruktor ist Parameter im anderen. Näheres dazu in Abschnitt 6.1. |
|
Abschließend noch das Einlesen von Objektdaten von der Konsole: |
|
|
eingabe = JOptionPane.showInputDialog("Matrikelnummer:");
|
|
|
stud.matrikelNr = eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Name:");
|
|
|
stud.name = eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Vorname:");
|
|
|
stud.vName = eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Postleitzahl:");
|
|
|
stud.plz = eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Ort:");
|
|
|
stud.ort = eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Straße:");
|
|
|
stud.strasse = eingabe;
|
|
|
eingabe = JOptionPane.showInputDialog("Hausnummer: ");
|
|
|
stud.hausnummer = Integer.parseInt(eingabe);
|
|
Klasse Stud mit Objekt stud (vgl. HS1). Mit Einlesen von Konsole. |
|
4.3 Record-Klassen |
|
Java erlaubt die Anlage von sog. Record-Klassen, die wohl von den Datensätzen (records) relationaler Datenbanken motiviert sind. Sie erlauben (für entsprechende Daten) eine schlankere Programmierung, v.a., weil sie eine schlankere Syntax aufweisen und weil einige Methoden gleich bei der Einrichtung durch den Konstruktor angelegt werden. |
Vgl. das Beispiel in Projekt HS6 |
Die Besonderheiten: |
|
- Record-Klassen verwalten für ihre Objekte nur Attribute (hier auch Record-Komponenten genannt).
- Ihre Objekte sind unveränderlich.
- Die Deklaration erfolgt mit dem Schlüsselwort record. Vgl. für die sonstige Syntax das Beispiel in Projekt HS6.
- Ihr Konstruktor übergibt in einer Parameterliste die Attributsausprägungen.
- Er erzeugt die Methoden equals(), toString() und hashCode(). Falls nötig, können sie verändert werden. Weitere Methoden können hinzugefügt werden.
- Für jedes Attribut wird automatisch eine Abfragemethode erstellt.
- Es gibt Schnittstellen, aber keine Vererbung
|
|
Die Methode equals() wird zum Vergleich von records verwendet. Sie sieht zwei records als gleich an, wennn sie vom gleichen Typ sind und falls jede Komponente denselben Wert hat. Dies leistet hier der Gleichheitsoperator nicht. |
|
Der Zugriff auf die Instanzvariablen erfolgt über Methoden mit derselben Bezeichnung wie das jeweilige Attrbut. Gibt es also ein Attribut name, steht die Methode name() zur Verfügung. |
|
Das Beispiel in HS6 stellt dieses Programmierkonstrukt dar. |
|
Vgl. [Ullenboom 2024, S. 897], [Kofler 2023, S. 220f] und [Habelitz 2025, S. 387] für weitergehende Beschreibungen. |
|
4.4 Aufruf von Methoden und Attributen |
|
Hier wird gezeigt, wie der Aufruf von Methoden und Attributen in Java geregelt ist. |
|
(1) Aufruf einer Instanzmethode aus dem HP heraus (HS2): |
|
|
public class HS2 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s0 = new Stud();//Standardkonstruktor
|
|
|
s0.mNr = 12345;
|
|
|
s0.name = "Sauer";
|
|
|
s0.vName = "Otto";
|
|
|
s0.anzSem = 5;
|
|
|
s0.gebTag = "21.09.2002";
|
|
|
System.out.println("\n------\n");
|
|
|
|
|
|
s0.ausgeben();
|
|
|
|
|
In Klasse Stud von HS1 wurde die Methode wie folgt angelegt: |
|
|
public class Stud {
|
|
|
.....
|
|
|
//Methode zum Ausgeben der Daten eines Objekts
|
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
(2) Aufruf eines Attributs (Variablen) einer anderen Klasse (HS4): |
|
|
System.out.println("\nAusgabe der Noten in Klasse HS4:");
|
|
|
System.out.println("Matrikelnummer: " + s1.mNr + "\nName: " + s1.name + "\nVorname: " + s1.vName + "\nFach: " + n1.fach + "\nNote: " + n1.note);
|
|
Mit Objektbezeichnung und Attributsname, verknüpft durch einen Punkt, wird die jeweilige Attributsausprägung angefordert. |
|
Das führt zu folgender Ausgabe: |
|

|
|
5 Prozedurales |
|
Java soll umfassend objektorientert sein. Es gibt nur Klassen, auch das Hauptprogramm ("main") soll in eine Klasse gepackt werden. Aber auch eine solche Programmiersprache benötigt prozedurale Komponenten, wenn es um die Realisierung von Methoden geht, um die dynamischen Aspekte der Anwendung. Es sind die üblichen von C und anderen prozeduralen Sprachen bekannten Konstrukte. Deren Ausprägung in Java wird hier kurz vorgestellt. |
|
|
|
5.1 Schleifen und Verzweigungen |
|
Eine While-Schleife mit enthaltener Switch-Verzweigung von Projekt HS2: |
|
|
boolean fertig = false;
|
|
|
while (!fertig) {
|
|
|
System.out.println(" ");
|
|
|
System.out.println("1 = Eingabe");
|
|
|
System.out.println("2 = Ausgabe");
|
|
|
System.out.println("3 = StudDaten wechseln");
|
|
|
System.out.println("4 = Programm beenden");
|
|
|
eingabe = JOptionPane.showInputDialog("Ihre Wahl");
|
|
|
int auswahl = Integer.parseInt(eingabe);
|
|
Oben: Menü auf der Konsole. Lesen der Nutzereingabe. |
|
|
|
|
|
switch(auswahl) {
|
|
Beginn der Switch-Verzweigungen, wie man es kennt mit case x und break. |
|
|
case 1:
|
|
|
eingabe = JOptionPane.showInputDialog("Matrikelnummer:");
|
|
|
stud.matrikelNr = eingabe;
|
|
|
.....
|
|
|
break;
|
|
|
case 2:
|
|
|
System.out.println(stud.matrikelNr);
|
|
|
System.out.println(stud.vName + " " + stud.name);
|
|
|
System.out.println(stud.plz + " " + stud.ort);
|
|
|
System.out.println(stud.strasse + " " + stud.hausnummer);
|
|
|
break;
|
|
|
case 3:
|
|
|
eingabe = JOptionPane.showInputDialog("Welcher Student (0 oder 1)?");
|
|
|
int nr = Integer.parseInt(eingabe);
|
|
|
|
|
Verzweigung mit if/else. |
|
|
if (nr == 0) {
|
|
|
stud = stud0;
|
|
|
}
|
|
|
else if (nr ==1) {
|
|
|
stud = stud1;
|
|
|
} else {
|
|
|
System.out.println("Eingabefehler!");
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case 4:
|
|
|
fertig = true;
|
|
|
break;
|
|
|
default:
|
|
|
System.out.println("Eingabefehler!");
|
|
|
}
|
|
|
}
|
|
Vgl. für weitergehende Informationen die Projektbeschreibung unten (HS2). |
|
5.2 Das Try/Catch-Konstrukt |
|
In Java wird ein Programmierkonstrukt angeboten, das kurz so beschrieben werden kann: Der Konstrollfluss wird unterteilt in einen Abschnitt mit dem gewünschten Ablauf ("try") und einen, der im Fehlerfall bei Laufzeitfehlern aktiv wird ("catch"). |
|
Der Try-Block kann unterschiedlich lang sein. Auch sehr kurz, z.B. für einen Einlesevorgang mit While-Schleife (hsdaten/Klasse Lesen) oder eine Arbeit mit dem Dateisystem, wie in hsdaten/Schreiben. Natürlich muss es ein zusammenhängender Abschnitt sein, so dass die Fehlermeldung im Catch-Block aussagekräftig ist. |
Vgl. die Beispiele im Projekt
hsdaten. |
Die folgende Abbildung erläutert die Syntax am Beispiel eines Programmfragments von hsdaten/Erstellen.java. Mit try und catch werden die beiden Abschnitte getrennt. Im Try-Block findet sich ein Programmabschnitt, bei dem eine Datei in einem bestimmten Verzeichnis (hier unter Windows) eingerichtet werden soll. Der Fehler, dass die Datei bereits existiert, wird direkt im Programm abgefangen und dem Nutzer gemeldet. Eventuelle Laufzeitfehlermeldungen werden im Catch-Block ausgeführt. Dies sind erstmal vordefinierte Meldungen, die aber spezifiziert werden können. Vgl. Kapitel 7 und die dort gegebenen Hinweise. |
|

|
|
Abbildung 5.2-1: Das Try/Catch-Konstrukt in Java. |
|
Vgl. Kapitel 9 in [Habelitz 2025] für eine weitergehende Beschreibung. Für zahlreiche Beispiele vgl. die Projekte unten, v.a. hsdaten. |
|
6 Textdateien bearbeiten |
|
|
|
6.1 Paket java.io |
|
Die gesamte für die Arbeit mit Dateien notwendige Funktionalität ist im Paket java.io vorhanden. Davon werden hier nur die Lese- und Schreibvorgänge mit TXT-Dateien benötigt. Es geht also um Eingabeströme (Eingeben in die Datei) und Ausgabeströme (Lesen aus der Datei). Außerdem um das Einrichten und Arbeiten mit Verzeichnissen und Dateien. |
Vgl. die Abbildung unten. |
Die benötigten Komponenten von java.io müssen im jeweiligen Programm importiert werden. Entweder als Ganzes mit |
|
|
Import java.io.*
|
|
oder über die Klassen, z.B: so: |
|
|
import java.io.BufferedReader;
|
|
|
import java.io.FileReader;
|
|
|
import java.io.FileWriter;
|
|
Zu den Klassen vgl. unten. |
|
6.2 Zugriffe mit Streams |
|
Bei den Eingabe- und Ausgabeströmen bzgl. Textdateien wird zwischen Character Streams und Byte Streams unterschieden: |
|
- Character Streams bestehen aus 16-Bit-Einheiten mit Char-Zeichen, kodiert nach Unicode.
- Byte Streams bestehen aus 8-Bit-Einheiten mit dem Datentyp Byte.
|
|
Die Basisfunktionalität wird durch abstrakte Klassen bereitgestellt. Dies sind Reader und Writer für Character Streams und InputStream sowie ExportStream für Byte Streams. Die eigentliche Arbeit leisten dann davon abgeleitete Klassen, die jeweils in ihrer Bezeichnung die der abstrakten Klasse enthalten. Zum Beispiel: |
|
- BufferedInputStream
- BufferedReader
- BufferedWriter
- FileWriter
- FileReader
|
|
6.3 Klasse File |
|
Die abstrakte Klasse File aus dem Paket java.io stellt die für den Umgang mit Dateien und Verzeichnissen benötigte Funktionalität zur Verfügung. Ein Objekt dieser Klasse repräsentiert jeweils ein Verzeichnis oder eine Datei. Im Fall von Dateien enthält das Objekt Daten wie Bezeichnung, Pfad, Größe, usw., nicht aber die Inhalte der Datei. |
File |
Eine wichtige der Klasse File zugeordnete Methode ist createNewFile(). Vgl. [hsdaten, Erstellen.java]. Mit dem Konstruktor |
|
|
Public File(String pathname)
|
|
wird ein Objekt von File im angegebenen Zugriffspfad eingerichtet. |
|
Die davon abgeleiteten Klassen tragen auch hier in ihrer Bezeichnung die der abstrakten Klasse. Zum Beispiel: |
|
- FileWriter. Richtet ein Objekt ein, mit dem in Dateien geschrieben werden kann. Es stellt die Verbindung her zu einer Datei aus dem Dateisystem des jeweiligen Rechners. Wichtige Methoden dieser Klasse sind write(), close().
- FileReader. (vgl. hsdaten/Lesen.java). Dessen "Objekte" stellen eine Verbindung zu einer Datei her, so dass ein zeilenweiser Lesezugriff ermöglicht wird.
- BufferedReader. Liest mit seiner Methode readLine() zeilenweise aus einer vom FileReader bereitgestellten Datei. Wenn das Ende der Datei erreicht ist, liefert readLine() als Ergebnis null.
- BufferedWriter. Liefert einen Eingabestrom, der "gepuffert" Unicode-Zeichen schreibt.
|
|
"Gepuffert" (buffered) meint hier, das der Ein- und Ausgabestrom nicht direkt ausgeführt wird. Die Daten werden also nicht zeitgleich mit der Lese- oder Schreibanweisung ausgeführt, sondern in einen Puffer geschrieben und erst transportiert, wenn der Puffer voll ist oder der Stream geschlossen wird. |
|
Beispiele |
|
hsdaten, Schreiben.java |
|
|
String dateiBez = "stud003";
|
|
|
stud1 = new FileWriter("C:/Meine Dateien/" + dateiBez + ".txt");
|
|
|
String text = "Sinnspruch Nummer 3\n"
|
|
|
+ "Der Weg ist weit, der Weg ist lang,"
|
|
|
+ " doch uns wird - wie immer - nicht bang";
|
|
|
stud1.write(text);
|
|
|
stud1.close();
|
|
Erläuterung: |
|
- Im obigen Beispiel wird zuerst die Dateibezeichnung in eine String-Variable geschrieben.
- In der zweiten Zeile wird ein Objekt der Klasse FileWriter erzeugt mit den Angaben zum Verzeichnis und zur Datei.
- Dann wird die Stringvariable text beschrieben
- Anschließend wird mit der Instanzmethode write() in das Objekt stud1 der Text der String-Variablen geschrieben.
- Abschließend wird das Objekt stud1 wieder geschlossen.
|
|
Das Ergebnis (mit Notepad): |
|

|
|
hsdaten, Schreiben2.java, EinlesenCSV.java |
|
Hier nun ein Beispiel für den Einsatz der Klasse BufferedWriter bei einem Schreibvorgang. Zuerst wird ein FileWriter-Objekt erzeugt. Durch Verzicht auf Angabe eines Verzeichnissses, wird die Datei im Standardverzeichnis (hier, mit Windows 11: c:/eclipse/hsdaten) angelegt. |
|
Der Schreibvorgang soll mit BufferedWriter realisiert werden (obwohl diese Datenmenge dies nicht nahelegt). Dazu wird ein BufferedWriter-Objekt buwr erzeugt, das als Input das zuvor erstellte FileWriter-Objekt fiwr hat: |
|
|
FileWriter fiwr = new FileWriter("stud07.txt");
|
|
|
BufferedWriter buwr = new BufferedWriter(fiwr);
|
|
Danach kann dann in das Objekt (die Datei) buwr geschrieben werden. In hsdaten/schreiben2 geschieht dies mit den Methoden write() und newLine(). |
|
Das Zusammenwirken der beiden Klassen kann auch verschachtelt programmiert werden. Im folgenden Beispiel aus hsdaten/EinlesenCSV geht es um einen Lesevorgang. Gelesen wird aus der Datei mitarbeiter.csv. Die Verschachtelung erfolgt auf Basis der Konstruktoren der beiden Klassen. Der Konstruktor von BufferedReader erhält als Parameter die Instanziierung von FileReader, die als Parameter den Dateinamen über die Variable fileName hat. |
|
|
String fileName = "mitarbeiter.csv";
|
|
|
stud1 = new BufferedReader(new FileReader(fileName ));
|
|
java.util.Formatter |
|
Die unten auch verwendete Klasse java.util.Formatter dient (hier) dazu, die Eingaben in eine Textdatei zu formatieren. Hier ein Beispiel aus hsdaten/Anhaengen.java: |
|
|
File datei = new File("C:/Meine Dateien/" + fileName + ".txt");
|
|
|
FileWriter writer = new FileWriter(datei, true);
|
|
|
Formatter formatter = new Formatter(writer)) {
|
|
Er benötigt ein Objekt der Klasse FileWriter als Parameter und stellt dann die benötigte Programmfunktionalität bereit. Die Methode format erlaubt dann die Spezifizierung: |
|
|
formatter.format("%s%n", newInput);
|
|
Vgl. die weiteren Ausführungen hierzu in hsdaten/Anhaengen.java. |
|
Die folgende Abbildung zeigt die hier verwendeten Klassen im Überblick. |
|

|
|
Abbildung 6.3-1: Klassen für Dateibearbeitung |
|
Da die IO-Klassen Systemressourcen benötigen, sollte man die entsprechenden Objekte schließen, wenn sie nicht mehr benötigt werden. Dies geschieht mit der Methode close(). |
|
Für weitergehende Beschreibungen vgl. die Literatur, z.B.: |
|
- [Ullenboom 2022, Abschnitt 20.4.4] für eine Beschreibung der Basisklase Writer und Abschnitt 20.4.6 für eine Beschreibung der Basisklasse Reader.
- [Ratz 2018, Kapitel 17] enthält eine verständliche und fundierte Darstellung der "Ein- und Ausgabe über I/O-Streams".
|
7 Exceptions |
|
Exceptions bedeutet hier Laufzeitfehler. Sie wurden in den unten gezeigten Programmen v.a. mit dem Try/catch-Konstrukt bei Zugriffen auf Dateien eingesetzt (IOExceptions). Exception ist auch eine Klasse, deren Objekte Fehlermeldungen sind. Die allgemeinste Fehlermeldung hat die Bezeichnung e. Sie kann auf den konkreten Fall zugeschnitten werden. |
|
In den jeweiligen Programmen muss diese Klasse mit import java.io.IOException importiert werden. Dies ist unten auch geschehen, v.a. für die Arbeit mit dem Dateisystem: |
|
- Zum Melden des Scheiterns der Methode createNewFile() (hsdaten/Erstellen.java) in einer Try/catch-Situation.
- Falls das Einrichten einer Datei und/oder des Schreibens in die Datei schief geht (hsdaten/Schreiben.java), ebenfalls in einer Try/catch-Situation.
- Beim Start eines Programms mit Dateizugriffen (hsdaten/Schreiben2.java).
|
|
Vgl. für eine ausführliche Beschreibung [Habelitz 2025, Kapitel 9]. |
|
|
|
8 Projekt HS1 |
|
HS1 steht für das erste Projekt zum Anwendungsbereich Hochschule. |
|
Aufbau der Beschreibungen |
|
Der Aufbau dieser Projektbeschreibungen ist immer gleich: Zuerst das Hauptprogramm (Klasse HP), dann die inhaltlichen Klassen. Alle Programme werden im Text zum einen ohne Erläuterungen angegeben, zum Kopieren und für den schnellen Überblick. Zum anderen aber auch mit Erläuterungen, für das schnelle Verstehen. Im letzten Abschnitt wird jeweils ein exemplarischer Programmlauf angegeben. |
|
Bei diesen Beispielsprojekten erfasst die Klasse HP den Programmablauf. Dazu wird wie immer in Java ein Hauptprogramm ("main") eingerichtet: |
|
|
public static void main(String[] args)
|
|
Zum Projekt HS1 |
|
Hier geht es schlicht darum, eine einfache Klasse Stud (Studierende) anzulegen, Objekte zu erzeugen und mit ihnen zu arbeiten. Die Klasse Stud beschreibt Studierende, ein weiterer Programmteil, sozusagen das Hauptprogramm (HP) beschreibt die dynamischen Aspekte, hier lediglich einige Handlungen mit den Objekten. |
|
Die Java-Erschaffer haben festgelegt, dass alle Programmelemente in Java-Programmen als Klassen angelegt werden müssen. Der gesamte Programmcode einer Anwendung ist also in Klassen gepackt, auch wenn dies manchmal keine Klassen im eigentlichen Sinn sind, wie schon das Beispiel hier mit dem Hauptprogramm ("main") und seinem Ablauf zeigt. |
|
Demonstriert wird in HS1: |
|
- Die Objekterzeugung (new Stud())
- Der Einsatz von Konstruktoren (mehrere Varianten)
- Das direktes Setzen von Attributen
- Der Einsatz eines Klassenattributs (anzStud)
|
|
|
|
8.1 Klasse HP |
|
Gleich zu Beginn wird ein Objekt erzeugt, s0 ("s" steht für Student/in). Dabei wird der Standardkonstruktorr verwendet. In der Klasse Stud ist zu sehen, dass es möglich ist, dem Standardkonstruktor ein Klassenattribut mit einer Wertezuweisung zuzuordnen. |
|
Nacheinander werden vier unterschiedliche Konstruktoren, die in der Klasse Stud angelegt sind, eingesetzt. Java wählt jeweils den geeigneten aus. D.h.: |
|
Eine Klasse kann verschiedene Konstruktoren besitzen. |
|
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
Auch das jeweilige Hauptprogramm (HP / main) muss in eine Klasse gepackt sein, vgl. die Anmerkung oben. |
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
Objekt s0 wird mit dem Standardkonstruktor erzeugt (instanziiert), das Klassenattribut anzStud (Anzahl Studierende) wird bearbeitet. Vgl. Klasse Stud. |
|
|
Stud s0 = new Stud();
|
|
|
System.out.println("s0 ohne Daten, nach Instanziierung:\n");
|
|
Zur Veranschaulichung die Ausgabe der Objektdaten: Nach der Instanziierung sind die Attribute mit Default-Werten beschrieben. Das Klassenattribut anzStud hat den Wert 1. Unten wird gezeigt, dass der Werte des Klassenattributs bei jeder Instanziierung um 1 erhöht wird. |
|
|
s0.ausgeben();
|
|
Dasselbe wie oben, jetzt für das zweite Objekt s1. Das Klassenattribut hat jetzt den Wert 2. |
|
|
Stud s1 = new Stud();
|
|
|
System.out.println("");
|
|
|
System.out.println("s1 ohne Daten, nach Instanziierung:\n");
|
|
|
s1.ausgeben();
|
|
Objekt s0 wird beschrieben. Dies ist einfach. Objekt- und Attributsbezeichnung identifizieren den konkreten Informationsträger, ansonsten Zuweisung wie bei Attributen. |
|
|
s0.mNr = 12345;
|
|
|
s0.name = "Sauer";
|
|
|
s0.vName = "Otto";
|
|
|
s0.anzSem = 5;
|
|
|
s0.gebTag = "21.09.2002";
|
|
|
|
|
|
System.out.println("");
|
|
|
System.out.println("s0 beschrieben:\n");
|
|
Das Objekt s0 wird mit der Instanzmethode ausgeben() aus der zum Projekt gehörenden Klasse Stud auf der Konsole ausgegeben. Innerhalb desselben Projekts genügt der Aufruf ohne Klassenangabe. Bei jedem Aufruf der Methode wird der Wert des hochgezählten Attributs anzStud ausgegeben. Siehe Programmlauf. |
|
|
s0.ausgeben();
|
|
Auch das Objekt s1 wird beschrieben und ausgegeben. |
|
|
s1.mNr = 98765;
|
|
|
s1.name = "Widder";
|
|
|
s1.vName = "Andrea";
|
|
|
s1.anzSem = 2;
|
|
|
s1.gebTag = "2.7.2005";
|
|
System.out.println(""); ist in Java plattformunabhängig gültig. Auf allen Plattformen (Windows, Linux, macOS, usw.) wird eine Leerzeile ausgegeben. |
|
|
System.out.println("");
|
|
|
System.out.println("s1 beschrieben:\n");
|
|
|
s1.ausgeben();
|
|
Nun der zweite Konstruktor, siehe Klasse Stud. Hier werden alle Attribute in der Parameterliste beschrieben. |
|
|
Stud s2 = new Stud(1111, "Maier", "Klara", 5, "21.09.2002");
|
|
|
System.out.println("\ns2 mit Daten vom Konstruktoraufruf:\n");
|
|
|
s2.ausgeben();
|
|
Der dritte Konstruktor, siehe Klasse Stud, erhält nur einen Teil der Attributsausprägungen über die Parameterliste: mNr, name, vName. Für die übrigen nimmt er die Standardwerte null bzw. 0. |
|
|
Stud s3 = new Stud(1111, "Maier", "Klara");
|
|
|
System.out.println("\ns3 mit teilweisen Daten vom Konstruktoraufruf:\n");
|
|
|
s3.ausgeben();
|
|
Java entscheidet aufgrund des Konstruktoraufrufs, hier auf Basis der Parameterliste, welcher der Konstruktoren aus der Klasse Stud verwendet wird. |
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
Stud s0 = new Stud(); //Objekt s0, Standardkonstruktor
|
|
|
|
|
|
System.out.println("s0 ohne Daten, nach Instanziierung:\n");
|
|
|
s0.ausgeben();
|
|
|
|
|
|
Stud s1 = new Stud();
|
|
|
System.out.println("");
|
|
|
System.out.println("s1 ohne Daten, nach Instanziierung:\n");
|
|
|
s1.ausgeben();
|
|
|
|
|
|
s0.mNr = 12345;
|
|
|
s0.name = "Sauer";
|
|
|
s0.vName = "Otto";
|
|
|
s0.anzSem = 5;
|
|
|
s0.gebTag = "21.09.2002";
|
|
|
System.out.println("");
|
|
|
System.out.println("s0 beschrieben:\n");
|
|
|
s0.ausgeben();
|
|
|
|
|
|
s1.mNr = 98765;
|
|
|
s1.name = "Widder";
|
|
|
s1.vName = "Andrea";
|
|
|
s1.anzSem = 2;
|
|
|
s1.gebTag = "2.7.2005";
|
|
|
System.out.println("");
|
|
|
System.out.println("s1 beschrieben:\n");
|
|
|
s1.ausgeben();
|
|
|
|
|
|
Stud s2 = new Stud(1111, "Maier", "Klara", 5, "21.09.2002");
|
|
|
System.out.println("\ns2 mit Daten vom Konstruktoraufruf:\n");
|
|
|
s2.ausgeben();
|
|
|
|
|
|
Stud s3 = new Stud(1111, "Maier", "Klara");
|
|
|
System.out.println("\ns3 mit teilweisen Daten
|
|
|
vom Konstruktoraufruf:\n");
|
|
|
s3.ausgeben();
|
|
|
}
|
|
|
}
|
|
8.2 Klasse Stud |
|
Klasse Stud mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
Beginn der Klassendefinition |
|
|
public class Stud {
|
|
Inhaltliche Attribute (Instanzattribute) zur Beschreibung der Objekte (Instanzen). |
|
|
public int mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName; //Vorname
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
Definition eines Klassenattributs (statisches Attribut) mit Anfangswert. Static fixiert die Unveränderlichkeit, int legt den Datentyp fest und anzStud = 0 einen Anfangswert. |
|
|
static int anzStud = 0;
|
|
Aufruf Konstruktor 1. Der Standardkonstruktor trägt Standardwerte in die Attribute des Objekts ein (o, null). Ergänzt hier durch den Wert des Klassenattributs anzStud. |
|
|
public Stud () {
|
|
|
anzStud++;
|
|
|
}
|
|
Aufruf Konstruktor 2, siehe Klasse Stud. Hier werden alle Attribute in der Parameterliste beschrieben |
|
|
public Stud (int mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
anzStud++;
|
|
|
}
|
|
Aufruf Konstruktor 3, siehe Klasse Stud. Dieser legt nur einen Teil der Attributsausprägungen in der Parameterliste fest: mNr, name, vName. Für die übrigen nimmt er die Standardwerte false, null oder 0. |
|
|
public Stud (int mNr, String name, String vName) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
anzStud++;
|
|
|
}
|
|
Instanzmethode zum Ausgeben der Daten eines Objekts. Das Klassenattribut anzStud gibt jeweils an, wieviele Objekte angelegt sind. Vgl. Programmlauf. |
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
System.out.println("Anzahl Studierende: " + anzStud);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse Stud ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud { //Beginn der Klassendefinition
|
|
|
public int mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName; //Vorname
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
|
static int anzStud = 0;
|
|
|
public Stud () {
|
|
|
anzStud++; //Zähler für die Objekte der Klasse
|
|
|
}
|
|
|
public Stud (int mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
anzStud++;
|
|
|
}
|
|
|
public Stud (int mNr, String name, String vName) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
anzStud++;
|
|
|
}
|
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
System.out.println("Anzahl Studierende: " + anzStud);
|
|
|
}
|
|
|
}
|
|
8.3 Programmlauf |
|
|
s0 ohne Daten, nach Instanziierung:
|
|
|
|
|
|
Matrikelnummer: 0
|
|
|
Name: null
|
|
|
Vorname:null
|
|
|
Erreichtes Semester: 0
|
|
|
Geburtstag: null
|
|
|
Anzahl Studierende: 1
|
|
|
|
|
|
s1 ohne Daten, nach Instanziierung:
|
|
|
|
|
|
Matrikelnummer: 0
|
|
|
Name: null
|
|
|
Vorname:null
|
|
|
Erreichtes Semester: 0
|
|
|
Geburtstag: null
|
|
|
Anzahl Studierende: 2
|
|
|
|
|
|
s0 beschrieben:
|
|
|
|
|
|
Matrikelnummer: 12345
|
|
|
Name: Sauer
|
|
|
Vorname:Otto
|
|
|
Erreichtes Semester: 5
|
|
|
Geburtstag: 21.09.2002
|
|
|
Anzahl Studierende: 2
|
|
|
|
|
|
s1 beschrieben:
|
|
|
|
|
|
Matrikelnummer: 98765
|
|
|
Name: Widder
|
|
|
Vorname:Andrea
|
|
|
Erreichtes Semester: 2
|
|
|
Geburtstag: 2.7.2005
|
|
|
Anzahl Studierende: 2
|
|
|
|
|
|
s2 mit Daten vom Konstruktoraufruf:
|
|
|
|
|
|
Matrikelnummer: 1111
|
|
|
Name: Maier
|
|
|
Vorname:Klara
|
|
|
Erreichtes Semester: 5
|
|
|
Geburtstag: 21.09.2002
|
|
|
Anzahl Studierende: 3
|
|
|
|
|
|
s3 mit teilweisen Daten vom Konstruktoraufruf:
|
|
|
|
|
|
Matrikelnummer: 1111
|
|
|
Name: Maier
|
|
|
Vorname:Klara
|
|
|
Erreichtes Semester: 0
|
|
|
Geburtstag: null
|
|
|
Anzahl Studierende: 4
|
|
9 Projekt HS2 |
|
Hier werden zwei Objekte (stud0 und stud1) eingerichtet und bearbeitet. Es soll deutlich werden, dass bei einer Vorgehensweise wie hier ein Objekt das aktive ist. Um dies zu vereinfachen, werden gleich zwei Objekte angelegt, mit denen dies geprüft werden kann. Es gibt ein Konsolenmenü ... |
|

|
|
... mit einer grafischen Eingabe per JOptionPane.showInputDialog (siehe Programmlauf). |
|
Da im Programm schon zwei Objekte angelegt sind, kann der Punkt 3 gleich ausprobiert werden. Dazu wird zuerst 2 angefordert, was zur Anzeige des aktiven Objekts führt. Dann wird mit 3 das Objekt gewechselt und wiederum mit 2 das jetzt aktive Objekt angezeigt. |
|
Mit 1 können neue Objekte eingegeben werden, die dann jeweils das aktive sind. Wie zu sehen ist, werden immer nur zwei Objekte bereitgehalten. |
|
|
|
9.1 Klasse HP |
|
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
Anmelden der Klasse javax.swing für die grafische Eingabe. |
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class HP {
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
String eingabe;
|
|
Erzeugen zweier Objekte mit dem Standardkonstruktor. |
|
|
Stud stud0 = new Stud();
|
|
|
Stud stud1 = new Stud();
|
|
Weiteres Objekt, mit Referenzcharakter. Zeigt aktuell auf das "aktive Objekt". |
|
|
Stud stud = stud0;
|
|
Daten zum Testen. Initialisierung von stud0. |
|
|
stud0.matrikelNr = "12345";
|
|
|
stud0.name = "Erster";
|
|
|
stud0.vName= "Paul";
|
|
|
stud0.plz = "7878";
|
|
|
stud0.ort="Weingarten";
|
|
|
stud0.strasse="Hinterm Berg";
|
|
|
stud0.hausnummer=99;
|
|
Initialisierung von stud1. |
|
|
stud1.matrikelNr = "67890";
|
|
|
stud1.name = "Zweite";
|
|
|
stud1.vName= "Viola";
|
|
|
stud1.plz = "8989";
|
|
|
stud1.ort="Ravensburg";
|
|
|
stud1.strasse="Hauptstr.";
|
|
|
stud1.hausnummer=88;
|
|
Damit nicht gleich zum Ausprobieren Daten eingegeben werden müssen, werden stud0 und stud1 mit Daten beschrieben. So ist es möglich, gleich nach dem Start die Ausgabe mit dem aktiven Objekt anzufordern (es kommt stud0), dann mit Punkt 3 das aktive Objekt zu wechseln (auf 1) und dieses wieder auszugeben. Das ist dann stud1. |
|
|
boolean fertig = false;
|
|
Beginn einer While-Schleife. Ende siehe unten. |
|
|
while (!fertig) {
|
|
|
System.out.println("\nEingabe von Daten \nin die Studierendendatei");
|
|
Menüauswahl auf Konsole. Anzeige siehe unten. |
|
|
System.out.println("1 = Eingabe");
|
|
|
System.out.println("2 = Ausgabe");
|
|
|
System.out.println("3 = Aktives Objekt wechseln");
|
|
|
System.out.println("4 = Programm beenden");
|
|
Eingabe über Dialogfenster in die String-Variable Eingabe. |
|
|
eingabe = JOptionPane.showInputDialog("Ihre Wahl");
|
|
Die String-Variable eingabe wird in einen Integer-Wert gewandelt ("parseInt") und in die Integer-Variable auswahl geschrieben. |
|
|
int auswahl = Integer.parseInt(eingabe);
|
|
|
System.out.println("\nEingegeben wurde: " + auswahl + "\n");
|
|
Verzweigung mit switch auf Basis der Nutzereingaben, die in Integerwerte gewandeltl wurden. |
|
|
switch(auswahl) {
|
|
|
case 1:
|
|
Studierendendaten eingeben. Bespielt wird Objekt stud. Es erfolgt jeweils eine grafische Anzeige der Eingabeaufforderung (vgl. unten) und das Übertragen der Nutzereingabe in die String-Variable eingabe. Diese wird in das entsprechende Objektattribut geschrieben. Für die Hausnummer wurde die Umwandlung des Strings in eine Integerzahl vorgenommen (mit parseInt). |
|
|
stud.matrikelNr = JOptionPane.showInputDialog("Matrikelnummer:");
|
|
|
stud.name = JOptionPane.showInputDialog("Name:");
|
|
|
stud.vName = JOptionPane.showInputDialog("Vorname:");
|
|
|
stud.plz = JOptionPane.showInputDialog("PLZ:");
|
|
|
stud.ort = JOptionPane.showInputDialog("Ort:");
|
|
|
stud.strasse = JOptionPane.showInputDialog("Straße:");
|
|
|
stud.hausnummer = Integer.parseInt(
|
|
|
JOptionPane.showInputDialog("Hausnummer:")
|
|
|
);
|
|
break wird für jede Case-Variante verlangt. Damit wird die Switch-Verzweigung verlassen. |
|
|
break;
|
|
|
case 2:
|
|
Diese Wahl führt zur Ausgabe der Studierendendaten des jeweils "aktiven" Objekts. |
|
|
System.out.println(stud.matrikelNr);
|
|
|
System.out.println(stud.vName + " " + stud.name);
|
|
|
System.out.println(stud.plz + " " + stud.ort);
|
|
|
System.out.println(stud.strasse + " " + stud.hausnummer);
|
|
|
break;
|
|
|
case 3:
|
|
Aktives Objekt wechseln |
|
|
int nr = Integer.parseInt(
|
|
|
JOptionPane.showInputDialog("Welcher Student (0 oder 1)?")
|
|
|
);
|
|
|
if (nr == 0) {
|
|
|
stud = stud0; // Referenz zeigt jetzt auf stud0
|
|
|
System.out.println("Jetzt ist Student 0 aktiv.");
|
|
|
} else if (nr == 1) {
|
|
|
stud = stud1; // Referenz zeigt jetzt auf stud1
|
|
|
System.out.println("Jetzt ist Student 1 aktiv.");
|
|
|
} else {
|
|
|
System.out.println("Fehler: Bitte 0 oder 1 eingeben!");
|
|
|
}
|
|
|
break;
|
|
|
case 4:
|
|
Programm beenden |
|
|
fertig = true;
|
|
|
break;
|
|
|
default:
|
|
Fehler bei falscher Menüeingabe |
|
|
System.out.println("Ungültige Eingabe!");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
String eingabe;
|
|
|
Stud stud0 = new Stud();
|
|
|
Stud stud1 = new Stud();
|
|
|
Stud stud = stud0;
|
|
|
stud0.matrikelNr = "12345";
|
|
|
stud0.name = "Erster";
|
|
|
stud0.vName = "Paul";
|
|
|
stud0.plz = "7878";
|
|
|
stud0.ort = "Weingarten";
|
|
|
stud0.strasse = "Hinterm Berg";
|
|
|
stud0.hausnummer = 99;
|
|
|
|
|
|
stud1.matrikelNr = "67890";
|
|
|
stud1.name = "Zweite";
|
|
|
stud1.vName = "Viola";
|
|
|
stud1.plz = "8989";
|
|
|
stud1.ort = "Ravensburg";
|
|
|
stud1.strasse = "Hauptstr.";
|
|
|
stud1.hausnummer = 88;
|
|
|
|
|
|
boolean fertig = false;
|
|
|
while (!fertig) {
|
|
|
System.out.println("\nEingabe von Daten \nin die Studierendendatei");
|
|
|
System.out.println("\n1 = Eingabe");
|
|
|
System.out.println("2 = Ausgabe");
|
|
|
System.out.println("3 = Aktives Objekt wechseln");
|
|
|
System.out.println("4 = Programm beenden");
|
|
|
|
|
|
eingabe = JOptionPane.showInputDialog("Ihre Wahl");
|
|
|
int auswahl = Integer.parseInt(eingabe);
|
|
|
System.out.println("\nEingegeben wurde: " + auswahl + "\n");
|
|
|
switch (auswahl) {
|
|
|
case 1:
|
|
|
stud.matrikelNr = JOptionPane.showInputDialog("Matrikelnummer:");
|
|
|
stud.name = JOptionPane.showInputDialog("Name:");
|
|
|
stud.vName = JOptionPane.showInputDialog("Vorname:");
|
|
|
stud.plz = JOptionPane.showInputDialog("PLZ:");
|
|
|
stud.ort = JOptionPane.showInputDialog("Ort:");
|
|
|
stud.strasse = JOptionPane.showInputDialog("Straße:");
|
|
|
stud.hausnummer = Integer.parseInt(
|
|
|
OptionPane.showInputDialog("Hausnummer:")
|
|
|
);
|
|
|
break;
|
|
|
case 2:
|
|
|
System.out.println("\n--- Studentendaten ---");
|
|
|
System.out.println(stud.matrikelNr);
|
|
|
System.out.println(stud.vName + " " + stud.name);
|
|
|
System.out.println(stud.plz + " " + stud.ort);
|
|
|
System.out.println(stud.strasse + " " + stud.hausnummer);
|
|
|
break;
|
|
|
case 3:
|
|
|
int nr = Integer.parseInt(
|
|
|
JOptionPane.showInputDialog("Welcher Student (0 oder 1)?")
|
|
|
);
|
|
|
|
|
|
if (nr == 0) {
|
|
|
stud = stud0; // Referenz zeigt jetzt auf stud0
|
|
|
System.out.println("Jetzt ist Student 0 aktiv.");
|
|
|
} else if (nr == 1) {
|
|
|
stud = stud1; // Referenz zeigt jetzt auf stud1
|
|
|
System.out.println("Jetzt ist Student 1 aktiv.");
|
|
|
} else {
|
|
|
System.out.println("Fehler: Bitte 0 oder 1 eingeben!");
|
|
|
}
|
|
|
break;
|
|
|
case 4:
|
|
|
fertig = true;
|
|
|
break;
|
|
|
default:
|
|
|
System.out.println("Ungültige Eingabe!");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
9.2 Klasse Stud |
|
Diese Klasse besteht nur aus der Klassendefinition. |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
|
public String matrikelNr; //Instanzvariablen
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public String plz;
|
|
|
public String ort;
|
|
|
public String strasse;
|
|
|
public int hausnummer;
|
|
|
}
|
|
9.3 Beispielhafter Programmlauf |
|
Nach dem Start des Programms erscheint das Konsolenmenü und die grafische Eingabeaufforderung. Diese wird auch für die Eingabe der Daten genutzt. |
|
Folgende zwei Eingabemasken werden genutzt: |
|

|
|
|
|

|
|
|
|
Ein Programmlauf: |
|
|
Eingabe von Daten
|
|
|
in die Studierendendatei
|
|
|
|
|
|
1 = Eingabe
|
|
|
2 = Ausgabe
|
|
|
3 = Aktives Objekt wechseln
|
|
|
4 = Programm beenden
|
|
|
|
|
|
Eingegeben wurde: 2
|
|
|
|
|
|
|
|
|
--- Studierendendaten ---
|
|
|
12345
|
|
|
Paul Erster
|
|
|
7878 Weingarten
|
|
|
Hinterm Berg 99
|
|
|
|
|
|
Eingabe von Daten
|
|
|
in die Studierendendatei
|
|
|
|
|
|
1 = Eingabe
|
|
|
2 = Ausgabe
|
|
|
3 = Aktives Objekt wechseln
|
|
|
4 = Programm beenden
|
|
|
|
|
|
Eingegeben wurde: 3
|
|
|
|
|
|
Jetzt ist Student 1 aktiv.
|
|
|
|
|
|
Eingabe von Daten
|
|
|
in die Studierendendatei
|
|
|
|
|
|
1 = Eingabe
|
|
|
2 = Ausgabe
|
|
|
3 = Aktives Objekt wechseln
|
|
|
4 = Programm beenden
|
|
|
|
|
|
Eingegeben wurde: 2
|
|
|
|
|
|
|
|
|
--- Studierendendaten ---
|
|
|
67890
|
|
|
Viola Zweite
|
|
|
8989 Ravensburg
|
|
|
Hauptstr. 88
|
|
|
|
|
|
Eingabe von Daten
|
|
|
in die Studierendendatei
|
|
|
|
|
|
1 = Eingabe
|
|
|
2 = Ausgabe
|
|
|
3 = Aktives Objekt wechseln
|
|
|
4 = Programm beenden
|
|
|
|
|
|
Eingegeben wurde: 4
|
|
Wird Eingabe gewählt, werden die einzelnen Adresselemente abgefragt (mit JoptionPane.showInputDialog(...)) und die neue Adresse wird zum aktiven Objekt. |
|
9.4 Anmerkungen zum Programm |
|
Objekte und Referenzen |
|
|
Stud stud = stud0;
|
|
"stud" ist kein neues Objekt, sondern zeigt auf stud0. Dies wird hier Referenz genannt. Stud0 ist das aktive Objekt. |
|
Mit |
|
|
stud = stud1;
|
|
zeigt stud auf ein anderes Objekt. Alle Änderungen betreffen dann stud1 statt stud0. Dieses wird zum aktiven Objekt. Der Begriff "aktives Objekt" soll helfen zu verstehen: |
|
- dass mehrere Objekte existieren,
- aber immer nur eines aktuell benutzt wird, weil die Referenzvariable gerade auf dieses Objekt zeigt.
|
|
Statt "aktives Objekt" könnte man methodisch genauer sagen: "Das aktuell referenzierte Objekt" oder "Das Objekt, auf das die Referenzvariable stud zeigt". |
|
JoptionPane |
|
JoptionPane ist eine Klasse aus der Java-Bibliothek zur einfachen Erstellung von Dialogfenstern. Sie gehört zum Paket javax.swing. Darum wird in HS2 zu Beginn geschrieben: |
|
|
import javax.swing.JOptionPane;
|
|
Mit JOptionPane können Programme einfach |
|
- Eingaben abfragen
- Meldungen anzeigen
- Warnungen ausgeben
- Auswahlfenster darstellen
|
|
ohne selbst grafische Fenster programmieren zu müssen. In HS2 wird JOptionPane zur Eingabe verwendet. Zum Beispiel: |
|
|
eingabe = JOptionPane.showInputDialog("Ihre Wahl");
|
|
Dadurch erscheint ein kleines Eingabefenster. showInputDialog() liefert immer einen String, auch wenn der Benutzer eine Zahl eingibt. Darum benötigt HS2: |
|
|
Integer.parseInt(eingabe);
|
|
Damit wird ein String in eine Ganzzahl (int) umgewandelt. |
|
Typische Methoden von JOptionPane sind: |
|
- JOptionPane.showInputDialog(...) für Benutzereingaben.
- JOptionPane.showMessageDialog(null, "Hallo") für Meldungsfenster.
- JOptionPane.showConfirmDialog(...) für ein Bestätigungsfenster.
|
|
Methodischer Hintergrund |
|
JOptionPane ist eine Klasse der GUI-Bibliothek Swing. GUI bedeutet Graphical User Interface (grafische Benutzeroberfläche). |
|
10 Projekt HS3 |
|
Array mit Objekten, zufallsgeneriert |
|
In diesem Projekt werden mehrere Objekte mit zufallsgenerierten fiktiven Daten erzeugt. Damit man nicht die Objekte einzeln im Progamm instanziieren muss, wird ein Array zu Hilfe genommen, in dem die Objekte per Programm angelegt werden. Ein solches Array wird auch komplexes Objekt genannt. |
|
Im Programm HP wird zuerst gefragt, wieviele Objekte generiert werden sollen, dann wird ein Array mit dieser Länge angelegt. In diesem werden dann gleich viele Objekte mit Leereinträgen erstellt. Diese haben die Attributsausprägungen 0 (für numerische Instanzvariablen), null (für Strings) und false (für boolesche Attribute). Damit liegt also ein Array mit Objekten vor. Wie üblich, sind die Positionen des Arrays nummeriert, beginnend mit 0. Wenn es also 50 Objekte sind, haben diese die Nummerierungen 0 bis 49 und die Adressen studiosi[i] für i gleich 0 bis 49. Über diese Array-Adresse können die Objekte angesprochen werden. |
studiosi[] |
Für die zu generierenden Objekte liegen zwei String-Arrays vor, einer mit 20 Nachnamen, einer mit 20 Vornamen. Auf deren Basis werden mit Hilfe der Methode java.util.Random() zufällige Namen und Vornamen erzeugt. Auch die übrigen Attributsausprägungen werden zufällig generiert. |
|
Wichtige Aspekte sind hier also: |
|
- Erzeugen eines Arrays aus Objekten (komplexes Objekt)
- Nutzung der Methode Random
|
|
Außerdem werden mit Hilfe der Klasse javax.swing.JoptionPane grafische Eingabemöglichkeiten genutzt: |
|

|
|
|
|
In diesem Beispiel wird, wie immer in dieser Lernhilfe, nicht die Nutzereingabe und "Tiefensemantik" kontrolliert. Z.B. könnte das Programm zwei gleiche Namenskombinationen oder Matrikelnummern erzeugen. |
|
|
|
10.1 Klasse HP |
|
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
Benötigte Klassen importieren |
|
|
import java.util.Random;
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
Überschrift ausgeben |
|
|
System.out.println("--- Objekte mit generierten Daten anlegen ---\n");
|
|
|
|
|
1. Benutzer nach Anzahl der Objekte fragen |
|
|
|
Eingabefenster anzeigen |
|
|
String eingabe =
|
|
|
JOptionPane.showInputDialog(
|
|
|
"Wieviele Objekte (maximal 100):");
|
|
Texteingabe in eine ganze Zahl umwandeln |
|
|
int ianz = Integer.parseInt(eingabe);
|
|
|
|
|
Eingabe prüfen |
|
|
if (ianz < 1 || ianz > 100) {
|
|
|
System.out.println(
|
|
|
"Fehler: Die Anzahl muss zwischen 1 und 100 liegen.");
|
|
|
|
|
Programm beenden |
|
|
return;
|
|
|
}
|
|
|
|
|
Kontrollausgabe ausgeben |
|
|
System.out.println("Anzulegende Objekte: " + ianz);
|
|
|
System.out.println();
|
|
|
|
|
2. Array für Studierende erzeugen |
|
|
Stud[] studiosi = new Stud[ianz];
|
|
|
|
|
3. Datenfelder vorbereiten |
|
|
|
|
Zur Verfügung gestellte Nachnamen |
|
|
String[] namen = {
|
|
|
"Ritter", "Knecht", "Maier", "Müller",
|
|
|
"Stauder", "Siskor", "Oduro", "Picarda",
|
|
|
"Ricker", "Maistro", "Studer", "Saskor",
|
|
|
"Podur", "Prickel", "Bond", "Jones",
|
|
|
"Riker", "Nobel"
|
|
|
};
|
|
Zur Verfügung gestellte Vornamen |
|
|
String[] vornamen = {
|
|
|
"Paul", "Frieder", "Angelika", "Karolin",
|
|
|
"Xian", "Ezri", "Jadzia", "Miriam",
|
|
|
"Elfriede", "Josef", "Guiseppe", "Angie",
|
|
|
"Frieda", "Andrea", "Ludwig", "Ricardo",
|
|
|
"Lisa", "Friedrich"
|
|
|
};
|
|
|
|
|
4. Objekte erzeugen, d.h. für jedes Feld im Array ein Stud-Objekt erzeugen |
|
|
for (int i = 0; i < studiosi.length; i++) {
|
|
|
studiosi[i] = new Stud();
|
|
|
}
|
|
|
System.out.println("Inhalte generieren und Objekte ausgeben");
|
|
Zufallszahlengenerator erzeugen |
|
|
Random r = new Random();
|
|
5. Daten generieren |
|
|
int nr = 0;
|
|
|
while (nr < studiosi.length) {
|
|
|
System.out.println();
|
|
|
System.out.println("Objekt Nr = " + nr);
|
|
Matrikelnummer erzeugen. Zufallszahl zwischen 10000 und 19999 |
|
|
studiosi[nr].mNr = r.nextInt(10000, 20000);
|
|
Nachnamen erzeugen. Zufälligen Namen aus dem Array wählen. |
|
|
studiosi[nr].name = namen[r.nextInt(namen.length)];
|
|
Vornamen erzeugen. |
|
|
studiosi[nr].vName = vornamen[r.nextInt(vornamen.length)];
|
|
Anzahl Semester erzeugen. Zufallszahl zwischen 1 und 19. |
|
|
studiosi[nr].anzSem = r.nextInt(1, 20);
|
|
6. Geburtsdatum erzeugen |
|
|
|
|
Monat zwischen 1 und 12 |
|
|
int monat = r.nextInt(1, 13);
|
|
Variable für den Tag |
|
|
int tag;
|
|
Prüfen, wie viele Tage der Monat hat |
|
|
if (monat == 2) {
|
|
|
tag = r.nextInt(1, 29);
|
|
|
}
|
|
Monate mit 30 Tagen |
|
|
else if (monat == 4 ||
|
|
|
monat == 6 ||
|
|
|
monat == 9 ||
|
|
|
monat == 11) {
|
|
Tag 1 bis 30 |
|
|
tag = r.nextInt(1, 31);
|
|
|
}
|
|
Monate mit 31 Tagen |
|
|
else {
|
|
|
tag = r.nextInt(1, 32);
|
|
|
}
|
|
Jahr zwischen 1995 und 2006 |
|
|
int jahr =
|
|
|
r.nextInt(1995, 2007);
|
|
Datum als String zusammensetzen |
|
|
studiosi[nr].gebTag = tag + "." + monat + "." + jahr;
|
|
7. Objekt ausgeben, Methode der Klasse Stud aufrufen |
|
|
studiosi[nr].ausgeben();
|
|
Zum nächsten Objekt wechseln |
|
|
nr++;
|
|
|
}
|
|
8. Gesamtanzahl ausgeben |
|
|
System.out.println(
|
|
|
"\nAnzahl Studierende: " + Stud.anzStud + "\n");
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
import java.util.Random;
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
System.out.println("--- Objekte mit generierten Daten anlegen ---\n");
|
|
|
String eingabe = JOptionPane.showInputDialog("Wieviele Objekte (maximal 100):");
|
|
|
int ianz = Integer.parseInt(eingabe);
|
|
|
|
|
|
if (ianz < 1 || ianz > 100) {
|
|
|
System.out.println("Fehler: Die Anzahl muss zwischen 1 und 100 liegen.");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
System.out.println("Anzulegende Objekte: " + ianz);
|
|
|
System.out.println();
|
|
|
|
|
|
Stud[] studiosi = new Stud[ianz];
|
|
|
|
|
|
String[] namen = {
|
|
|
"Ritter", "Knecht", "Maier", "Müller", "Stauder",
|
|
|
"Siskor", "Oduro", "Picarda", "Ricker", "Maistro",
|
|
|
"Müller", "Studer", "Saskor", "Podur", "Prickel",
|
|
|
"Ricker", "Bond", "Jones", "Riker", "Nobel"
|
|
|
};
|
|
|
|
|
|
String[] vornamen = {
|
|
|
"Paul", "Frieder", "Angelika", "Karolin", "Xian",
|
|
|
"Ezri", "Jadzia", "Miriam", "Elfriede", "Josef",
|
|
|
"Guiseppe", "Angie", "Frieda", "Andrea", "Karolin",
|
|
|
"Ludwig", "Ricardo", "Andrea", "Lisa", "Friedrich"
|
|
|
};
|
|
|
for (int i = 0; i < studiosi.length; i++) {
|
|
|
studiosi[i] = new Stud();
|
|
|
}
|
|
|
System.out.println("Inhalte generieren und Objekte ausgeben");
|
|
|
Random r = new Random();
|
|
|
int nr = 0;
|
|
|
while (nr >= 0 amp;amp; nr < studiosi.length) {
|
|
|
System.out.println();
|
|
|
System.out.println("Objekt Nr = " + nr);
|
|
|
studiosi[nr].mNr = r.nextInt(10000, 20000);
|
|
|
studiosi[nr].name = namen[r.nextInt(namen.length)];
|
|
|
studiosi[nr].vName = vornamen[r.nextInt(vornamen.length)];
|
|
|
studiosi[nr].anzSem = r.nextInt(1, 20);
|
|
|
int monat = r.nextInt(1, 13);
|
|
|
int tag;
|
|
|
|
|
|
if (monat == 2) {
|
|
|
tag = r.nextInt(1, 29);
|
|
|
} else if (monat == 4 || monat == 6 || monat == 9 || monat == 11) {
|
|
|
tag = r.nextInt(1, 31);
|
|
|
} else {
|
|
|
tag = r.nextInt(1, 32);
|
|
|
}
|
|
|
int jahr = r.nextInt(1995, 2007);
|
|
|
|
|
|
studiosi[nr].gebTag = tag + "." + monat + "." + jahr;
|
|
|
studiosi[nr].ausgeben();
|
|
|
nr++;
|
|
|
}
|
|
|
System.out.println("\nAnzahl Studierende: " + Stud.anzStud + "\n");
|
|
|
}
|
|
|
}
|
|
10.2 Klasse Stud |
|
Klasse Stud mit Erläuterungen |
|
|
package hochschule;
|
|
Klassenattribut und statisches Attribut mit Anfangswert. |
|
|
public class Stud {
|
|
|
public int mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
|
static int anzStud = 0;
|
|
|
|
|
Konstruktor mit Klassenattribut. |
|
|
public Stud () {
|
|
|
anzStud++;
|
|
|
}
|
|
Methode zum Ausgeben der Daten eines Objekts |
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
Klasse Stud ohne Erläuterungen |
|
|
package hochschule;
|
|
|
public class Stud {
|
|
|
public int mNr;
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public int anzSem;
|
|
|
public String gebTag;
|
|
|
static int anzStud = 0;
|
|
|
public Stud () {
|
|
|
anzStud++;
|
|
|
}
|
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
10.3 Programmlauf |
|
Hier wurden aus Platzgründen nur drei Objekte angefordert. |
|
|
---Objekte mit generierten Daten anlegen
|
|
|
|
|
|
Anzulegende Objekte: 3
|
|
|
|
|
|
Inhalte generieren und Objekte ausgeben
|
|
|
|
|
|
Objekt Nr = 0
|
|
|
Matrikelnummer: 17591
|
|
|
Name: Saskor
|
|
|
Vorname: Jadzia
|
|
|
Erreichtes Semester: 17
|
|
|
Geburtstag: 27.10.2006
|
|
|
|
|
|
Objekt Nr = 1
|
|
|
Matrikelnummer: 16863
|
|
|
Name: Ricker
|
|
|
Vorname: Miriam
|
|
|
Erreichtes Semester: 14
|
|
|
Geburtstag: 13.3.2005
|
|
|
|
|
|
Objekt Nr = 2
|
|
|
Matrikelnummer: 15464
|
|
|
Name: Oduro
|
|
|
Vorname: Ezri
|
|
|
Erreichtes Semester: 3
|
|
|
Geburtstag: 20.0.2002
|
|
|
|
|
|
Anzahl Studierende: 3
|
|
10.4 Beschreibung des Programms |
|
Das Projekt HS3 erweitert das Programm HS2: Statt nur mit zwei Studierenden wird jetzt mit vielen gleichzeitig gearbeitet. Die Daten werden automatisch erzeugt und in einem Array gespeichert. |
|
Zusätzlich gibt es das statische Attribut (Klassenattribut) static int anzStud. Diese Variable zählt, wie viele Studierende insgesamt erzeugt wurden. |
|
Der Konstruktor ist |
|
|
public Stud() {
|
|
|
anzStud++;
|
|
|
}
|
|
Jedes Mal, wenn ein Objekt erzeugt wird, wird der Zähler erhöht. |
|
Die Methode ausgeben() gibt alle Daten eines Studierenden aus: |
|
|
studiosi[nr].ausgeben();
|
|
Das ist eine typische Objektmethode. |
|
Im Hauptprogramm (HP) passiert die eigentliche Verarbeitung. |
|
Schritt 1: Anzahl der Objekte festlegen |
|
|
eingabe = JOptionPane.showInputDialog("Wieviele Objekte...");
|
|
Der Benutzer gibt ein, wie viele Studierendendaten erzeugt werden sollen. |
|
Schritt 2: Array erzeugen |
|
|
Stud[] studiosi = new Stud[ianz];
|
|
Das ist ein Array (Feld) für mehrere Objekte. Es ist zuerst leer, enthält nur Platz für Objekte. |
|
Schritt 3: Objekte erzeugen |
|
|
for (int i = 0; i < studiosi.length; i++) {
|
|
|
studiosi[i] = new Stud();
|
|
|
}
|
|
Jetzt werden die Objekte tatsächlich erstellt. Ergebnis: studiosi[0], studiosi[1], ... sind "echte Studierende". |
|
Schritt 4: Zufallsdaten erzeugen |
|
- Mit Random r = new Random() kann man Zufallszahlen erzeugen.
- Matrikelnummern: r.nextInt(10000, 20000) ergibt eine Zahl zwischen 10000 und 19999
- Namen auswählen: namen[r.nextInt(20)]; wählt zufällig den Nachnamen aus einer Liste
- Vornamen auswählen: vornamen[r.nextInt(20)];
- Semester: r.nextInt(1, 20);
|
|
Datum erzeugen |
|
- Monat wird zufällig gewählt
- Tag hängt vom Monat ab
- Jahr wird zufällig bestimmt
|
|
Daraus wird ein String gebaut wie: 12.5.2001 |
|
Schritt 5: Verarbeitungsschleife |
|
|
while (nr >= 0 amp;amp; nr < studiosi.length){...}
|
|
Diese Schleife geht über alle Objekte. Für jedes Objekt geschieht: |
|
- Daten erzeugen
- Daten speichern
- Daten ausgeben
|
|
Mit |
|
|
studiosi[nr].ausgeben();
|
|
werden die Daten der Objekte angezeigt. Die Methode ist in der Klasse Stud definiert. |
|
Am Ende erfolgt die Ausgabe der Gesamtanzahl aller erzeugten Objekte: |
|
|
System.out.println("Anzahl Studierende: " + Stud.anzStud);
|
|
Mit der Klasse Random ein Zufallszahlengenerator erzeugt werden. So wie hier: |
|
|
Random r = new Random();
|
|
D.h., das instanziierte Objekt r von Random() ist ein Zufallszahlengenerator. Man kann sich r wie eine kleine Maschine vorstellen, die immer neue Zufallszahlen liefert. Z.B. eine zufällige Matrikelnummer: |
|
|
studiosi[nr].mNr = r.nextInt(10000, 20000);
|
|
Oder, so wie oben, einen zufälligen Namen aus einem Array: |
|
|
studiosi[nr].name = namen[r.nextInt(namen.length)];
|
|
11 Projekt HS4 |
|
Hier werden Aufrufe über Klassengrenzen hinweg demonstriert, darunter auch eine, die zur Verknüpfung von Inhalten führt. Neben der Klasse mit dem HP liegen zwei inhaltlich motivierte Klassen vor: Stud (Studierende) und Noten. |
|
|
|
11.1 Klasse HP |
|
Zu Beginn werden mittels zweier Konstruktoraufrufe die Objekte (Studierenden) s0 und s1 instanziiert und deren Daten ausgegeben. Anschließend erfolgt der Konstruktoraufruf zur Klasse Noten. Auch hier werden die Daten per Parameteraufruf eingetragen. Abschließend wird die Ausgabe verknüpfter Daten gezeigt. Insgesamt erfolgt hier an folgenden Stellen ein Aufruf einer anderen Klasse: |
|
- s0.ausgeben() ruft im HP eine Methode der Klasse Stud auf.
- s1.name, usw. fordert im HP aus Stud die Daten des Objekts an.
- n1.fach fordert von Noten das Studienfach der Notenvergabe an, usw.
|
|
In Stud ist ein Klassenattribut eingefügt: anzStud. Es hält die Anzahl der Studierenden (die Anzahl der Objekte von Stud) fest. Das Hochzählen erfolgt im Konstruktor von Stud. |
Klassen-
attribut |
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
|
|
|
public static void main(String[] args) {
|
|
Konstruktor für das Objekt s0. Die Attribute des Objekts werden über die Parameterliste des Konstruktors befüllt. Vgl. Stud für den entsprechenden Aufbau des Konstruktors. |
|
|
Stud s0 = new Stud("123", "Maier", "Klara", 5, "21.09.2002");
|
|
|
System.out.println("Ausgabe der Daten in HP mit Methode der Klasse Stud:");
|
|
Aufruf der Instanzmethode ausgeben() der Klasse Stud.java. |
|
|
s0.ausgeben();
|
|
Ein weiteres Objekt von Stud entsteht und wird ausgegeben. |
|
|
Stud s1 = new Stud("234", "Müller", "Ulla", 5, "1.1.1999");
|
|
|
s1.ausgeben();
|
|
Konstruktor der Klasse Noten mit Dateneingabe per Parameter,. Es entsteht Objekt n1. EinfWI bedeutet: Einführung in die Wirtschaftsinformatik. Dann erfolgt der Aufruf der Instanzenmethode ausgNote() zur Ausgabe der Noten. |
|
|
Noten n1 = new Noten("234", "EinfWI", 1);
|
|
|
n1.ausgNote();
|
|
Mit den folgenden Befehlen werden, von HP aus, verknüpfte Daten von s1 und n1 ausgegeben. Das Beispiel ist aus didaktischen Gründen stark fokussiert auf die Aufruf- und Konstruktorthematik. In Wirklichkeit müssten natürlich die passenden Studierenden und Noten zuerst gesucht werden. |
|
|
System.out.println("\nAusgabe der Noten in Klasse HP:");
|
|
|
System.out.println("Matrikelnummer: " + s1.mNr + "\nName: " + s1.name + "\nVorname: " + s1.vName + "\nFach: " + n1.fach + "\nNote: " + n1.note);
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s0 = new Stud("123", "Maier", "Klara", 5, "21.09.2002");
|
|
|
System.out.println("Ausgabe der Daten in HP mit Methode der Klasse Stud:");
|
|
|
s0.ausgeben();
|
|
|
Stud s1 = new Stud("234", "Müller", "Ulla", 5, "1.1.1999");
|
|
|
s1.ausgeben();
|
|
|
Noten n1 = new Noten("123", "EinfWI", 1);
|
|
|
n1.ausgNote();
|
|
|
System.out.println("\nAusgabe der Noten in Klasse HP:");
|
|
|
System.out.println("Matrikelnummer: " + s1.mNr + "\nName: "
|
|
|
+ s1.name + "\nVorname: " + s1.vName + "\nFach: " + n1.fach
|
|
|
+ "\nNote: " + n1.note);
|
|
|
}
|
|
|
}
|
|
11.2 Klasse Noten |
|
Die Klasse Noten erfasst mit den Attributen mNr (Matrikelnummer), fach (Studienfach) und Note (erreichte Note in Klausur, mündlicher Prüfung, Hausarbeit, usw.) die Noten der Studierenden. |
|
Der Konstruktor ist wiederum so angelegt, dass die Attributsausprägungen (Werte) gleich beim Aufruf übergeben werden. Eine Methode ausgNote() erlaubt es, die Noten eines Studierenden bzgl. eines Faches anzeigen zu lassen. |
|
Klasse Noten mit Erläuterungen |
|
|
package hochschule;
|
|
Ein Konstruktor mit Werteübergabe in der Parameterliste. Damit entsteht dann nicht ein unbeschriebenes Objekt mit 0, null und false, sondern gleich eines mit beschriebenen Attributsausprägungen. Der Aufruf im HP ist wie folgt: Noten n1 = new Noten("12345", "EinfWI", 1). Zu beachten ist die Zuweisung der übergebenen Werte an die Attribute des Objekts mittels this. |
|
|
public class Noten {
|
|
|
public String mNr; //Matrikelnummer
|
|
|
public String fach; //Studienfach
|
|
|
public int note;
|
|
|
public Noten(String matrNr, String fach, int note)
|
|
|
{
|
|
|
this.mNr = matrNr;
|
|
|
this.fach = fach;
|
|
|
this.note = note;
|
|
|
}
|
|
Definition der Instanzmethode ausgNote() ("Noten ausgeben") Diese steht dann im gesamten Programm zur Verfügung, dank package hochschule. Aufruf im HP z.B. so: n1.ausgNote(). |
|
|
void ausgNote() {
|
|
|
System.out.println("\nAusgabe der Daten in Klasse Noten:");
|
|
|
System.out.println("Student (Matrikelnummer): " + mNr);
|
|
|
System.out.println("Fach: " + fach);
|
|
|
System.out.println("Note: " + note);
|
|
|
}
|
|
|
}
|
|
Klasse Noten ohne Erläuterungen |
|
|
package hochschule;
|
|
|
public class Noten {
|
|
|
public String mNr;
|
|
|
public String fach;
|
|
|
public int note;
|
|
|
public Noten(String matrNr, String fach, int note)
|
|
|
{
|
|
|
this.mNr = matrNr;
|
|
|
this.fach = fach;
|
|
|
this.note = note;
|
|
|
}
|
|
|
void ausgNote() {
|
|
|
System.out.println("\nAusgabe der Daten in Klasse Noten:");
|
|
|
System.out.println("Student (Matrikelnummer): " + mNr);
|
|
|
System.out.println("Fach: " + fach);
|
|
|
System.out.println("Note: " + note);
|
|
|
}
|
|
|
}
|
|
11.3 Klasse Stud |
|
Die Klasse Stud enthält neben den Attributen mNr (Matrikelnummer), name (Name), vName (Vorname), gebTag (Geburtstag) und anzSem (erreichtes Semester) das Klassenattribut anzStud (Anzahl Studierende). Diese wird bei der Einrichtung auf einen Anfangswert gesetzt. |
|
Die hier gewählte Konstruktorvariante zeigt die Erstellung eines Objekts mit Hilfe der Parameterliste. Wie der zugehörige Aufruf aussieht, zeigt die Klasse HP. Die Einträge der im Aufruf übergebenen Werte erfolgt mit Hilfe des Key Words this. Außerdem wird hier wiederum gleich beim Konstruktor das Attribut anzStud um 1 hochgezählt. |
|
Die Klasse hat außerdem die Methode ausgeben(), mit der die Daten des gerade erstellten Objekts auf der Konsole angezeigt werden. |
|
Klasse Stud mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
Instanzenattribute zur Beschreibung der Objekte. |
|
|
public String mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
Klassenattribut (statisches Attribut) mit Anfangswert: |
|
|
static int anzStud = 0;
|
|
Konstruktor mit Parameterliste. Zu beachten ist das Eintragen der Parameterwerte mittel this in die Attribute. Der Aufruf im HP ist hier wie folgt: Stud s0 = new Stud("1111", "Maier", "Klara", 5, "21.09.2002"). Das Klassenattribut anzStud() wird bei jedem Konstruktoraufruf um 1 erhöht. |
|
|
public Stud (String mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
anzStud++; //Zähler für Klassenattribut
|
|
|
}
|
|
Methode zum Ausgeben der Daten eines Objekts. Der Aufruf im HP ist z.B. wie folgt: s1.ausgeben(); |
|
|
void ausgeben() {
|
|
|
System.out.println("\nMatrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
Klasse Stud ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
|
public String mNr;
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public int anzSem;
|
|
|
public String gebTag; //Geburtstag
|
|
|
static int anzStud = 0;
|
|
|
public Stud (String mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr =mNr;
|
|
|
this.name =name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
anzStud++;
|
|
|
}
|
|
|
void ausgeben() {
|
|
|
System.out.println("\nMatrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
11.4 Programmlauf |
|
|
Ausgabe der Daten in HP mit Methode der Klasse Stud:
|
|
|
|
|
|
Matrikelnummer: 123
|
|
|
Name: Maier
|
|
|
Vorname:Klara
|
|
|
Erreichtes Semester: 5
|
|
|
Geburtstag: 21.09.2002
|
|
|
|
|
|
Matrikelnummer: 234
|
|
|
Name: Müller
|
|
|
Vorname:Ulla
|
|
|
Erreichtes Semester: 5
|
|
|
Geburtstag: 1.1.1999
|
|
|
|
|
|
Ausgabe der Daten in Klasse Noten:
|
|
|
Student (Matrikelnummer): 123
|
|
|
Fach: EinfWI
|
|
|
Note: 1
|
|
|
|
|
|
Ausgabe der Noten in Klasse HP:
|
|
|
Matrikelnummer: 234
|
|
|
Name: Müller
|
|
|
Vorname: Ulla
|
|
|
Fach: EinfWI
|
|
|
Note: 1
|
|
11.5 Beschreibung des Programms |
|
Das Projekt HS4 besteht aus den drei Klassen HP, Stud und Noten. Es zeigt, wie mehrere Klassen in einem Java-Programm zusammenwirken. Außerdem werden Konstruktoraufrufe mittels Parameterübergabe ausführlicher dargestellt. |
|
Das Projekt besteht aus drei Dateien: |
|
- HP.java
- Stud.java
- Noten.java
|
|
Im Projekt werden Studierende erzeugt, deren Daten gespeichert, Noten angelegt und alle Informationen ausgegeben. Dabei wird gezeigt, wie mehrere Klassen zusammenarbeiten. |
|
Die Klasse Noten beschreibt eine einzelne Note. Gespeichert werden: |
|
- Matrikelnummer des Studierenden
- Fach
- Note
|
|
Wichtig: Die 1:n-Beziehung zwischen Studierenden und Noten existiert natürlich, wird aber zunächst nur vereinfacht über die Matrikelnummer bei den Notenobjekten erfasst. Die Beschreibung der Einrichtung einer objektorientierten 1:n-Beziehung folgt später. Dabei erhält die Klasse Stud eine Notenliste: List<Noten> noten = new ArrayList<>(); Damit können dann einem Studierenden mehrere Notenobjekte direkt zugeordnet werden. |
|
Die Klasse Noten besitzt zwei Konstruktoren: |
|
- einen parameterlosen Konstruktor
- einen Konstruktor mit Parametern
|
|
Mit Parametern ergibt sich folgendes: |
|
|
public Noten(String matrNr, String fach, int note)
|
|
Damit werden Werte direkt beim Erzeugen des Objekts übergeben, z.B. so: |
|
|
Noten n1 = new Noten("123", "EinfWI", 1);
|
|
Ohne Parameter ist der Aufruf wie folgt: |
|
|
public Noten()
|
|
Dabei können Standardwerte gesetzt werden, so wie hier: |
|
|
mNr = "000";
|
|
|
fach = "unbekannt";
|
|
|
note = 0;
|
|
Der Aufruf ist: |
|
|
Noten n2 = new Noten();
|
|
Solche Konstruktoren sind nützlich, wenn zunächst ein "leeres" Objekt erzeugt werden soll. |
|
Statische Variable |
|
In der Klasse Stud gibt es eine sog. statische Variable, bzw. ein Klassenattribut: |
|
|
static int anzStud = 0;
|
|
Ein solches bezieht sich nicht auf ein einzelnes Objekt, sondern auf die gesamte Klasse. Hier gibt es an, wie viele Studierenden-Objekte erzeugt wurden. Dafür wird jeweils im Konstruktor um eins erhöht: |
|
|
anzStud++;
|
|
12 Projekt HS5 |
|
Hier werden mit java.util.Scanner Konsoleneingaben (Integerwerte und Strings) gelesen. Vgl. Abschnitt 3.1. Dann wird ein Objekt erzeugt und mit den eingelesenen Daten bespielt. Mithilfe der Instanzmethode ausgeben() aus Stud.java wird dann dieses Objekt auf dem Bildschirm angezeigt. Abschließend wird das Hochzählen einer Klassenvariablen demonstriert. |
|
|
|
12.1 Klasse HP |
|
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
Scanner-Objekt erzeugen. Mit Scanner können Daten über die Tastatur eingelesen werden. System.in bedeutet: Eingabe von der Konsole. |
|
|
Scanner scanner = new Scanner(System.in);
|
|
Benutzer fragen, ob ein Objekt angelegt werden soll. |
|
|
System.out.print("Objekt eingeben (j/n): ");
|
|
Eingabe als Zeichenkette einlesen. |
|
|
String s = scanner.nextLine();
|
|
Auswahl abhängig von der Eingabe. switch überprüft den Inhalt der Variablen s. |
|
|
switch (s) {
|
|
Falls der Benutzer "j" eingibt: |
|
|
case "j":
|
|
|
System.out.println("Eingabe:");
|
|
Matrikelnummer abfragen. nextLine() liefert zunächst einen String. Integer.parseInt(...) wandelt den String in eine Ganzzahl um. |
|
|
System.out.print("Matrikelnummer: ");
|
|
|
int mNr = Integer.parseInt(scanner.nextLine());
|
|
Namen einlesen. |
|
|
System.out.print("Name: ");
|
|
|
String name = scanner.nextLine();
|
|
Vorname einlesen. |
|
|
System.out.print("Vorname: ");
|
|
|
String vName = scanner.nextLine();
|
|
Aktuelles Semester einlesen. |
|
|
System.out.print("Aktuelles Semester: ");
|
|
|
int anzSem = Integer.parseInt(scanner.nextLine());
|
|
Geburtstag einlesen. |
|
|
System.out.print("Geburtstag: ");
|
|
|
String gebTag = scanner.nextLine();
|
|
Neues Objekt der Klasse Stud erzeugen. Der parameterlose Konstruktor wird aufgerufen. |
|
|
Stud s100 = new Stud();
|
|
Die eingegebenen Werte werden den Attributen zugewiesen. Das Objekt s100 wird dadurch beschrieben. |
|
|
s100.mNr = mNr;
|
|
|
s100.name = name;
|
|
|
s100.vName = vName;
|
|
|
s100.anzSem = anzSem;
|
|
|
s100.gebTag = gebTag;
|
|
Ausgabeüberschrift. |
|
|
System.out.println("\n-----Objekt mit externer Methode anzeigen:\n");
|
|
Methode ausgeben() der Klasse Stud aufrufen. Die Methode gibt die Daten des Objekts aus. |
|
|
s100.ausgeben();
|
|
|
System.out.println();
|
|
Ende dieses case-Zweigs. |
|
|
break;
|
|
Falls nicht "j" eingegeben wurde. Programmabbruch melden. |
|
|
default:
|
|
|
System.out.println("Abbruch");
|
|
|
break;
|
|
|
}
|
|
Scanner schließen. Dadurch werden Systemressourcen freigegeben. |
|
|
scanner.close();
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
Scanner scanner = new Scanner(System.in);
|
|
|
System.out.print("Objekt eingeben (j/n): ");
|
|
|
String s = scanner.nextLine();
|
|
|
switch (s) {
|
|
|
case "j":
|
|
|
System.out.println("Eingabe:");
|
|
|
System.out.print("Matrikelnummer: ");
|
|
|
int mNr = Integer.parseInt(scanner.nextLine());
|
|
|
System.out.print("Name: ");
|
|
|
String name = scanner.nextLine();
|
|
|
System.out.print("Vorname: ");
|
|
|
String vName = scanner.nextLine();
|
|
|
System.out.print("Aktuelles Semester: ");
|
|
|
int anzSem = Integer.parseInt(scanner.nextLine());
|
|
|
System.out.print("Geburtstag: ");
|
|
|
String gebTag = scanner.nextLine();
|
|
|
Stud s100 = new Stud();
|
|
|
s100.mNr = mNr;
|
|
|
s100.name = name;
|
|
|
s100.vName = vName;
|
|
|
s100.anzSem = anzSem;
|
|
|
s100.gebTag = gebTag;
|
|
|
System.out.println("\n-----Objekt mit externer Methode anzeigen:\n");
|
|
|
s100.ausgeben();
|
|
|
System.out.println();
|
|
|
break;
|
|
|
default:
|
|
|
System.out.println("Abbruch");
|
|
|
break;
|
|
|
}
|
|
|
scanner.close();
|
|
|
}
|
|
|
}
|
|
12.2 Klasse Stud |
|
Klasse Stud mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
|
public int mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
Klassenattribut/statisches Attribut anzStud mit Anfangswert. |
|
|
static int anzStud = 0;
|
|
Konstruktor mit Klassenattribut als Zähler. Bei jedem Aufruf wird er um 1 höher gesetzt. |
|
|
public Stud() {
|
|
|
anzStud++; //Zähler für Klassenattribut
|
|
|
}
|
|
Methode zum Ausgeben der Daten eines Objekts. |
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
Klasse Stud ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
|
public int mNr; //Matrikelnummer
|
|
|
public String name;
|
|
|
public String vName;
|
|
|
public int anzSem; //Erreichtes Semester
|
|
|
public String gebTag; //Geburtstag
|
|
|
static int anzStud = 0;
|
|
|
public Stud () {
|
|
|
anzStud++; //Zähler für Klassenattribut
|
|
|
}
|
|
|
void ausgeben() {
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
12.3 Beispielhafter Programmlauf |
|
|
Objekt eingeben (j/n):
|
|
|
j
|
|
|
Eingabe:
|
|
|
Matrikelnummer: 12345
|
|
|
Name: Studer
|
|
|
Vorname: Guiseppe
|
|
|
Aktuelles Semester: 8
|
|
|
Geburtstag: 21.9.2000
|
|
|
|
|
|
-----Objekt mit externer Methode anzeigen:
|
|
|
|
|
|
Matrikelnummer: 12345
|
|
|
Name: Studer
|
|
|
Vorname:Guiseppe
|
|
|
Erreichtes Semester: 8
|
|
|
Geburtstag: 21.9.2000
|
|
12.4 Anmerkungen zum Programm |
|
Der Programmlauf zeigt, dass die Dateneingabe mit java.util.Scanner recht schlicht ist. Es gibt die Möglichkeit, mit |
|
|
System.out.println("\nMatrikelnummer:");
|
|
den Cursor auf dem Bildschirm in die nächste Zeile zu stellen, was aber auch nicht überzeugend ist. Deshalb werden hier in den weiteren Programmen noch andere Vorgehensweisen für Eingaben demonstriert. |
|
Das Programm ist bewusst einfach gehalten und dient Lernzwecken: |
|
- Die Attribute sind öffentlich zugänglich
- Es erfolgt keine Fehlerbehandlung bei falschen Eingaben
|
|
Dies müsste in professionellen Anwendungen anders gelöst werden. |
|
13 Exkurs - Nachrichtenverkehr |
|
In der UML spielt der Nachrichtenverkehr zwischen Objekten eine wichtige Rolle bei der Erbringung der Programmleistung. An dieser Stelle nun die Frage: Gibt es in Java auch das Konzept der Nachrichten zwischen Objekten und wie ist es umgesetzt. |
|
Der Hintergrund des Nachrichtenkonzepts der UML ist ja, dass ein Objekt einer Klasse ein Objekt einer anderen Klasse zu einer Aktion aufruft. Dies geschieht in Java durch Methodenaufrufe, wie sie auch hier in den Programmen zu sehen sind. Ein einfaches Beispiel ist, dass aus dem HP der Ausdruck aus einer Klasse Drucker angefordert wird: |
|
|
class Drucker {
|
|
|
void drucken(String text) {
|
|
|
System.out.println(text);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
Drucker d = new Drucker();
|
|
|
d.drucken("Hallo Welt");
|
|
|
}
|
|
|
}
|
|
Hier erhält also das Objekt d der Klasse Drucker die Nachricht |
|
|
drucken("Hallo Welt")
|
|
und führt daraufhin die Methode aus. |
|
Beispiel aus den HS-Projekten: In der Klasse HP aus HS9 liegt vor: |
|
|
s1.addNote(n1);
|
|
Die Methode ist in der Klasse Stud und wird dort für das Objekt s1 ausgeführt. |
|
Im HP des Projekts HS6 wird mittels |
|
|
s1.ausgeben();
|
|
die entsprechende Methode in Stud aufgerufen und für das Objekt s1 ausgeführt. Näheres siehe dort. |
|
Merksatz |
|
Objektorientierte Programme bestehen aus Objekten, die sich gegenseitig über Methodenaufrufe Nachrichten senden und die damit gemeinsam die Aufgabenerledigung realisieren. |
|
|
|
14 Projekt HS6 |
|
Hier geht es um Record-Klassen. Vgl. deren Beschreibung in Abschnitt 4.7. |
|
|
|
14.1 Klasse HP |
|
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
Drei Record-Objekte werden erzeugt. Auch hier wird mit new der Konstruktor angeworfen. Vgl. Record Stud unten. Die records werden per Parameterübergabe beschrieben. |
|
|
Stud s1 = new Stud("Stauder", "Franz", 88888, "Überall", 5, "20.1.2000");
|
|
|
Stud s2 = new Stud("Müller", "Franz", 99999, "Nirgendwo", 13, "1.1.2001");
|
|
|
Stud s3 = new Stud("Müller", "Franz", 99999, "Nirgendwo", 13, "1.1.2001");
|
|
Für jedes Attribut wird bei Records automatisch eine gleichnamige Abfragemethode bereitgestellt. Für name also name(), wie hier gezeigt. |
|
|
System.out.println("\nAusgabe einzelner Attributsausprägungen:\n");
|
|
|
System.out.println("Name: " + s1.name());
|
|
|
System.out.println("Name: " + s2.name());
|
|
Die Methode toString() liefert Ausgaben eines ganzen Record-Objekts mit Attributsbezeichnung und Attributsausprägung. Vgl. Programmlauf. |
|
|
System.out.println("\nAusgabe records s1 ... s3:\n");
|
|
|
System.out.println(s1.toString());
|
|
|
System.out.println(s2.toString());
|
|
|
System.out.println(s3.toString());
|
|
|
System.out.println("\nVergleich der Objekte:\n");
|
|
Der Vergleich von Record-Objekten erfolgt mit der Methode equals(). Eine Abfrage mittels einfacher Gleichsetzung klappt nicht. Vgl. die in Abschnitt 4.7 angegebene Literatur. |
|
|
if (s1.equals(s2))
|
|
|
System.out.println("s1 und s2: Identische Studierende.");
|
|
|
else
|
|
|
System.out.println("s1 und s2: Nicht identische Studierende.");
|
|
|
if (s3.equals(s2))
|
|
|
System.out.println("s3 und s2: Identische Studierende.");
|
|
|
else
|
|
|
System.out.println("s3 und s2: Nicht identische Studieren-de.");
|
|
|
if (s3.equals(s1))
|
|
|
System.out.println("s3 und s1: Identische Studierende.");
|
|
|
else
|
|
|
System.out.println("s3 und s1: Nicht identische Studieren-de.");
|
|
Zur Veranschaulichung hier noch die "klassische" Ausgabe auf der Konsole. |
|
|
System.out.println("\nStudierende/r s1:");
|
|
|
s1.ausgeben();
|
|
|
System.out.println("\nStudierende/r s2:");
|
|
|
s2.ausgeben();
|
|
|
System.out.println("\nStudierende/r s3:");
|
|
|
s3.ausgeben();
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s1 = new Stud("Stauder", "Franz", 88888, "Überall", 5, "20.1.2000");
|
|
|
Stud s2 = new Stud("Müller", "Franz", 99999, "Nirgendwo", 13, "1.1.2001");
|
|
|
Stud s3 = new Stud("Müller", "Franz", 99999, "Nirgendwo", 13, "1.1.2001");
|
|
|
System.out.println("\nAusgabe einzelner Attributsausprägungen:\n");
|
|
|
System.out.println("Name: " + s1.name());
|
|
|
System.out.println("Name: " + s2.name());
|
|
|
System.out.println("\nAusgabe records s1 ... s3:\n");
|
|
|
System.out.println(s1.toString());
|
|
|
System.out.println(s2.toString());
|
|
|
System.out.println(s3.toString());
|
|
|
System.out.println("\nVergleich der Objekte:\n");
|
|
|
if (s1.equals(s2))
|
|
|
System.out.println("s1 und s2: Identische Studierende.");
|
|
|
else
|
|
|
System.out.println("s1 und s2: Nicht identische Studierende.");
|
|
|
if (s3.equals(s2))
|
|
|
System.out.println("s3 und s2: Identische Studierende.");
|
|
|
else
|
|
|
System.out.println("s3 und s2: Nicht identische Studieren-de.");
|
|
|
if (s3.equals(s1))
|
|
|
System.out.println("s3 und s1: Identische Studierende.");
|
|
|
else
|
|
|
System.out.println("s3 und s1: Nicht identische Studieren-de.");
|
|
|
System.out.println("\nStudierende/r s1:");
|
|
|
s1.ausgeben();
|
|
|
System.out.println("\nStudierende/r s2:");
|
|
|
s2.ausgeben();
|
|
|
System.out.println("\nStudierende/r s3:");
|
|
|
s3.ausgeben();
|
|
|
}
|
|
|
}
|
|
14.2 Klasse Stud |
|
|
package hochschule;
|
|
|
|
|
Aufruf des Konstruktors. Damit wird der Record eingerichtet.Vgl. unten. |
|
|
public record Stud(String name, String vName, int plz, String ort, int anzSem, String gebTag) {
|
|
|
void ausgeben() {
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname: " + vName);
|
|
|
System.out.println("PLZ: " + plz);
|
|
|
System.out.println("Ort: " + ort);
|
|
|
System.out.println("Anzahl Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
14.3 Beispielhafter Programmlauf |
|
|
Ausgabe einzelner Attributsausprägungen:
|
|
|
|
|
|
Name: Müller
|
|
|
Name: Müller
|
|
|
|
|
|
Ausgabe records s1 ... s3:
|
|
|
|
|
|
Stud[name=Müller, vName=Franz, plz=88888, ort=Überall, anzSem=5, gebTag=20.1.2000]
|
|
|
Stud[name=Müller, vName=Franz, plz=99999, ort=Nirgendwo, anzSem=13, gebTag=1.1.2001]
|
|
|
Stud[name=Müller, vName=Franz, plz=99999, ort=Nirgendwo, anzSem=13, gebTag=1.1.2001]
|
|
|
|
|
|
Vergleich der Objekte:
|
|
|
|
|
|
s1 und s2: Nicht identische Studierende.
|
|
|
s3 und s2: Identische Studierende.
|
|
|
s3 und s1: Nicht identische Studierende.
|
|
|
|
|
|
Studierende/r s1:
|
|
|
Name: Müller
|
|
|
Vorname: Franz
|
|
|
PLZ: 88888
|
|
|
Ort: Überall
|
|
|
Anzahl Semester: 5
|
|
|
Geburtstag: 20.1.2000
|
|
|
|
|
|
Studierende/r s2:
|
|
|
Name: Müller
|
|
|
Vorname: Franz
|
|
|
PLZ: 99999
|
|
|
Ort: Nirgendwo
|
|
|
Anzahl Semester: 13
|
|
|
Geburtstag: 1.1.2001
|
|
|
|
|
|
Studierende/r s3:
|
|
|
Name: Müller
|
|
|
Vorname: Franz
|
|
|
PLZ: 99999
|
|
|
Ort: Nirgendwo
|
|
|
Anzahl Semester: 13
|
|
|
Geburtstag: 1.1.2001
|
|
14.4 Projektbeschreibung |
|
Ziel des Projekts |
|
Das Projekt HS6 führt in das Konzept der Records in Java ein. Records sind eine spezielle Form von Klassen, die verwendet werden, um Objekte mit Daten besonders einfach zu beschreiben. Viele Standardfunktionen werden dabei automatisch von Java erzeugt. |
|
Das Projekt zeigt: |
|
- Erzeugen von Record-Objekten
- Arbeiten mit Attributen
- automatische Zugriffsmethoden
- automatische toString()-Methode
- Vergleich von Objekten mit equals()
- eigene Methoden innerhalb eines Records
|
|
Aufbau des Projekts |
|
Das Projekt besteht aus den zwei Programmen HP.java (Hauptprogramm, wie üblich) und Stud.java mit den Records für Studierende. |
|
Im Hauptprogramm werden |
|
- mehrere Record-Objekte erzeugt
- Attributwerte abgefragt
- ganze Objekte ausgegeben
- Objekte miteinander verglichen
|
|
Der Record Stud |
|
Mit dem Record Stud werden Studierende beschrieben. Die Definition lautet: |
|
|
public record Stud(
|
|
|
String name,
|
|
|
String vName,
|
|
|
int plz,
|
|
|
String ort,
|
|
|
int anzSem,
|
|
|
String gebTag)
|
|
Die einzelnen Bestandteile heißen Komponenten des Records. Sie entsprechen den Attributen eines normalen Objekts. Ein Record unterscheidet sich von einer normalen Klasse. Java erzeugt automatisch: |
|
- einen Konstruktor
- Zugriffsmethoden
- toString()
- equals()
- hashCode()
|
|
Dadurch wird der Quellcode deutlich kürzer. |
|
Erzeugen von Record-Objekten |
|
Im Hauptprogramm werden drei Objekte erzeugt: |
|
|
Stud s1 = new Stud(...);
|
|
|
Stud s2 = new Stud(...);
|
|
|
Stud s3 = new Stud(...);
|
|
Beim Aufruf von new wird automatisch der Konstruktor des Records verwendet. Die Werte (Attributsausprägungen) werden direkt als Parameter übergeben. |
|
Zugriff auf einzelne Werte |
|
Für jede Komponente erzeugt Java automatisch eine Zugriffsmethode. Für die Komponente: |
|
|
String name
|
|
entsteht automatisch die Methode: |
|
|
name()
|
|
Beispiel: |
|
|
System.out.println(s1.name());
|
|
Damit wird der Nachname des Objekts s1 ausgegeben. |
|
Ausgabe eines gesamten Objekts |
|
Records besitzen automatisch die Methode: |
|
|
toString()
|
|
Damit können alle Inhalte eines Objekts auf einmal ausgegeben werden. Beispiel: |
|
|
System.out.println(s1.toString());
|
|
Die Ausgabe enthält: |
|
- den Record-Namen
- alle Komponenten
- die zugehörigen Werte
|
|
Vergleich von Record-Objekten |
|
Der Vergleich erfolgt mit: |
|
|
equals()
|
|
Beispiel: |
|
|
s2.equals(s3)
|
|
Das Ergebnis ist: |
|
|
true
|
|
weil alle Werte identisch sind. Dagegen liefert: |
|
|
s1.equals(s2)
|
|
den Wert: |
|
|
false
|
|
weil sich mehrere Werte unterscheiden. |
|
14.5 Exkurs - Record vs. Klasse |
|
Ein Record ist in Java eine besondere Form einer Klasse. Jeder Record ist gleichzeitig auch eine Klasse, aber nicht jede Klasse ist ein record. Intern wird für einen Record automatisch eine Klasse erzeugt. Das bedeutet |
|
|
public record Stud(...)
|
|
entspricht ungefähr |
|
|
public final class Stud,
|
|
allerdings mit automatisch erzeugtem Zusatzcode. |
|
Der Record-Kopf gibt die Komponenten des Records an: |
|
|
(String name, String vName, int plz, String ort, int anzSem, String gebTag)
|
|
Java erzeugt daraus automatisch: |
|
- private finale Attribute
- einen Konstruktor
- Getter-Methoden
- toString()
- equals()
- hashCode()
|
|
Intern entsteht ungefähr: |
|
|
private final String name;
|
|
|
private final String vName;
|
|
|
private final int plz;
|
|
|
...
|
|
Java erzeugt auch automatisch einen Konstruktor, etwa so: |
|
|
public Stud(String name, String vName, int plz, String ort, int anzSem, String gebTag) {
|
|
|
this.name = name;
|
|
|
this.vName = vName;
|
|
|
...
|
|
|
}
|
|
Ebenso entsteht für jede Komponente auch eine Zugriffsmethode, die den ansonsten üblichen Getter-Methoden entspricht: |
|
|
name()
|
|
|
vName()
|
|
|
plz()
|
|
|
ort()
|
|
|
anzSem()
|
|
|
gebTag()
|
|
Der Methodenaufruf erfolgt dann z.B. so: |
|
|
s1.name()
|
|
Merksatz |
|
Ein Record ist eine spezielle Klasse zur einfachen Verwaltung unveränderlicher Daten. |
|
14.6 Exkurs - Methode hashCode() |
|
Die Methode hashCode() liefert zu einem Objekt eine ganze Zahl (int), die als eine Art „numerischer Fingerabdruck“ des Objekts dient. Sie wird vor allem für Datenstrukturen verwendet wie: |
|
- HashMap
- HashSet
- Hashtable
|
|
Dort hilft der Hashcode dabei, Objekte schnell wiederzufinden. Einfaches Bild: |
|
- Der Hashcode bestimmt, in welches "Fach" oder welchen "Behälter" ein Objekt einsortiert wird.
- Dadurch muss später nicht die gesamte Sammlung durchsucht werden.
|
|
Beispiel: |
|
- String s1 = "Hallo";
- System.out.println(s1.hashCode());
|
|
Ausgabe z.B.: |
|
|
69609650
|
|
Damit wurde in Java eine alte Dateitechnik herangezogen, die der Direktzugriffsdateien/Hashing. Vgl. für eine Kurzbeschreibung: |
|
|
https://www.staud.info/rm2/rm_t_1.php#Abschnitt22.5
|
|
Wichtig ist, in einem "Behälter" sind tatsächlich mehrere Objekte, dort muss also weiterhin gesucht werden. Trotzdem reduziert sich der insgesamt notwendige Suchaufwand enorm. |
|
15 Projekt HS7 - Vererbung, Attribute |
|
Hier wird an einem einfachen Beispiel die Umsetzung des Vererbungskonzepts in Java gezeigt. Dies erfolgt anhand des folgenden Auschnitts aus der Vererbungshierarchie von Abbildung 6.5-1 aus [Staud 2025] und anhand von Attributen. |
|
Die Superklasse ist Fahrzeuge, zwei Subklassen davon sind PKW und LKW, eine weitere Subklasse, jetzt aber von PKW, ist VAN. Attribute sind unten in den Programmen angegeben. |
|

|
|
Abbildung 13.3-1: Generalisierung / Spezialisierung mit Vererbung. Quelle: Auszug aus [Staud 2025, Abbildung 13.3-2] |
|
Darstellung |
|
Bei diesem Projekt betrachten wir zuerst die Klassen der Generalisierung / Spezialisierung mit ihrer Vererbungshierarchie, dann das HP (Hauptprogramm). Auch hier werden die Beispiele ganz einfach gehalten und auf die aktuelle Fragestellung zugeschnitten. |
|
|
|
15.1 Klasse Fahrzeuge |
|
Klasse Fahrzeuge mit Erläuterungen |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class Fahrzeuge {
|
|
|
int fzNr = 0;
|
|
|
float listenPreis = 0.0F;
|
|
Eingeschränkte Sichtbarkeit mit private. |
|
|
private float marktPreis = 0.0f;
|
|
|
String hersteller;
|
|
|
String bez;
|
|
|
int baujahr;
|
|
|
String datumZul;
|
|
|
double gewicht;
|
|
|
char antrieb = 'n'; // d = Diesel, b = Benzin, e = Elektro, h = Hybrid
|
|
|
int kw;
|
|
|
String getriebe;
|
|
Der Marktpreis des jeweiligen Objekts kann von den anderen Klassen wegen Sichtbarkeit private nicht direkt abgefragt werden. Deshalb die folgende Methode. Diese wird dann von HP aufgerufen. |
|
|
void marktPreis() {
|
|
|
System.out.println("Derzeitiger Marktpreis vor EINTRAGEN: " + marktPreis);
|
|
|
}
|
|
Eintragen in private marktPreis. |
|
|
void marktPreisEintragen(float marktPreis) {
|
|
|
this.marktPreis = marktPreis;
|
|
|
System.out.println("Derzeitiger Marktpreis nach EINTRAGEN: " + marktPreis);
|
|
|
}
|
|
|
}
|
|
Klasse Fahrzeuge ohne Erläuterungen |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class Fahrzeuge {
|
|
|
int fzNr = 0;
|
|
|
float listenPreis = 0.0F;
|
|
|
private float marktPreis = 0.0f;
|
|
|
String hersteller;
|
|
|
String bez;
|
|
|
int baujahr;
|
|
|
String datumZul;
|
|
|
double gewicht;
|
|
|
char antrieb = 'n'; // d = Diesel, b = Benzin, e = Elektro, h = Hybrid
|
|
|
int kw;
|
|
|
String getriebe;
|
|
|
|
|
|
void marktPreis() {
|
|
|
System.out.println("Derzeitiger Marktpreis vor EINTRAGEN: " + marktPreis);
|
|
|
}
|
|
|
|
|
|
void marktPreisEintragen(float marktPreis) {
|
|
|
this.marktPreis = marktPreis;
|
|
|
System.out.println("Derzeitiger Marktpreis nach EINTRAGEN: " + marktPreis);
|
|
|
}
|
|
|
}
|
|
15.2 Klasse PKW |
|
Diese Subklasse von Fahrzeuge enthält Attribute, die spezifisch sind für PKW oder die im jeweiligen Kontext nur für PKW erhoben werden sollen. |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class PKW extends Fahrzeuge {
|
|
|
String garantie = "nicht erfasst";
|
|
|
String typ;
|
|
|
int autonomStufe;
|
|
15.3 Klasse LKW |
|
Klasse LKW mit Erläuterungen |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class LKW extends Fahrzeuge {
|
|
Spezifische Attribute für LKW. Erbt alle Attribute und Methoden von Fahrzeuge. |
|
|
double ladeKap;
|
|
|
int zahlAchsen;
|
|
|
String zustand = "---";
|
|
Konstruktor mit Datenübergabe per Parameter. Aufruf siehe HP. |
|
|
public LKW(int fzNr, float listenPreis, String hersteller, String bez, int baujahr, String datumZul, double gewicht, char antrieb, int kw, String getriebe, double ladeKap, int zahlAchsen, String zustand) {
|
|
|
this.fzNr = fzNr;
|
|
|
this.listenPreis = listenPreis;
|
|
|
this.hersteller = hersteller;
|
|
|
this.bez = bez;
|
|
|
this.baujahr = baujahr;
|
|
|
this.datumZul = datumZul;
|
|
|
this.gewicht = gewicht;
|
|
|
this.antrieb = antrieb;
|
|
|
this.kw = kw;
|
|
|
this.getriebe = getriebe;
|
|
|
this.ladeKap = ladeKap;
|
|
|
this.zahlAchsen = zahlAchsen;
|
|
|
this.zustand = zustand;
|
|
|
}
|
|
Standardkonstruktor. Ist voreingestellt da und muss normalerweise nicht angegeben werden. Hier aber notwendig, weil oben ein spezifischer Konstruktor angegeben wurde. |
|
|
public LKW() {
|
|
|
}
|
|
|
}
|
|
Klasse LKW ohne Erläuterungen |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class LKW extends Fahrzeuge {
|
|
|
double ladeKap;
|
|
|
int zahlAchsen;
|
|
|
String zustand = "---";
|
|
|
public LKW(int fzNr, float listenPreis, String hersteller,
|
|
|
String bez, int baujahr, String datumZul, double gewicht,
|
|
|
char antrieb, int kw, String getriebe, double ladeKap,
|
|
|
int zahlAchsen, String zustand) {
|
|
|
this.fzNr = fzNr;
|
|
|
this.listenPreis = listenPreis;
|
|
|
this.hersteller = hersteller;
|
|
|
this.bez = bez;
|
|
|
this.baujahr = baujahr;
|
|
|
this.datumZul = datumZul;
|
|
|
this.gewicht = gewicht;
|
|
|
this.antrieb = antrieb;
|
|
|
this.kw = kw;
|
|
|
this.getriebe = getriebe;
|
|
|
this.ladeKap = ladeKap;
|
|
|
this.zahlAchsen = zahlAchsen;
|
|
|
this.zustand = zustand;
|
|
|
}
|
|
|
public LKW() {
|
|
|
}
|
|
|
}
|
|
15.4 Klasse VAN |
|
Klasse VAN mit Erläuterungen |
|
Subklasse von PKW. Diese kann also die Attribute und Methoden von PKW und von Fahrzeuge erben. Sie selbst enthält Attribute, die spezifisch sind für VANs oder die im jeweiligen Kontext nur für VANs erhoben werden sollen. |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class VAN extends PKW {
|
|
|
int maxPers = 0;
|
|
|
boolean bank = false;
|
|
Konstruktor mit Übergabe der Werte beim Aufruf. |
|
|
public VAN(int maxPers, boolean bank) {
|
|
|
this.maxPers = maxPers;
|
|
|
this.bank = bank;
|
|
|
}
|
|
Methode ausgeben() in VAN mit Zugriff auf die Attribute von Superklassen (übergeordneten Klassen). Alle folgenden Attribute geerbt von Fahrzeuge. |
|
|
void ausgeben() {
|
|
|
System.out.println("Inventarnummer: " + fzNr);
|
|
|
System.out.println("Hersteller: " + hersteller);
|
|
|
System.out.println("Bezeichnung: " + bez);
|
|
|
System.out.println("Baujahr: " + baujahr);
|
|
|
System.out.println("Datum der Erstzulassung: " + datumZul);
|
|
|
System.out.println("Antriebsart: " + antrieb);
|
|
|
System.out.println("Listenpreis: " + listenPreis);
|
|
|
System.out.println("Gewicht: " + gewicht);
|
|
|
System.out.println("Nennleistung: " + kw);
|
|
|
System.out.println("Getriebe: " + getriebe);
|
|
Die nächsten drei Attribute stammen von der Klasse PKW. |
|
|
System.out.println("Garantie: " + garantie);
|
|
|
System.out.println("Typ: " + typ);
|
|
|
System.out.println("Automatisches Fahren, Stufe: " + autonomStufe);
|
|
Die nächsten zwei von der Klasse VAN. |
|
|
System.out.println("Maximale Anzahl Personen: " + maxPers);
|
|
|
System.out.println("Bank: " + bank);
|
|
|
}
|
|
|
}
|
|
Klasse VAN ohne Erläuterungen |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class VAN extends PKW {
|
|
|
int maxPers = 0;
|
|
|
boolean bank = false;
|
|
|
public VAN(int maxPers, boolean bank) {
|
|
|
this.maxPers = maxPers;
|
|
|
this.bank = bank;
|
|
|
}
|
|
|
void ausgeben() {
|
|
|
System.out.println("Inventarnummer: " + fzNr);
|
|
|
System.out.println("Hersteller: " + hersteller);
|
|
|
System.out.println("Bezeichnung: " + bez);
|
|
|
System.out.println("Baujahr: " + baujahr);
|
|
|
System.out.println("Datum der Erstzulassung: " + datumZul);
|
|
|
System.out.println("Antriebsart: " + antrieb);
|
|
|
System.out.println("Listenpreis: " + listenPreis);
|
|
|
System.out.println("Gewicht: " + gewicht);
|
|
|
System.out.println("Nennleistung: " + kw);
|
|
|
System.out.println("Getriebe: " + getriebe);
|
|
|
System.out.println("Garantie: " + garantie);
|
|
|
System.out.println("Typ: " + typ);
|
|
|
System.out.println("Automatisches Fahren, Stufe: " + autonomStufe);
|
|
|
System.out.println("Maximale Anzahl Personen: " + maxPers);
|
|
|
System.out.println("Bank: " + bank);
|
|
|
}
|
|
|
}
|
|
15.5 Klasse HP |
|
Klasse HP mit Erläuterungen |
|
Im Hauptprogramm (Klasse HP) wird die Nutzung des Vererbungsmechanismus demonstriert. Zuerst mit Hilfe des Konstruktors von VAN, dessen Objekte von zwei übergeordneten Klassen die Attribute übernehmen. Dann mit der Klasse LKW, die von der Superklasse erbt. Abschließend wird ein Objekt von Fahrzeuge instantiiert, das von keiner anderen Klasse erbt. Außerdem sind mehrere Methodenaufrufe entlang der Vererbungsbeziehungen eingefügt. |
|
|
package fahrzeuge;
|
|
|
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
Konstruktor von VAN mit Übergabe der Attributsausprägungen in der Parameterliste. Es entsteht ein Objekt pkw1, das zusätzlich zu den Attributen von VAN die von PKW und Fahrzeuge aufweist. Alle diese Attribute werden im folgenden beschrieben und angezeigt. |
|
|
VAN pkw1 = new VAN(1, false);
|
|
|
String eingabe;
|
|
|
System.out.println("\nKonstruktor mit Klasse VAN");
|
|
|
System.out.println("(geerbt wird von PKW und Fahrzeuge):");
|
|
|
System.out.println();
|
|
|
System.out.println("Ausgabe des Objekts der Klasse VAN im HP \nOHNE DATEN mit Methode aus VAN:\n");
|
|
Diese Methode ist in der Klasse VAN definiert, kann aber von HP aus aufgerufen werden. |
|
|
pkw1.ausgeben();
|
|
Alle Attribute von pkw1 werden im HP beschrieben. |
|
|
System.out.println("\nBeschreiben aller Attribute des Objekts der Klasse VAN im HP\n");
|
|
|
pkw1.fzNr = 1007;
|
|
|
pkw1.listenPreis = 50000;
|
|
|
pkw1.hersteller = "Audi";
|
|
|
pkw1.bez = "Touran";
|
|
|
pkw1.baujahr = 2020;
|
|
|
pkw1.datumZul = "1.1.2020";
|
|
|
pkw1.gewicht = 3.5D;
|
|
|
pkw1.antrieb = 'd';
|
|
|
pkw1.kw = 150;
|
|
|
pkw1.getriebe = "Automatik";
|
|
|
pkw1.garantie = "3 Jahre";
|
|
|
pkw1.typ = "L";
|
|
|
pkw1.autonomStufe = 1;
|
|
|
pkw1.maxPers = 10;
|
|
|
pkw1.bank = true;
|
|
|
System.out.println("\n======Ausgabe des Objekts der Klasse VAN im HP \nMIT DATEN und der Methode aus VAN:\n");
|
|
Diese Methode ist in Klasse VAN definiert. |
|
|
pkw1.ausgeben();
|
|
|
System.out.println("\n=====Methoden in Fahrzeuge aufrufen:=====\n");
|
|
|
pkw1.marktPreis();
|
|
|
System.out.println("Marktpreis festlegen");
|
|
|
eingabe = JOptionPane.showInputDialog("Neuer Marktpreis: ");
|
|
|
float marktPreis = Float.parseFloat(eingabe);
|
|
|
pkw1.marktPreisEintragen(marktPreis);
|
|
|
System.out.println("\n=====Methodeneinsatz für Preiserhöhung=====");
|
|
|
System.out.println("Bisheriger Preis: " + pkw1.listenPreis);
|
|
|
eingabe = JOptionPane.showInputDialog("Gewünschte Preiserhöhung in %: ");
|
|
String-Eingabe wird umgewandelt in Integer-Wert |
|
|
int erhPreis = Integer.parseInt(eingabe);
|
|
|
|
|
|
System.out.println("Alter Preis: " + pkw1.listenPreis);
|
|
|
System.out.println("Gewünschte Erhöhung: " + erhPreis + "%");
|
|
|
|
|
|
pkw1.listenPreis = (pkw1.listenPreis / 100) * (100 + erhPreis);
|
|
|
System.out.println("Neuer Preis: " + pkw1.listenPreis);
|
|
|
|
|
|
System.out.println("\n=====Konstruktor von Klasse LKW=====");
|
|
|
System.out.println("(geerbt wird nur von Fahrzeuge):\n");
|
|
|
|
|
lkw1 der Klasse LKW wird erzeugt. |
|
|
LKW lkw1 = new LKW();
|
|
Objekt beschreiben und Daten ausgeben. |
|
|
System.out.println("Daten von Objekt LKW1: \n");
|
|
|
lkw1.fzNr = 123456;
|
|
|
System.out.println("Fahrzeugnummer: " + lkw1.fzNr);
|
|
|
lkw1.listenPreis = 150299.90F;
|
|
|
System.out.println("Listenpreis: " + lkw1.listenPreis);
|
|
|
lkw1.antrieb = 'd';
|
|
|
|
|
|
if (lkw1.antrieb == 'd')
|
|
|
System.out.println("Antrieb: Diesel");
|
|
|
else if (lkw1.antrieb == 'b')
|
|
|
System.out.println("Antrieb: Benzin");
|
|
|
else if (lkw1.antrieb == 'e')
|
|
|
System.out.println("Antrieb: Elektro");
|
|
|
else if (lkw1.antrieb == 'h')
|
|
|
System.out.println("Antrieb: Hybrid");
|
|
|
else
|
|
|
System.out.println("Antrieb: unbekannt");
|
|
|
|
|
|
lkw1.datumZul = "1.1.2010";
|
|
|
System.out.println("Datum Erstzulassung: " + lkw1.datumZul);
|
|
|
lkw1.gewicht = 7.5D;
|
|
|
System.out.println("Gewicht: " + lkw1.gewicht);
|
|
|
lkw1.ladeKap = 40.5;
|
|
|
System.out.println("Ladekapazität: " + lkw1.ladeKap);
|
|
|
lkw1.zahlAchsen = 6;
|
|
|
System.out.println("Anzahl Achsen: " + lkw1.zahlAchsen);
|
|
|
lkw1.zustand = "Schlecht";
|
|
|
System.out.println("Zustand des LKW: " + lkw1.zustand);
|
|
Neues Objekt lkw2 durch Datenübergabe an Konstruktor. |
|
|
LKW lkw2 = new LKW(12345, 50000.60F, "BMW", "xyzhybrid", 2022, "1.1.2022", 1500, 'h', 240, "Automatik", 40.5, 4, "Toll");
|
|
|
|
|
|
System.out.println("\nDaten von Objekt LKW2: \n");
|
|
|
System.out.println("Fahrzeugnummer: " + lkw2.fzNr);
|
|
|
System.out.println("Listenpreis2: " + lkw2.listenPreis);
|
|
|
System.out.println("Antrieb: " + lkw2.antrieb);
|
|
|
System.out.println("Datum Erstzulassung: " + lkw2.datumZul);
|
|
|
System.out.println("Gewicht: " + lkw2.gewicht);
|
|
|
System.out.println("Ladekapazität: " + lkw2.ladeKap);
|
|
|
System.out.println("Anzahl Achsen: " + lkw2.zahlAchsen);
|
|
|
System.out.println("Zustand des LKW: " + lkw2.zustand);
|
|
|
|
|
|
System.out.println("\n=====Konstruktor von Klasse Fahrzeuge=====");
|
|
|
System.out.println("(nichts wird geerbt):\n");
|
|
Der Konstruktor von Fahrzeuge erzeugt ein Objekt ohne die Attribute und Methoden der Subklassen. |
|
|
Fahrzeuge fz1 = new Fahrzeuge();
|
|
|
fz1.datumZul = "1.1.2016";
|
|
|
System.out.println("Zulassung: " + fz1.datumZul);
|
|
|
fz1.fzNr = 12345;
|
|
|
System.out.println("Fahrzeugnummer: " + fz1.fzNr);
|
|
|
fz1.antrieb = 'b';
|
|
|
System.out.println("Antrieb: " + fz1.antrieb);
|
|
|
fz1.listenPreis = 120900.00F;
|
|
|
System.out.println("Preis: " + fz1.listenPreis);
|
|
|
fz1.gewicht = 2.0D;
|
|
|
System.out.println("Gewicht: " + fz1.gewicht);
|
|
|
fz1.kw = 140;
|
|
|
System.out.println("Motorleistung (kW): " + fz1.kw);
|
|
|
fz1.getriebe = "Schalter";
|
|
|
System.out.println("Getriebe: " + fz1.getriebe);
|
|
|
fz1.baujahr = 2020;
|
|
|
System.out.println("Baujahr: " + fz1.baujahr);
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package fahrzeuge;
|
|
|
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
VAN pkw1 = new VAN(1, false);
|
|
|
String eingabe;
|
|
|
System.out.println("\nKonstruktor mit Klasse VAN");
|
|
|
System.out.println("(geerbt wird von PKW und Fahrzeuge):");
|
|
|
System.out.println();
|
|
|
System.out.println("Ausgabe des Objekts der Klasse VAN im HP \nOHNE DATEN mit Methode aus VAN:\n");
|
|
|
pkw1.ausgeben();
|
|
|
System.out.println("\nBeschreiben aller Attribute des Objekts der Klasse VAN im HP\n");
|
|
|
pkw1.fzNr = 1007;
|
|
|
pkw1.listenPreis = 50000;
|
|
|
pkw1.hersteller = "Audi";
|
|
|
pkw1.bez = "Touran";
|
|
|
pkw1.baujahr = 2020;
|
|
|
pkw1.datumZul = "1.1.2020";
|
|
|
pkw1.gewicht = 3.5D;
|
|
|
pkw1.antrieb = 'd';
|
|
|
pkw1.kw = 150;
|
|
|
pkw1.getriebe = "Automatik";
|
|
|
pkw1.garantie = "3 Jahre";
|
|
|
pkw1.typ = "L";
|
|
|
pkw1.autonomStufe = 1;
|
|
|
pkw1.maxPers = 10;
|
|
|
pkw1.bank = true;
|
|
|
System.out.println("\n======Ausgabe des Objekts der Klasse VAN im HP \nMIT DATEN und der Methode aus VAN:\n");
|
|
|
pkw1.ausgeben();
|
|
|
System.out.println("\n=====Methoden in Fahrzeuge aufrufen:=====\n");
|
|
|
pkw1.marktPreis();
|
|
|
System.out.println("Marktpreis festlegen");
|
|
|
eingabe = JOptionPane.showInputDialog("Neuer Marktpreis: ");
|
|
|
float marktPreis = Float.parseFloat(eingabe);
|
|
|
pkw1.marktPreisEintragen(marktPreis);
|
|
|
System.out.println("\n=====Methodeneinsatz für Preiserhöhung=====");
|
|
|
System.out.println("Bisheriger Preis: " + pkw1.listenPreis);
|
|
|
eingabe = JOptionPane.showInputDialog("Gewünschte Preiserhöhung in %: ");
|
|
|
int erhPreis = Integer.parseInt(eingabe);
|
|
|
System.out.println("Alter Preis: " + pkw1.listenPreis);
|
|
|
System.out.println("Gewünschte Erhöhung: " + erhPreis + "%");
|
|
|
pkw1.listenPreis = (pkw1.listenPreis / 100) * (100 + erhPreis);
|
|
|
System.out.println("Neuer Preis: " + pkw1.listenPreis);
|
|
|
System.out.println("\n=====Konstruktor von Klasse LKW=====");
|
|
|
System.out.println("(geerbt wird nur von Fahrzeuge):\n");
|
|
|
Objekt lkw1 der Klasse LKW wird erzeugt.
|
|
|
LKW lkw1 = new LKW();
|
|
|
System.out.println("Daten von Objekt LKW1: \n");
|
|
|
lkw1.fzNr = 123456;
|
|
|
System.out.println("Fahrzeugnummer: " + lkw1.fzNr);
|
|
|
lkw1.listenPreis = 150299.90F;
|
|
|
System.out.println("Listenpreis: " + lkw1.listenPreis);
|
|
|
lkw1.antrieb = 'd';
|
|
|
if (lkw1.antrieb == 'd')
|
|
|
System.out.println("Antrieb: Diesel");
|
|
|
else if (lkw1.antrieb == 'b')
|
|
|
System.out.println("Antrieb: Benzin");
|
|
|
else if (lkw1.antrieb == 'e')
|
|
|
System.out.println("Antrieb: Elektro");
|
|
|
else if (lkw1.antrieb == 'h')
|
|
|
System.out.println("Antrieb: Hybrid");
|
|
|
else
|
|
|
System.out.println("Antrieb: unbekannt");
|
|
|
lkw1.datumZul = "1.1.2010";
|
|
|
System.out.println("Datum Erstzulassung: " + lkw1.datumZul);
|
|
|
lkw1.gewicht = 7.5D;
|
|
|
System.out.println("Gewicht: " + lkw1.gewicht);
|
|
|
lkw1.ladeKap = 40.5;
|
|
|
System.out.println("Ladekapazität: " + lkw1.ladeKap);
|
|
|
lkw1.zahlAchsen = 6;
|
|
|
System.out.println("Anzahl Achsen: " + lkw1.zahlAchsen);
|
|
|
lkw1.zustand = "Schlecht";
|
|
|
System.out.println("Zustand des LKW: " + lkw1.zustand);
|
|
|
LKW lkw2 = new LKW(12345, 50000.60F, "BMW", "xyzhybrid", 2022, "1.1.2022", 1500, 'h', 240, "Automatik", 40.5, 4, "Toll");
|
|
|
System.out.println("\nDaten von Objekt LKW2: \n");
|
|
|
System.out.println("Fahrzeugnummer: " + lkw2.fzNr);
|
|
|
System.out.println("Listenpreis2: " + lkw2.listenPreis);
|
|
|
System.out.println("Antrieb: " + lkw2.antrieb);
|
|
|
System.out.println("Datum Erstzulassung: " + lkw2.datumZul);
|
|
|
System.out.println("Gewicht: " + lkw2.gewicht);
|
|
|
System.out.println("Ladekapazität: " + lkw2.ladeKap);
|
|
|
System.out.println("Anzahl Achsen: " + lkw2.zahlAchsen);
|
|
|
System.out.println("Zustand des LKW: " + lkw2.zustand);
|
|
|
System.out.println("\n=====Konstruktor von Klasse Fahrzeuge=====");
|
|
|
System.out.println("(nichts wird geerbt):\n");
|
|
|
Fahrzeuge fz1 = new Fahrzeuge();
|
|
|
fz1.datumZul = "1.1.2016";
|
|
|
System.out.println("Zulassung: " + fz1.datumZul);
|
|
|
fz1.fzNr = 12345;
|
|
|
System.out.println("Fahrzeugnummer: " + fz1.fzNr);
|
|
|
fz1.antrieb = 'b';
|
|
|
System.out.println("Antrieb: " + fz1.antrieb);
|
|
|
fz1.listenPreis = 120900.00F;
|
|
|
System.out.println("Preis: " + fz1.listenPreis);
|
|
|
fz1.gewicht = 2.0D;
|
|
|
System.out.println("Gewicht: " + fz1.gewicht);
|
|
|
fz1.kw = 140;
|
|
|
System.out.println("Motorleistung (kW): " + fz1.kw);
|
|
|
fz1.getriebe = "Schalter";
|
|
|
System.out.println("Getriebe: " + fz1.getriebe);
|
|
|
fz1.baujahr = 2020;
|
|
|
System.out.println("Baujahr: " + fz1.baujahr);
|
|
|
}
|
|
|
}
|
|
15.6 Programmlauf |
|
Folgende zwei Eingabefenster kommen zum Einsatz: |
|

|
|
|
|
|

|
|
|
|
Bildschirmausgabe: |
|
|
Konstruktor mit Klasse VAN
|
|
|
(geerbt wird von PKW und Fahrzeuge):
|
|
|
|
|
|
Ausgabe des Objekts der Klasse VAN im HP
|
|
|
OHNE DATEN mit Methode aus VAN:
|
|
|
|
|
|
Inventarnummer: 0
|
|
|
Hersteller: null
|
|
|
Bezeichnung: null
|
|
|
Baujahr: 0
|
|
|
Datum der Erstzulassung: null
|
|
|
Antriebsart: n
|
|
|
Listenpreis: 0.0
|
|
|
Gewicht: 0.0
|
|
|
Nennleistung: 0
|
|
|
Getriebe: null
|
|
|
Garantie: nicht erfasst
|
|
|
Typ: null
|
|
|
Automatisches Fahren, Stufe: 0
|
|
|
Maximale Anzahl Personen: 1
|
|
|
Bank: false
|
|
|
|
|
|
Beschreiben aller Attribute des Objekts der Klasse VAN im HP
|
|
|
|
|
|
|
|
|
======Ausgabe des Objekts der Klasse VAN im HP
|
|
|
MIT DATEN und der Methode aus VAN:
|
|
|
|
|
|
Inventarnummer: 1007
|
|
|
Hersteller: VW
|
|
|
Bezeichnung: Touran
|
|
|
Baujahr: 2020
|
|
|
Datum der Erstzulassung: 1.1.2020
|
|
|
Antriebsart: d
|
|
|
Listenpreis: 50000.0
|
|
|
Gewicht: 3.5
|
|
|
Nennleistung: 150
|
|
|
Getriebe: Automatik
|
|
|
Garantie: 3 Jahre
|
|
|
Typ: L
|
|
|
Automatisches Fahren, Stufe: 1
|
|
|
Maximale Anzahl Personen: 10
|
|
|
Bank: true
|
|
|
|
|
|
=====Methoden in Fahrzeuge aufrufen:=====
|
|
|
|
|
|
Derzeitiger Marktpreis vor EINTRAGEN: 0.0
|
|
|
Marktpreis festlegen
|
|
|
Derzeitiger Marktpreis nach EINTRAGEN: 40000.0
|
|
|
|
|
|
=====Methodeneinsatz für Preiserhöhung=====
|
|
|
Bisheriger Preis: 50000.0
|
|
|
Alter Preis: 50000.0
|
|
|
Gewünschte Erhöhung: 10%
|
|
|
Neuer Preis: 55000.0
|
|
|
|
|
|
=====Konstruktor von Klasse LKW=====
|
|
|
(geerbt wird nur von Fahrzeuge):
|
|
|
|
|
|
Daten von Objekt LKW1:
|
|
|
|
|
|
Fahrzeugnummer: 123456
|
|
|
Listenpreis: 150299.9
|
|
|
Antrieb: Diesel
|
|
|
Datum Erstzulassung: 1.1.2010
|
|
|
Gewicht: 7.5
|
|
|
Ladekapazität: 40.5
|
|
|
Anzahl Achsen: 6
|
|
|
Zustand des LKW: Schlecht
|
|
|
|
|
|
Daten von Objekt LKW2:
|
|
|
|
|
|
Fahrzeugnummer: 12345
|
|
|
Listenpreis2: 50000.6
|
|
|
Antrieb: h
|
|
|
Datum Erstzulassung: 1.1.2022
|
|
|
Gewicht: 1500.0
|
|
|
Ladekapazität: 40.5
|
|
|
Anzahl Achsen: 4
|
|
|
Zustand des LKW: Toll
|
|
|
|
|
|
=====Konstruktor von Klasse Fahrzeuge=====
|
|
|
(nichts wird geerbt):
|
|
|
|
|
|
Zulassung: 1.1.2016
|
|
|
Fahrzeugnummer: 12345
|
|
|
Antrieb: b
|
|
|
Preis: 120900.0
|
|
|
Gewicht: 2.0
|
|
|
Motorleistung (kW): 140
|
|
|
Getriebe: Schalter
|
|
|
Baujahr: 2020
|
|
15.7 Projektbeschreibung |
|
15.7.1 Ziel des Projekts |
|
Das Projekt HS7 dient der weiteren Einführung in die objektorientierte Programmierung mit Java. Im Mittelpunkt stehen folgende Konzepte: |
|
- Klassen und Objekte
- Vererbung
- Konstruktoren
- geerbte Attribute und Methoden
- Spezialisierung von Klassen
- einfache Methodenaufrufe
|
|
Das Projekt zeigt anhand verschiedener Fahrzeugtypen, wie gemeinsame Eigenschaften in einer Oberklasse zusammengefasst und von Unterklassen übernommen werden können. |
|
15.7.2 Aufbau des Projekts |
|
Das Projekt besteht aus fünf Klassen: |
|
|
|
| Klasse |
Bedeutung |
| Fahrzeuge |
Oberklasse mit allgemeinen Fahrzeugdaten |
| PKW |
Unterklasse von Fahrzeuge |
| VAN |
Unterklasse von PKW |
| LKW |
Unterklasse von Fahrzeuge |
| HP |
Hauptprogramm mit main() |
| |
|
|
Zur Vererbungsstruktur vgl. Kapitelanfang. Es gilt also: |
|
- Ein
PKW ist ein spezielles Fahrzeug.
- Ein
VAN ist ein spezieller PKW.
- Ein
LKW ist ebenfalls ein spezielles Fahrzeug.
|
|
D.h., Fahrzeuge ist Superklasse von PKW und LKW, PKW ist Superklasse von VAN. |
|
15.7.3 Beschreibung der einzelnen Klassen |
|
Klasse Fahrzeuge |
|
Die Klasse Fahrzeuge bildet die Oberklasse des Projekts. Sie enthält allgemeine Attribute, die für alle Fahrzeuge gelten, zum Beispiel: |
|
- int fzNr;
- float listenPreis;
- String hersteller;
- String bez;
|
|
Zusätzlich enthält die Klasse: |
|
|
private float marktPreis;
|
|
Dieses Attribut ist privat und kann deshalb nicht direkt von außen verändert werden. Der Zugriff erfolgt über Methoden: |
|
- void marktPreis()
- void marktPreisEintragen(float marktPreis)
|
|
Damit wird das Prinzip der Kapselung vorbereitet. |
|
Klasse PKW |
|
Die Klasse PKW erbt von Fahrzeuge: |
|
|
public class PKW extends Fahrzeuge
|
|
Zusätzlich besitzt ein PKW weitere Eigenschaften: |
|
|
String garantie;
|
|
|
String typ;
|
|
|
int autonomStufe;
|
|
Außerdem enthält die Klasse die Methode: |
|
|
void komfortAnzeige()
|
|
Damit wird gezeigt, dass Unterklassen eigene Methoden ergänzen können. |
|
Klasse VAN |
|
Die Klasse VAN erweitert die Klasse PKW: |
|
|
public class VAN extends PKW
|
|
Ein VAN besitzt zusätzliche Attribute: |
|
|
int maxPers;
|
|
|
boolean bank;
|
|
Die Klasse enthält: |
|
- einen Konstruktor mit Parametern
- die Methode ausgeben()
|
|
Die Methode ausgeben() gibt sowohl eigene als auch geerbte Attribute aus. Dadurch wird sichtbar, dass ein Objekt der Klasse VAN alle Eigenschaften der Oberklassen besitzt. |
|
Klasse LKW |
|
Die Klasse LKW erbt direkt von Fahrzeuge: |
|
|
public class LKW extends Fahrzeuge
|
|
Zusätzliche Attribute sind: |
|
|
double ladeKap;
|
|
|
int zahlAchsen;
|
|
|
String zustand;
|
|
Die Klasse besitzt: |
|
- einen parameterlosen Konstruktor
- einen Konstruktor mit vielen Parametern
|
|
Damit wird der Einsatz verschiedener Konstruktoren demonstriert. |
|
Klasse HP |
|
Die Klasse HP enthält die Methode: |
|
|
public static void main(String[] args)
|
|
Sie dient als Hauptprogramm zum Testen aller Klassen. Im Hauptprogramm werden: |
|
- Objekte erzeugt
- Attribute beschrieben
- Methoden aufgerufen
- Konstruktoren getestet
- Ausgaben auf der Konsole erzeugt
|
|
15.7.4 Ablauf des Programms |
|
Erzeugen eines VAN-Objekts |
|
|
VAN van1 = new VAN(1, false);
|
|
Zunächst werden nur die Attribute gesetzt, die im Konstruktor von VAN vorkommen. Danach erfolgt eine Ausgabe ohne weitere Daten. |
|
Beschreiben der geerbten Attribute |
|
Anschließend werden zahlreiche geerbte Attribute beschrieben: |
|
|
van1.fzNr = 1007;
|
|
|
van1.hersteller = "VW";
|
|
|
van1.listenPreis = 50000;
|
|
Damit wird gezeigt, dass ein VAN auf geerbte Eigenschaften zugreifen kann. |
|
Methodenaufrufe |
|
Es werden Methoden aus der Oberklasse Fahrzeuge verwendet: |
|
|
van1.marktPreis();
|
|
|
van1.marktPreisEintragen(marktPreis);
|
|
Dadurch wird deutlich: Unterklassen erben nicht nur Attribute, sondern auch Methoden. |
|
Preisänderung |
|
Im Hauptprogramm wird eine prozentuale Preiserhöhung berechnet. Dabei wird der Umgang mit Benutzereingaben und Berechnungen gezeigt. |
|
Arbeiten mit LKW-Objekten |
|
Es werden zwei LKW-Objekte erzeugt: |
|
|
LKW lkw1 = new LKW();
|
|
|
LKW lkw2 = new LKW(...);
|
|
Dadurch wird der Unterschied zwischen: |
|
- parameterlosen Konstruktoren
- Konstruktoren mit Parametern
|
|
sichtbar. |
|
Arbeiten mit einem Fahrzeuge-Objekt |
|
Zum Schluss wird ein Objekt der Oberklasse direkt erzeugt: |
|
|
Fahrzeuge fz1 = new Fahrzeuge();
|
|
Dadurch wird gezeigt: |
|
- Auch Oberklassen können selbst Objekte erzeugen.
- Unterklassen erweitern lediglich die vorhandenen Eigenschaften.
|
|
16 Projekt HS7a |
|
Hier nun, ganz auf den Punkt gebracht, ein Beispiel zu Override und Overload. Bei den beiden Klassen handelt es sich um gekürzte Versionen von HS7. |
|
|
|
16.1 Klasse HP |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
PKW p1 = new PKW();
|
|
|
|
|
|
p1.fzNr = 1001;
|
|
|
p1.hersteller = "VW";
|
|
|
p1.sitzplaetze = 5;
|
|
|
|
|
|
System.out.println("--- Normale Ausgabe ---");
|
|
|
p1.ausgeben();
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
|
System.out.println("--- Ausgabe mit Überschrift ---");
|
|
|
p1.ausgeben("Daten des PKW:");
|
|
|
}
|
|
|
}
|
|
16.2 Klasse Fahrzeuge |
|
|
package fahrzeuge;
|
|
|
|
|
|
class Fahrzeuge {
|
|
|
int fzNr;
|
|
|
String hersteller;
|
|
|
|
|
|
void ausgeben() {
|
|
|
System.out.println("Fahrzeugnummer: " + fzNr);
|
|
|
System.out.println("Hersteller: " + hersteller);
|
|
|
}
|
|
|
}
|
|
16.3 Klasse PKW |
|
|
package fahrzeuge;
|
|
|
|
|
|
class PKW extends Fahrzeuge {
|
|
|
int sitzplaetze;
|
|
Override: Methode aus Fahrzeuge wird überschrieben |
|
|
@Override
|
|
|
void ausgeben() {
|
|
|
System.out.println("Ausgabe aus der Klasse PKW:");
|
|
|
System.out.println("Fahrzeugnummer: " + fzNr);
|
|
|
System.out.println("Hersteller: " + hersteller);
|
|
|
System.out.println("Sitzplätze: " + sitzplaetze);
|
|
|
}
|
|
Overload: gleicher Methodenname, aber anderer Parameter |
|
|
void ausgeben(String titel) {
|
|
|
System.out.println(titel);
|
|
|
ausgeben();
|
|
|
}
|
|
|
}
|
|
16.4 Programmlauf |
|
|
--- Normale Ausgabe ---
|
|
|
Ausgabe aus der Klasse PKW:
|
|
|
Fahrzeugnummer: 1001
|
|
|
Hersteller: VW
|
|
|
Sitzplätze: 5
|
|
|
|
|
|
--- Ausgabe mit Überschrift ---
|
|
|
Daten des PKW:
|
|
|
Ausgabe aus der Klasse PKW:
|
|
|
Fahrzeugnummer: 1001
|
|
|
Hersteller: VW
|
|
|
Sitzplätze: 5
|
|
16.5 Exkurs: Override vs. Overload |
|
Die Oberklasse Fahrzeuge enthält zwei Attribute und eine Methode ausgeben(). Die Klasse PKW enthält ebenfalls zwei Attribute und eine Methode ausgeben(). Die Methode gibt die Daten des Fahrzeugs aus. |
|
Override - Überschreiben einer Methode |
|
Die Oberklasse Fahrzeuge besitzt also bereits die Methode void ausgeben(). In PKW wird dieselbe Methode nochmals geschrieben: |
|
- @Override
- void ausgeben()
|
|
Das wird Override genannt. Die Methode der Oberklasse wird in der Subklasse durch eine neue Version ersetzt. Damit können bei einer Ausgabe in PKW die Attribute von Fahrzeuge ergänzt werden. Die Methode wird neu definiert, erweitert und an die Unterklasse angepasst. |
|
Die optionale Angabe @Override ist eine sog. Annotation. Sie bedeutet: "Diese Methode überschreibt eine Methode der Oberklasse." Der Compiler prüft dadurch, ob wirklich eine passende Methode existiert, ob der Methodenname korrekt geschrieben wurde und ob die Parameter identisch sind. |
|
Overload - Überladen einer Methode |
|
Nun gibt es in PKW zusätzlich: |
|
|
void ausgeben(String titel)
|
|
Damit existieren zwei gleichnamige Methoden, die sich in den Parametern untescheiden. Dies wird Overload genannt. Die Idee hinter Overload ist, dass eine Methode unterschiedlich verwendet werden kann. Hier z.B. einmal so: |
|
|
p1.ausgeben();
|
|
und zum anderen so: |
|
|
p1.ausgeben("Daten des PKW:");
|
|
Der Methodenname bleibt also gleich, aber die Nutzung wird erweitert. Welche Methode aufgerufen wird, entscheidet Java anhand der Parameter. |
|
17 Projekt HS8 - Kapselung |
|
Hier werden an einfachen Beispielen die Möglichkeiten gezeigt, den Zugriff auf Instanzattribute, Variablen und Methoden zu kontrollieren. Vgl. auch Abschnitt 4.1. |
|
|
|
17.1 Klasse HP |
|
Klasse HP mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
S1 wird mit dem Standardkonstruktor erzeugt. |
|
|
Stud s1 = new Stud();
|
|
|
System.out.println("Leeres Objekt von HP aus mit Methode aus Stud ausgeben:");
|
|
Folgendes klappt, weil die Methode ausgeben() in Stud paketsichtbar ist. Wird kein Modifizierer angegeben, gilt in Java die Paketsichtbarkeit. Da HP und Stud beide im Package hochschule liegen, darf HP diese Methode aufrufen. Auch protected wäre hier erlaubt. Würde man ausgeben() dagegen private machen, wäre die Methode von HP aus nicht sichtbar. Ausprobieren!! |
|
|
s1.ausgeben();
|
|
S0 wird erzeugt (instantiiert) und über den Konstruktor mit Daten versorgt. |
|
|
Stud s0 = new Stud("123", "Maier", "Klara", 5, "21.09.2002");
|
|
|
System.out.println("\nBeschriebenes Objekt von HP aus mit Methode aus Stud ausgeben:");
|
|
Folgendes klappt wiederum, weil der Zugriff aus demselben Package kommt und der Modifizierer der Methode ausgeben() dies erlaubt. |
|
|
s0.ausgeben();
|
|
Das Attribut gebTag kann wegen Sichtbarkeit public abgefragt werden. |
|
|
System.out.println("\nDie Ausgabe des Geburtstags klappt: " + s0.gebTag);
|
|
Zwei Fehlschläge, verursacht durch den Sichtbarkeitsmodizierer. |
|
|
System.out.println("\nDas klappt nicht: s0.name= 'Erwin'");
|
|
|
System.out.println("\nDas auch nicht: System.out.println(s0.name ohne Setter= + s0.name)");
|
|
"Getter" hilft. |
|
|
System.out.println("\nDirekte Abfrage s0.name mit Getter-Methode: " + s0.getName());
|
|
"Setter" ebenso. |
|
|
System.out.println("\nDirektes Beschreiben s0.name mit Setter-Methode (Millifranz): ");
|
|
|
s0.setName("Millifranz");
|
|
|
|
|
|
System.out.println("\nGeänderter Name: " + s0.getName());
|
|
|
}
|
|
|
}
|
|
Klasse HP ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s1 = new Stud();
|
|
|
System.out.println("Leeres Objekt von HP aus mit Methode aus Stud ausgeben:");
|
|
|
s1.ausgeben();
|
|
|
Stud s0 = new Stud("123", "Maier", "Klara", 5, "21.09.2002");
|
|
|
|
|
|
System.out.println("\nBeschriebenes Objekt von HP aus mit Methode aus Stud ausgeben:");
|
|
|
s0.ausgeben();
|
|
|
|
|
|
System.out.println("\nDie Ausgabe des Geburtstags klappt: " + s0.gebTag);
|
|
|
|
|
|
System.out.println("\nDas klappt nicht: s0.name= 'Erwin'");
|
|
|
System.out.println("\nDas auch nicht: System.out.println(s0.name ohne Setter= + s0.name)");
|
|
|
|
|
|
System.out.println("\nDirekte Abfrage s0.name mit Getter-Methode: " + s0.getName());
|
|
|
|
|
|
System.out.println("\nDirektes Beschreiben s0.name mit Setter-Methode (Millifranz): ");
|
|
|
s0.setName("Millifranz");
|
|
|
|
|
|
System.out.println("\nGeänderter Name: " + s0.getName());
|
|
|
}
|
|
|
}
|
|
17.2 Klasse Stud |
|
Klasse Stud mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
|
private String mNr; // Matrikelnummer
|
|
|
private String name; // privat: Zugriff nur über Getter/Setter
|
|
|
String vName; // Paketsichtbar
|
|
|
private int anzSem; // Erreichtes Semester
|
|
|
public String gebTag; // Geburtstag
|
|
Konstruktor mit Parameterübergabe. Er wird vom HP aufgerufen, in der Klasse Stud (natürlich) ausgeführt, deshalb spielen die Sichtbarkeitsmodifizierer keine Rolle |
|
|
public Stud(String mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr = mNr;
|
|
|
this.name = name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
}
|
|
Standardkonstruktor. |
|
|
public Stud() {
|
|
|
}
|
|
Getter-Methode. Mit ihr ist es möglich, trotz Sichtbarkeitsmodifizierer protected das jeweilige Attribut abzufragen. Siehe HP. |
|
|
public String getName() {
|
|
|
return name;
|
|
|
}
|
|
Setter-Methode. Mit ihr ist es möglich, trotz Sichtbarkeitsmodifizierer protected das jeweilige Attribut zu beschreiben. Siehe HP. |
|
|
public void setName(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
Methode zum Ausgeben der Daten eines Objekts. |
|
|
void ausgeben() {
|
|
|
System.out.println("\nMatrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse Stud ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
public class Stud {
|
|
|
private String mNr; // Matrikelnummer
|
|
|
private String name; // privat: Zugriff nur über Getter/Setter
|
|
|
String vName; // Paketsichtbar
|
|
|
private int anzSem; // Erreichtes Semester
|
|
|
public String gebTag; // Geburtstag
|
|
|
public Stud(String mNr, String name, String vName, int anzSem, String gebTag) {
|
|
|
this.mNr = mNr;
|
|
|
this.name = name;
|
|
|
this.vName = vName;
|
|
|
this.anzSem = anzSem;
|
|
|
this.gebTag = gebTag;
|
|
|
}
|
|
|
public Stud() {
|
|
|
}
|
|
|
public String getName() {
|
|
|
return name;
|
|
|
}
|
|
|
public void setName(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
|
void ausgeben() {
|
|
|
System.out.println("\nMatrikelnummer: " + mNr);
|
|
|
System.out.println("Name: " + name);
|
|
|
System.out.println("Vorname:" + vName);
|
|
|
System.out.println("Erreichtes Semester: " + anzSem);
|
|
|
System.out.println("Geburtstag: " + gebTag);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
17.3 Programmlauf |
|
|
Leeres Objekt von HP aus mit Methode aus Stud ausgeben:
|
|
|
|
|
|
Matrikelnummer: null
|
|
|
Name: null
|
|
|
Vorname:null
|
|
|
Erreichtes Semester: 0
|
|
|
Geburtstag: null
|
|
|
|
|
|
Beschriebenes Objekt von HP aus mit Methode aus Stud ausgeben:
|
|
|
|
|
|
Matrikelnummer: 123
|
|
|
Name: Maier
|
|
|
Vorname:Klara
|
|
|
Erreichtes Semester: 5
|
|
|
Geburtstag: 21.09.2002
|
|
|
|
|
|
Die Ausgabe des Geburtstags klappt: 21.09.2002
|
|
|
|
|
|
Das klappt nicht: s0.name= 'Erwin'
|
|
|
|
|
|
Das auch nicht: System.out.println(s0.name ohne Setter= + s0.name)
|
|
|
|
|
|
Direkte Abfrage s0.name mit Getter-Methode: Maier
|
|
|
|
|
|
Direktes Beschreiben s0.name mit Setter-Methode (Millifranz):
|
|
17.4 Projektbeschreibung |
|
HS8 behandelt vor allem: |
|
- Sichtbarkeit von Attributen
- Zugriffsmodifizierer
- Getter- und Setter-Methoden
- kontrollierten Zugriff auf Objektdaten
|
|
Es wird gezeigt, dass Attribute nicht immer direkt von außen verändert werden können sollen. Im Projekt gibt es wieder zwei Klassen: |
|
- HP als Hauptprogramm
- Stud als Datenklasse für Studierende
|
|
Sichtbarkeit |
|
Im Unterschied zu früheren Projekten sind die Attribute jetzt nicht mehr alle gleich sichtbar. In Stud kommen verschiedene Zugriffsarten vor: |
|
- private String mNr;
- protected String name;
- String vName;
- private int anzSem;
- public String gebTag;
|
|
Etwas konkreter: |
|
- private mit private String mNr; und private int anzSem; Diese Attribute dürfen nur innerhalb der Klasse Stud direkt benutzt werden.
|
|
Von HP aus wäre also so etwas nicht erlaubt: |
|
|
s0.mNr = "999";
|
|
oder |
|
|
System.out.println(s0.anzSem);
|
|
- protected mit protected String name; "protected" ist geschützter als public, aber weniger streng als private. Es bedeutet also, sichtbar im selben Package und in Unterklassen, auch wenn diese in einem anderen Package liegen.
|
|
Da HP im gleichen Package hochschule liegt, ist der Zugriff hier möglich. Das Projekt zeigt aber zugleich, dass man den Zugriff besser über Methoden steuern kann. |
|
- Paketsichtbar mit dem Beispiel String vName;
|
|
Ohne Modifizierer ist das Attribut im gleichen Package sichtbar. |
|
- public mit public String gebTag; Dieses Attribut darf von überall direkt benutzt werden. Darum funktioniert in HP System.out.println(s0.gebTag);
|
|
Die Sichtbarkeitsmodifizierer zusammengefasst: |
|
|
|
| Modifizierer |
Bedeutung |
| private |
Nur innerhalb der Klasse sichtbar |
| kein Modifizierer |
Paketsichtbar |
| protected |
Paket + Unterklassen |
| public |
Überall sichtbar |
| |
|
|
Getter und Setter |
|
Wichtige Komponenten in HS8 sind Getter und Setter: |
|
|
public String getName() { //Getter
|
|
|
return name;
|
|
|
}
|
|
und |
|
|
public void setName(String name) {//Setter
|
|
|
this.name = name;
|
|
|
}
|
|
Damit wird name nicht direkt, sondern über Methoden gelesen und geändert. s0.getName() liefert den aktuellen Namen zurück. s0.setName("Millifranz"); ändert den Namen kontrolliert. Damit kann man später Regeln einbauen, zum Beispiel: |
|
|
public void setName(String name) {
|
|
|
if (name != null amp;amp; !name.isBlank()) {
|
|
|
this.name = name;
|
|
|
}
|
|
|
}
|
|
Dann kann nicht einfach irgendein ungültiger Wert gesetzt werden. Das ist ein wichtiger Schritt in Richtung Kapselung. |
|
18 Projekt HS9 |
|
Hier geht es um folgende Aspekte: |
|
- eine Assoziation zwischen Klassen umzusetzen
- den Umgang mit Objektreferenzen zu üben
- eine 1:n-Beziehung in Java zu modellieren
|
|
Dies erfolgt am Beispiel der Verwaltung von Studierenden und ihren Noten. Die Klassen sind: |
|
- Stud (Studierende) mit Matrikelnummer, Name, Vorname
- Noten mit Fach und Note
|
|
Die Assoziation soll mit Objektreferenzen umgesetzt werden. |
|
|
|
18.1 Klasse HP |
|
|
package hochschule;
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
Konstruktor für Studierendenobjekt |
|
|
Stud s1 = new Stud();
|
|
|
s1.mNr = 1001;
|
|
|
s1.name = "Maier";
|
|
|
s1.vName = "Paul";
|
|
Noten erzeugen |
|
|
Note n1 = new Note("Mathe", 2, s1);
|
|
|
Note n2 = new Note("Informatik", 1, s1);
|
|
|
Noten n3 = new Noten("GPM", 3, s1);
|
|
Verknüpfen von Studierenden und Noten |
|
|
s1.addNote(n1);
|
|
|
s1.addNote(n2);
|
|
|
s1.addNote(n3);
|
|
Ausgabe |
|
|
System.out.println(s1.name + " hat folgende Noten:");
|
|
|
for (Noten n : s1.noten) {
|
|
|
System.out.println(n.fach + ": " + n.note);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
18.2 Klasse Stud |
|
Klasse Stud mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
Für die Verwaltung mehrerer Objekte werden Klassen aus der Java-Bibliothek importiert. |
|
|
Import java.util.ArrayList;
|
|
|
//import java.util.List;
|
|
|
|
|
|
class Stud {
|
|
|
int mNr;
|
|
|
String name;
|
|
|
String vName;
|
|
Hier wird eine Liste für Noten angelegt. Die Bedeutung im Einzelnen: - List<Noten> "List" ist ein allgemeiner Datentyp für Listen. <Noten> bedeutet: In dieser Liste dürfen nur Objekte der Klasse Noten gespeichert werden. Die Liste funktioniert ähnlich wie ein flexibles Array. Der Unterschied: Die Größe muss nicht vorher festgelegt werden. noten: Bezeichnung der Liste. = new ArrayList<>() Mit "new" wird die Liste tatsächlich erzeugt. ArrayList ist eine konkrete Implementierung von List. In die Liste werdenn später Notenobjekte eingefügt. Anfangs ist die Liste leer. |
|
|
List<Noten> noten = new ArrayList<>();
|
|
Methode zum Hinzufügen einer Note Der Parameter n ist ein Objekt der Klasse Noten. noten.add(n); fügt dieses Objekt der Liste hinzu. |
|
|
void addNote(Note n) {
|
|
|
noten.add(n);
|
|
|
}
|
|
|
}
|
|
Klasse Stud ohne Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
class Stud {
|
|
|
int mNr;
|
|
|
String name;
|
|
|
String vName;
|
|
|
|
|
|
List<Noten> noten = new ArrayList<>();
|
|
|
|
|
|
void addNote(Note n) {
|
|
|
noten.add(n);
|
|
|
}
|
|
|
}
|
|
18.3 Klasse Noten |
|
|
package hochschule;
|
|
|
|
|
|
class Noten {
|
|
|
String fach;
|
|
|
int note;
|
|
|
Stud student;
|
|
Konstruktor mit Parameterübergabe. |
|
|
public Noten(String fach, int note, Stud student) {
|
|
|
this.fach = fach;
|
|
|
this.note = note;
|
|
|
this.student = student;
|
|
|
}
|
|
|
}
|
|
18.4 Programmlauf |
|
|
Maier hat folgende Noten:
|
|
|
Mathe: 2
|
|
|
Informatik: 1
|
|
|
GPM: 3
|
|
Dabei bedeutet GPM "Geschäftsprozessmanagement". |
|
18.5 Erläuterungen zum Programm |
|
For-Each-Schleife |
|
Im Programm oben finden sich folgende Zeilen: |
|
|
for (Noten n : s1.noten) {
|
|
|
System.out.println(n.fach + ": " + n.note);
|
|
|
}
|
|
Dies ist eine sogenannte for-each-Schleife. Sie wird benutzt, um nacheinander alle Elemente einer Liste zu durchlaufen. In diesem Projekt bedeutet das: Alle Noten des Studierenden s1 werden ausgegeben. Der Schleifenrumpf: |
|
|
System.out.println(n.fach + ": " + n.note);
|
|
gibt jeweils Fach und Note aus. |
|
Interface |
|
Die Zeile ... |
|
|
List<Noten> noten = new ArrayList<>();
|
|
... bedeutet: List<Noten> legt den Typ fest. List ist ein Interface aus dem Paket java.util. <Noten> bedeutet, die Liste darf nur Objekte vom Typ Note enthalten. |
|
19 Projekt hsdaten |
|
Umgesetzt mit Eclipse 2026-06. Package immer: hsdaten. |
|
Das folgende Projekt zeigen den Umgang mit Textdateien. Damit können in einfacher Form Daten gespeichert und bearbeitet werden, nicht wie in Datenbanksystemen, aber immerhin. Sinnvoll wäre ein in Java integriertes objektorientiertes Datenbanksystem. Das liegt aber nicht vor. |
|
Stattdessen bietet Java APIs (Application Programming Interfaces) für zahlreiche unterschiedliche Datenbanksysteme an. Unter anderem für relationale Datenbanksysteme (RDBS) und ihre Datenbanken. Dies ist sinnvoll, da RDBS sehr weit verbreitet sind. Die dafür zur Verfügung gestellten Schnittstellen werden JDBC (Java Database Connectivity) genannt. Vgl. [Ullenboom 2024, Kapitel 21]. |
|
In einer der nächsten Auflagen wird auch das hier vorgestellt, weil (natürlich) viele UML-Elemente auf Datenbestände ausgerichtet sind. |
|
Wobei dies keine wirklich zufriedenstellende Lösung ist. Relationale Datenbanken und objektorientierte sind zwei verschiedene Ansätze zur Lösung der Persistenzfrage, weshalb ihr Zusammenwirken umfangreiche technische und inhaltliche Abstimmungen verlangt. |
|
In diesem Projekt wird beschrieben, wie eine Textdatei eingerichtet, beschrieben und gelesen wird. Von der Klassenbibliothek wird dafür die Klasse java.io.File benötigt. |
|
Slash und Backslash bei Verzeichnissen in Java |
|
Beim Arbeiten mit Dateien muss man Java sagen, wo eine Datei gespeichert oder gelesen werden soll. Dazu verwendet man einen Pfad. Beispiel: |
|
|
C:\Meine Dateien\Stud004.txt
|
|
Dieser Pfad besteht aus: |
|
- Laufwerk: C:
- Ordner: Meine Dateien
- Datei: Stud004.txt
|
|
Windows verwendet traditionell den umgekehrten Schrägstrich (Backslash) in Pfaden. Deshalb die Angabe oben. In Java hat allerdings der Backslash eine Sonderbedeutung. Er leitet sogenannte Escape-Sequenzen ein. Zum Beispiel \n für neue Zeile. Darum interpretiert Java ein einzelnes backslash nicht einfach als Zeichen, weshalb man schreibt: |
|
|
C:\\Meine Dateien\\Stud004.txt
|
|
Denn: \\ bedeutet: Gib einen echten Backslash aus. |
|
Java akzeptiert allerdings auch normale Schrägstriche. Das funktioniert unter Windows meistens problemlos: |
|
|
C:/Meine Dateien/Stud004.txt
|
|
Dieser Pfad, "C:/Meine Dateien/...", wird auch in den folgenden Programmen genutzt. |
|
|
|
19.1 Klasse Erstellen |
|
Hier wird mit Hilfe der Methoden der Klasse java.io.File in einem bestimmten Verzeichnis eine neue Datei erstellt. Dazu wird, wie das folgende Beispiel zeigt, im Konstruktor der Pfad, der Dateiname und evtl. weitere Informationen angegeben. |
|
Auf diese Instanz kann dann die Methode createNewFile() angewandt werden. Sie richtet die Datei im gewählten Verzeichnis ein. Gibt es sie schon, ist der Ausdruck false und es wird angegeben, dass die Datei bereits existiert: |
|
- Datei noch nicht da, datei.createNewFile() ist erfolgreich und im Ausdruck wahr.
- Datei schon da, der Ausdruck hat den Wert false.
Klasse Erstellen mit Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
Klasse File der Klassenbibliothek in das Programm einbinden. |
|
|
import java.io.File;
|
|
|
|
|
|
public class Erstellen {
|
|
|
public static void main(String[] args) {
|
|
Try/Catch-Konstrukt. Vgl. Abschnitt 5.2. |
|
|
try {
|
|
String-Variable einrichten und bespielen. |
|
|
String fileName = "Stud006";
|
|
Konstruktor der Klasse File. Mit diesen Parametern wird das Verzeichnis und der Name der Datei angegeben. Das "Objekt" datei hat verschiedene Instanzmethoden. |
|
|
File datei = new File("C:/Meine Dateien/" + fileName + ".txt");
|
|
createNewFile ist eine Instanzmethode von File. Ist der Ausdruck wahr, kannn Erfolg gemeldet werden. |
|
|
if(datei.createNewFile())
|
|
|
System.out.println("Die Datei wurde erstellt");
|
|
|
else
|
|
|
System.out.println("Die Datei existiert bereits");
|
|
|
}
|
|
|
catch (Exception e) {
|
|
|
System.err.println(e);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse Erstellen ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
public class Erstellen {
|
|
|
public static void main(String[] args) {
|
|
|
try {
|
|
|
String fileName = "Stud006";
|
|
|
File datei = new File("C:/Meine Dateien/" + fileName + ".txt");
|
|
|
if(datei.createNewFile())
|
|
|
System.out.println("Die Datei wurde erstellt");
|
|
|
else
|
|
|
System.out.println("Die Datei existiert bereits");
|
|
|
}
|
|
|
catch (Exception e) {
|
|
|
System.err.println(e);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
19.2 Klasse Schreiben |
|
Vgl. zu den Klassen für das Lesen und Schreiben aus bzw. in Dateien Kapitel 6.Abschnitt 6.2. In dieser Klasse wird mit der Klasse FileWriter ohne Puffern gearbeitet. Außerdem wird die Datei in einem spezifischen Verzeichnis angelegt, nicht im Standardverzeichnis (vgl. Schreiben2.java). |
|
Klasse Schreiben mit Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
Klassen aus dem java.io-Paket: FileWriter: Datenstromklasse, die read- und write-Methoden auf Dateien abbildet. Java.io.IOException: Diese Klasse hilft, Fehlermeldungen ("exceptions") zu organisieren. |
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
|
|
|
|
public class Schreiben {
|
|
|
public static void main(String[] args) {
|
|
Eine Variable, die auf ein Objekt der Klasse FileWriter verweist, wird eingerichtet. |
|
|
FileWriter stud1 = null;
|
|
Beginn des Try/Catch-Abschnitts. Vgl. Abschnitt 5.2. |
|
|
try {
|
|
In einer Stringvariablen wird der Dateiname festgehalten. |
|
|
String dateiBez = "stud003";
|
|
Konstruktor der Klasse FileWriter. Dieses "Objekt" richtet die Datei im angegebenen Verzeichnis ein. |
|
|
stud1 = new FileWriter("C:/Meine Dateien/" + dateiBez + ".txt");
|
|
Text bereitstellen für das Eintragen in die Datei. |
|
|
String text = "Sinnspruch Nummer 3\n"
|
|
|
+ "Der Weg ist weit, der Weg ist lang,"
|
|
|
+ " doch uns wird - wie immer - nicht bang.";
|
|
Schreiben des Textes in die Datei stud1. |
|
|
stud1.write(text);
|
|
Schließen der Datei. |
|
|
stud1.close();
|
|
|
}
|
|
Für den Fall, dass der Try-Abschnitt scheitert, wird eine Fehlermeldung ausgegeben. |
|
|
catch (IOException fehler) { System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse Schreiben ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
|
|
|
|
public class Schreiben {
|
|
|
public static void main(String[] args) {
|
|
|
FileWriter stud1 = null;
|
|
|
try {
|
|
|
String dateiBez = "stud003";
|
|
|
stud1 = new FileWriter("C:/Meine Dateien/" + dateiBez + ".txt");
|
|
|
String text = "Sinnspruch Nummer 3\n"
|
|
|
+ "Der Weg ist weit, der Weg ist lang,"
|
|
|
+ " doch uns wird - wie immer - nicht bang.";
|
|
|
stud1.write(text);
|
|
|
stud1.close();
|
|
|
}
|
|
|
catch (IOException fehler) { System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
19.3 Klasse Schreiben2 |
|
Hier wird die Klasse BufferedWriter verwendet, die einen gepufferten Datenstrom bereitstellt. Das Programm als Ganzes erzeugt eine neue Datei im Standardverzeichnis c:/eclipse/hsdaten, und trägt in diese gepuffert Daten ein. Vgl. hierzu Abschnitt 6.2. |
|
Gepuffertes Schreiben ist für umfangreiche Datenströme oder Datenströme, die in einer Schleife abgearbeitet werden, notwendig. Hier dient es Demonstrationszwecken. |
|
Klasse Schreiben2 mit Erläuterungen |
|
|
package hochschule;
|
|
|
import java.io.*;
|
|
|
|
|
|
public class Schreiben2 {
|
|
|
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
|
|
Konstruktor der Klasse FileWriter. Das "Objekt" fiwr stellt das Programmfragment für den Schreibzugriff auf die angebene Datei bereit. |
|
|
FileWriter fiwr = new FileWriter("C:/Meine Dateien/Stud004.txt");
|
|
Konstruktor der Klasse BufferedWriter. Das "Objekt" buwr erlaubt das "gepufferte" Schreiben in die Datei fiwr. Obige zwei Befehle können auch gekapselt werden. Vgl. Abschnitt 6.2. Vgl. zu den E/A-Strömen Abschnitt 6.2. |
|
|
BufferedWriter buwr = new BufferedWriter(fiwr);
|
|
Schreiben in die Datei mit der Methode write(). Anfordern einer Leerzeile. Java-Programme sollen ja auf verschiedenen Betriebssystemen (Windows, Linux, usw.) einsetzbar sein ("Plattformunabhängigkeit"). Deshalb hier die Methode newLine() für das Anfordern einer neuen Zeile. Bleibt man unter Windows mit seinem Programm, wäre dafür auch die Zeichenfolge \n in der vorausgehenden Textausgabe möglich. Beides wird hier in den Beispielen demonstriert. |
|
|
buwr.write("Name=Staudacher");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Vorname=Guiseppe");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Ort=Ravensburg");
|
|
|
buwr.newLine();
|
|
|
buwr.close();
|
|
|
}
|
|
|
}
|
|
Klasse Schreiben2 ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
|
public class Schreiben2 {
|
|
|
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
FileWriter fiwr = new FileWriter("C:/Meine Dateien/Stud004.txt");
|
|
|
BufferedWriter buwr = new BufferedWriter(fiwr);
|
|
|
|
|
|
buwr.write("Name=Müller");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Vorname=Inge");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Ort=Ravensburg");
|
|
|
buwr.newLine();
|
|
|
buwr.close();
|
|
|
}
|
|
|
}
|
|
19.4 Klasse Lesen |
|
Hier spielen die Klassen FileReaderund BufferedReadereine zentrale Rolle. Ein Objekt von FileReader (also eine Art Schnittstelle zur Datei) ist der Parameter von BufferedReader. |
|
Für den zeilenweisen Zugriff auf eine Textdatei sind zwei Instanzen nötig. Eine von FileReader und eine von BufferedReader. Die von FileReader erhält im Konstruktor als Parameternamen die Dateibezeichnung und, wenn sie nicht im Standardverzeichnis ist, die Pfadangabe der Datei. |
|
Diese Instanz von FileReader wird beim Konstruktor von BufferedReader als Parameter eingegeben. Damit kann dann "gepuffert", d.h. nicht zeichenweise, mit der Methode readLine() gelesen werden. Vgl. das Beispiel unten. |
|
Die beiden Konstruktor-Ereignisse können hintereinander oder verschachtelt angegeben werden. Beides ist im Programm unten angegeben. |
|
Klasse Lesen mit Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.FileNotFoundException;
|
|
|
import java.io.FileReader;
|
|
|
import java.io.IOException;
|
|
|
|
|
|
public class Lesen {
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
Mit diesem Befehl wird ein Objekt der Klasse BufferedReader erzeugt, das einen zeilenweisen und gepufferten Lesezugriff auf eine Datei ermöglicht. |
|
|
BufferedReader stud1 = null;
|
|
|
|
|
|
String text;
|
|
Try/Catch-Konstrukt. Vgl. Abschnitt 5.2. |
|
|
try {
|
|
|
|
|
|
String dateiBez = "stud003";
|
|
|
|
|
|
System.out.println("\nDateiname:" + dateiBez + "\n");
|
|
|
|
|
Mit new FileReader("C:/Meine Dateien/" + dateiBez + ".txt") wird ein Objekt der Klasse FileReader erzeugt, mit dem das Verzeichnis und die Bezeichnung einer Datei verwaltet werden können. Der Gesamtbefehl ... stud1 = new BufferedReader (new FileReader("C:/Meine Dateien/" + dateiBez + ".txt")); führt dann zur Zugriffsoption, zum Öffnen der Datei im angegebenen Verzeichnis. Dessen Methode readLine() liest die Datei zeilenweise aus und gibt null zurück, wenn das Dateiende erreicht ist. |
|
|
stud1 = new BufferedReader
|
|
|
(new FileReader("C:/Meine Dateien/" + dateiBez + ".txt"));
|
|
Oben: Verschachtelte Konstruktorvorgänge Obiges Beispiel zeigt auch, dass es möglich ist, Konstruktorvorgänge zu verschachteln. Als Parameter in new BufferedReader wird new FileReader eingesetzt. |
|
|
|
|
|
} catch (FileNotFoundException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
try {
|
|
Lesen der Datei bis zur angegebenen Bedingung und Ausgeben des Gelesenen. |
|
|
while ((text = stud1.readLine()) != null) {
|
|
|
System.out.println(text);
|
|
|
}
|
|
|
} catch (IOException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse Lesen ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.FileNotFoundException;
|
|
|
import java.io.FileReader;
|
|
|
import java.io.IOException;
|
|
|
|
|
|
public class Lesen {
|
|
|
public static void main(String[] args) {
|
|
|
BufferedReader stud1 = null;
|
|
|
String text;
|
|
|
try {
|
|
|
String dateiBez = "stud003";
|
|
|
System.out.println("\nDateiname:" + dateiBez + "\n");
|
|
|
stud1 = new BufferedReader (new FileReader("C:/Meine Dateien/" + dateiBez + ".txt"));
|
|
|
} catch (FileNotFoundException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
try {
|
|
|
while ((text = stud1.readLine()) != null) {
|
|
|
System.out.println(text);
|
|
|
}
|
|
|
} catch (IOException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
19.5 Klasse Anhaengen |
|
Das Programm dieser Klasse leistet folgendes: |
|
- Erfragen einer Datei und Anfügen einer Zeile in dieser.
- Einfaches Einlesen von der Konsole mit Klasse Scanner.
- Einsatz der Klasse Formatter mit dem Formatspezifizierer %s/n.
|
|
Die Klasse Formatter dient hier dazu, die Eingaben in eine Textdatei zu formatieren. Der Konstruktor ist: |
|
|
Formatter formatter = new Formatter(writer))
|
|
Er benötigt ein Objekt der Klasse FileWriter als Parameter und stellt dann die benötigte Programmfunktionalität bereit. Die Methode format erlaubt dann die Spezifizierung: |
|
|
formatter.format("%s%n", newInput);
|
|
Die Kürzel: |
|
- %s bedeutet unformatierte Ausgabe eines Strings.
- %n bedeutet Anforderung einer neuen Zeile.
|
|
[Ullenboom 2024, S. 668] empfiehlt wegen der großen Zahl an Formatspezifizierern diesbezüglich den Blick in die API-Dokumentation. |
|
Klasse Anhaengen mit Erläuterungen |
|
|
package hsdaten;
|
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
|
import java.util.Formatter;
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class Anhaengen {
|
|
|
public static void main(String args[]) {
|
|
Ein Objekt der Klasse Scanner wird erzeugt. D.h., es wird die Funktionalität bereitgestellt, mit der Eingaben von der Konsole gelesen werden können. Der Parameter System.in gibt an, dass die Eingabe von der Konsole kommt. |
|
|
Scanner scanner = new Scanner(System.in);
|
|
Zuerst wird auf der Konsole die angegebene Frage formuliert. Dann wird mit der Methode scanner.next() ein Eingabefeld auf der Konsole eingerichtet und für die Aufnahme der Eingabe eine String-Variable fileName angelegt. Anschließend wird mit der Methode scanner.next() die Konsoleneingabe (der Dateiname) gelesen und in die String-Variable fileName gespielt. Mit scanner.nextLine() wird dann die textliche Eingabe gelesen. |
|
|
System.out.println("Welche Datei (ohne .txt)?");
|
|
|
String fileName = scanner.next(); //stud02.txt
|
|
|
scanner.nextLine();
|
|
Konstruktor der Klasse File. Dieses Programmfragment (Objekt) stellt den Zugriff auf die angegebene Datei im jeweiligen Verzeichnis bereit. Es erhält die Bezeichnung myFile. |
|
|
File datei = new File("C:/Meine Dateien/" + fileName + ".txt");
|
|
|
|
|
|
try(
|
|
Konstruktor der (Strom-)Klasse FileWriter. Das Objekt writer stellt eine Schnittstelle zu der als Parameter angegebenen Datei her. |
|
|
FileWriter writer = new FileWriter(datei, true);
|
|
Konstruktor der Klasse Formatter. Dieses Objekt stellt die Formatierungsmöglichkeiten für die Ausgabe von Texten bereit. Vgl. die nachfolgende Methode format() dieser Klasse. |
|
|
Formatter formatter = new Formatter(writer)) {
|
|
Zeilenweises Lesen der Eingabe (das ist der Text, der in der Datei an den vorhandenen Text angefügt wird). Zu den Formatcodes: %s bedeutet "Zeichenkette". %n bedeutet "neue Zeile" |
|
|
System.out.println("Eingabe: ");
|
|
|
String newInput = scanner.nextLine();
|
|
|
|
|
|
formatter.format("%s%n", newInput);
|
|
|
}
|
|
|
catch (IOException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
Schlusssequenz. Schließen der durch die Klasse Scanner angelegten Programmfragmente. Ausgabe der Erfolgsmeldung. |
|
|
scanner.close();
|
|
|
System.out.println("\nEs hat geklappt!");
|
|
|
}
|
|
|
}
|
|
Klasse Anhaengen ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
|
import java.util.Formatter;
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class Anhaengen {
|
|
|
public static void main(String args[]) {
|
|
|
Scanner scanner = new Scanner(System.in); //Konstruktor
|
|
|
System.out.println("Welche Datei (ohne .txt)?");
|
|
|
String fileName = scanner.next(); //stud02.txt
|
|
|
scanner.nextLine();
|
|
|
File datei = new File("C:/Meine Dateien/" + fileName + ".txt");
|
|
|
try(
|
|
|
FileWriter writer = new FileWriter(datei, true);
|
|
|
Formatter formatter = new Formatter(writer)) {
|
|
|
System.out.println("Eingabe: ");
|
|
|
String newInput = scanner.nextLine();
|
|
|
formatter.format("%s%n", newInput);
|
|
|
}
|
|
|
catch (IOException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
scanner.close();
|
|
|
System.out.println("\nEs hat geklappt!");
|
|
|
}
|
|
|
}
|
|
Beispielhafter Programmlauf |
|
|
Welche Datei (ohne .txt)?
|
|
|
stud02
|
|
|
Eingabe:
|
|
|
Angehängter Text
|
|
|
|
|
|
Es hat geklappt!
|
|
Hier noch ein Blick auf die Datei: |
|

|
|
19.6 Klasse Loeschen |
|
Löscht Dateien im Verzeichnis c:/Meine Dateien/. Ohne Pfadangabe würde die Datei im Standardverzeichnis gelöscht. Hier mit Windows 11 und einer Standardinstallation von Eclipse: c:/eclipse/hsdaten. Zur Scanner-Klasse vgl. die Ausführungen oben. |
|
Klasse Loeschen mit Erläuterungen |
|
|
package hochschule;
|
|
|
|
|
|
import java.io.*;
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class Loeschen {
|
|
|
public static void main(String[] args) {
|
|
|
Scanner scanner = new Scanner(System.in);
|
|
|
|
|
Die Bezeichnung der zu löschenden Datei wird von der Konsole eingelesen. Hier wird die Datei stud02.txt gewählt. |
|
|
System.out.println("Welche Datei soll gelöscht werden (mit .txt)?");
|
|
|
String fileName = scanner.next(); //stud02.txt
|
|
|
scanner.nextLine();
|
|
Ein Objekt der Klasse File wird mit der Dateibezeichnung erzeugt. Dies repräsentiert dann die Datei in ihrem Verzeichnis und stellt Methoden zu deren Bearbeitung bereit. |
|
|
File file = new File("C:/Meine Dateien/" + fileName);
|
|
Die Methode file.delete() wird aufgerufen. Ist sie erfolgreich, kommt es zur Erfolgsmeldung, andernfalls zur Misserfolgsmeldung. |
|
|
if(file.delete())
|
|
|
{
|
|
|
System.out.println("Die Datei wurde gelöscht.");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
System.out.println("Die Datei konnte nicht gelöscht werden.");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
Klasse Loeschen ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.*;
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class Loeschen {
|
|
|
public static void main(String[] args) {
|
|
|
Scanner scanner = new Scanner(System.in);
|
|
|
System.out.println("Welche Datei soll gelöscht werden (mit .txt)?");
|
|
|
String fileName = scanner.next(); //stud02.txt
|
|
|
scanner.nextLine();
|
|
|
File file = new File("C:/Meine Dateien/" + fileName);
|
|
|
if(file.delete())
|
|
|
{
|
|
|
System.out.println("Die Datei wurde gelöscht.");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
System.out.println("Die Datei konnte nicht gelöscht werden.");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
19.7 Klasse ErzeugLoesch |
|
Hier wird zuerst eine Datei im Verzeichnis c:/Meine Dateien eingerichtet sowie beschrieben und dann wahlweise belassen oder wieder gelöscht. |
|
Klasse ErzeugLoesch mit Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.BufferedWriter;
|
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class ErzeugLoesch {
|
|
|
|
|
Die IOException ist zur Fehlerbehandlung notwendig. |
|
|
public static void main(String[] args) throws IOException {
|
|
Zuerst eine Datei erzeugen |
|
|
String dateibez = "C:/Meine Dateien/stud05.txt";
|
|
Mit dem "Objekt" fiwr der Klasse FileWriter wird die angegebene Datei zum Beschreiben bereitgestellt. Das "Objekt" buwr der Klasse BufferedWriter stellt Methoden für das gepufferte Schreiben bereit. Der Parameter ist hier die Bezeichnung des File Writer-Objekts. Vgl. auch Abschnitt 6.2. |
|
|
FileWriter fiwr = new FileWriter(dateibez);
|
|
|
BufferedWriter buwr = new BufferedWriter(fiwr);
|
|
Mit den Methoden newLine() (Neue Zeile anfordern) und write() (Zeile in die Datei eintragen) wird die Datei beschrieben. |
|
|
buwr.write("Name=Mostkopf");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Vorname=Paul");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Ort=Ravensburg");
|
|
|
buwr.newLine();
|
|
|
buwr.close();
|
|
|
System.out.println("Datei " + dateibez + "
|
|
|
wurde im Standardverzeichnis erzeugt");
|
|
Die Eingabe in die grafische Eingabeaufforderung (siehe unten) führt zu einem String. |
|
|
String eingabe = JOptionPane.showInputDialog
|
|
|
("Datei wieder löschen (j/n)?");
|
|
Da der Umgang mit Strings manchmal schwierig ist und als Beispiel hier das Auslesen des ersten Stringelements in ein Character-Zeichen, mit dem dann die Abfrage, ob j/J oder n/N vorliegt, einfacher ist. |
|
|
char erster = eingabe.charAt(0);
|
|
|
if ((erster == 'j') || (erster == 'J')) {
|
|
|
System.out.println("j wurde erkannt");
|
|
In dateibez steht die Bezeichnung der Datei. Damit wird ein Objekt der Klasse File erzeugt. Dies repräsentiert die Datei in ihrem Verzeichnis. |
|
|
File file = new File(dateibez);
|
|
Dann wird mit dieser Dateibezeichnung die Methode file.delete() zum Löschen der Datei aufgerufen. Ist sie erfolgreich, kommt es zur Erfolgsmeldung, andernfalls zur Misserfolgsmeldung |
|
|
if(file.delete())
|
|
|
{
|
|
|
System.out.println("Die Datei wurde gelöscht.");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
System.out.println("Die Datei konnte nicht gelöscht werden.");
|
|
|
}
|
|
|
}
|
|
|
else if ((erster == 'n' ) || (erster == 'N')) {
|
|
|
System.out.println("Datei wird nicht gelöscht");
|
|
|
}
|
|
|
else System.out.println("Fehlerhafte Eingabe");
|
|
|
}
|
|
|
}
|
|
Klasse ErzeugLoesch ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.BufferedWriter;
|
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
|
public class ErzeugLoesch {
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
String dateibez = "C:/Meine Dateien/stud05.txt";
|
|
|
FileWriter fiwr = new FileWriter(dateibez);
|
|
|
BufferedWriter buwr = new BufferedWriter(fiwr);
|
|
|
buwr.write("Name=Mostkopf");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Vorname=Paul");
|
|
|
buwr.newLine();
|
|
|
buwr.write("Ort=Ravensburg");
|
|
|
buwr.newLine();
|
|
|
buwr.close();
|
|
|
System.out.println("Datei " + dateibez + " wurde im Standardverzeichnis erzeugt");
|
|
|
String eingabe = JOptionPane.showInputDialog("Datei wieder löschen (j/n)?");
|
|
|
char erster = eingabe.charAt(0);
|
|
|
if ((erster == 'j') || (erster == 'J')) {
|
|
|
System.out.println("j wurde erkannt");
|
|
|
File file = new File(dateibez);
|
|
|
if(file.delete())
|
|
|
{
|
|
|
System.out.println("Die Datei wurde gelöscht.");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
System.out.println("Die Datei konnte nicht gelöscht werden.");
|
|
|
}
|
|
|
}
|
|
|
else if ((erster == 'n' ) || (erster == 'N')) {
|
|
|
System.out.println("Datei wird nicht gelöscht");
|
|
|
}
|
|
|
else System.out.println("Fehlerhafte Eingabe");
|
|
|
}
|
|
|
}
|
|
Eingabefenster: |
|
|
|

|
|
|
|
19.8 Klasse EinlesenCSV |
|
CSV bedeutet Comma separated value und meint eine Textdatei, deren Inhalte auf eine bestimmte Art strukturiert sind. Vgl. unten. Für dieses Beispiel wurde eine Excel-Datei (mitarbeiter.csv) mit einigen wenigen Zeilen erzeugt und als CSV-Datei abgespeichert. Im Notepad sieht dies dann so aus: |
|

|
|
Zum Nachvollziehen sollte eine entsprechende Datei im Verzeichnis c:\meine Dateien eingerichtet werden. Dies klappt nur, falls die Excel-Datei als CSV/UTF-8 gespeichert wird. |
Beachten! |
Klasse EinlesenCSV mit Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.util.Scanner;
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.FileNotFoundException;
|
|
|
import java.io.FileReader;
|
|
|
import java.io.IOException;
|
|
|
|
|
|
public class EinlesenCSV {
|
|
|
|
|
|
public static void main(String[] args) throws FileNotFoundException {
|
|
|
|
|
Konstruktor der Klasse File. Vgl. Abschnitt 6.3. |
|
|
File CSVDatei = new File("mitarbeiter.csv");
|
|
Konstruktor der Klasse Scanner. Richtet ein "Scanner-Objekt" ein, mit dem von der Konsole gelesen werden kann. Klappt nur, falls Excel-Datei als CSV/UTF-8 gespeichert ist. Er erhält als Parameter die Dateibezeichnung und die Angabe des Zeichencodes (8-Bit UCS Transformation Code). |
|
|
Scanner lesen = new Scanner(CSVDatei, "UTF-8");
|
|
Die Instanzenmethode useDelimiter() wird auf die zum Scannen bereitgestellte Datei angewandt. Hier wird das Trennzeichen zwischen den Einzeleinträgen geklärt. Vgl. die Ausgabe unten. |
|
|
lesen.useDelimiter(";");
|
|
|
|
|
|
System.out.println("\nZum Testen, Ausgabe als CSV-Datei:\n");
|
|
|
while (lesen.hasNext())
|
|
|
{
|
|
|
System.out.print(lesen.next() + " / ");
|
|
|
}
|
|
|
lesen.close();
|
|
|
|
|
|
System.out.println("\n\nEinfache Ausgabe als Testdatei:");
|
|
|
BufferedReaderstud1 = null;
|
|
|
String text;
|
|
|
try {
|
|
|
String fileName = "C:/meine dateien/mitarbeiter.csv";
|
|
|
|
|
Hier liegen wiederum verkapselte "Konstruktor-Objekte" vor. Als Parameter von BufferedReader dient ein FileReader-Objekt.: stud1 = new BufferedReader (new FileReader(fileName )); |
|
|
System.out.println("Dateiname:" + fileName + "\n");
|
|
|
stud1 = new BufferedReader (new FileReader(fileName ));
|
|
|
|
|
|
} catch (FileNotFoundException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
Noch ein Try/Catch-Konstrukt. Diesmal mit einer Schleife zum Lesen und Ausgeben der Zeilen der Datei und für die evtl. Fehlermeldung. |
|
|
try {
|
|
|
while ((text = stud1.readLine()) != null) {
|
|
|
System.out.println(text);
|
|
|
}
|
|
|
} catch (IOException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse EinlesenCSV ohne Erläuterungen |
|
|
package hsdaten;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.FileNotFoundException;
|
|
|
import java.io.FileReader;
|
|
|
import java.io.IOException;
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class EinlesenCSV {
|
|
|
|
|
|
public static void main(String[] args) throws FileNotFoundException {
|
|
|
File CSVDatei = new File("mitarbeiter.csv");
|
|
|
Scanner lesen = new Scanner(CSVDatei, "UTF-8");
|
|
|
lesen.useDelimiter(";");
|
|
|
System.out.println("\nAusgabe als CSV-Datei:\n");
|
|
|
while (lesen.hasNext())
|
|
|
{
|
|
|
System.out.print(lesen.next() + " / ");
|
|
|
}
|
|
|
lesen.close();
|
|
|
|
|
|
System.out.println("\n\nZum Testen, Ausgabe als Textdatei:\n");
|
|
|
BufferedReader stud1 = null;
|
|
|
String text;
|
|
|
try {
|
|
|
String fileName = "C:/meine dateien/mitarbeiter.csv";
|
|
|
System.out.println("Dateiname: " + fileName + "\n");
|
|
|
stud1 = new BufferedReader(new FileReader(fileName ));
|
|
|
|
|
|
} catch (FileNotFoundException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
try {
|
|
|
while ((text = stud1.readLine()) != null) {
|
|
|
System.out.println(text);
|
|
|
}
|
|
|
} catch (IOException fehler) {
|
|
|
System.out.println("Fehler: " + fehler);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Ausgabe |
|
|
Ausgabe als CSV-Datei:
|
|
|
|
|
|
nachname / vorname / mitarbeiternummer / abteilung
|
|
|
Tanzer / Toni / 1234 / KA
|
|
|
Leoprecht / Max / 3712 / IT
|
|
|
Honig / Fritz / 3713 / ORG
|
|
|
Mälker / Kai / 9876 / PW
|
|
|
Staud / Josef / 1097 / IT /
|
|
|
|
|
|
Zum Testen, einfache Ausgabe als Textdatei:
|
|
|
|
|
|
Dateiname: C:/meine dateien/mitarbeiter.csv
|
|
|
|
|
|
nachname;vorname;mitarbeiternummer;abteilung
|
|
|
Tanzer;Toni;1234;KA
|
|
|
Leoprecht;Max;3712;IT
|
|
|
Honig;Fritz;3713;ORG
|
|
|
Mälker;Kai;9876;PW
|
|
|
Staud;Josef;1097;IT
|
|
|
|
|
|
20 Übungsaufgaben zu OOP mit Java |
|
Hier nun einfache Aufgaben zum Üben der Programmierkompetenz. Durch oftmaliges Lösen solcher Aufgabenstellungen wird die Basiskompetenz erworben. Übrigens können hier auch die modernen KI-Programme hilfreich sein. Nicht nur zum Überprüfen der Lösung, sondern auch zum Stellen von Aufgaben: |
|
Nutzen Sie die KI als Trainer, indem sie sich Aufgaben stellen lassen, zuerst einfacher, dann schwieriger. |
|
|
|
20.1 Aufgabe 1 - Klasse und Objekt (HS1) |
|
20.1.1 Aufgabe |
|
Erstellen Sie eine Klasse Aufgabe01 (Hauptprogramm) und eine Klasse Stud. Letztere erfasst Studierende und erhält folgende Attribute: |
|
- Matrikelnummer (int)
- Name (String)
- Vorname (String)
|
|
Erzeugen Sie im HP ein Objekt, beschreiben sie es und geben Sie die Daten aus. |
|
|
|
20.1.2 Lösung |
|
Klasse Stud |
|
|
Package Studierende;
|
|
|
|
|
|
class Stud {
|
|
|
int mNr;
|
|
|
String name;
|
|
|
String vName;
|
|
|
|
|
|
void ausgeben() {
|
|
|
System.out.println(mNr + " " + vName + " " + name);
|
|
|
}
|
|
|
}
|
|
Klasse Aufgabe01 |
|
|
Package Studierende;
|
|
|
|
|
|
public class Aufgabe01 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s = new Stud();
|
|
|
s.mNr = 123;
|
|
|
s.name = "Maier";
|
|
|
s.vName = "Klara";
|
|
|
s.ausgeben();
|
|
|
}
|
|
|
}
|
|
Ergebnis Programmlauf |
|
|
123 Klara Maier
|
|
20.2 Aufgabe 2 - Referenzen |
|
20.2.1 Aufgabe |
|
Wenn obiges Programm um folgende Zeilen ergänzt wird, wie sieht dann das Ergebnis aus? |
|
|
Stud s1 = new Stud();
|
|
|
Stud s2 = s1;
|
|
|
|
|
|
s1.name = "Meier";
|
|
|
System.out.println(s2.name);
|
|
Wie erklärt sich das Ergebnis? |
|
|
|
20.2.2 Lösung |
|
Klasse Aufgabe02 |
|
|
package studierende;
|
|
|
|
|
|
public class Aufgabe02 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s = new Stud();
|
|
|
s.mNr = 123;
|
|
|
s.name = "Maier";
|
|
|
s.vName = "Klara";
|
|
|
|
|
|
s.ausgeben();
|
|
|
|
|
|
Stud s1 = new Stud();
|
|
|
Stud s2 = s1;
|
|
|
s1.name = "Meier";
|
|
|
System.out.println(s2.name);
|
|
|
}
|
|
|
}
|
|
Klasse Stud |
|
|
package studierende;
|
|
|
|
|
|
class Stud {
|
|
|
int mNr;
|
|
|
String name;
|
|
|
String vName;
|
|
|
|
|
|
void ausgeben() {
|
|
|
System.out.println(mNr + " " + vName + " " + name);
|
|
|
}
|
|
|
}
|
|
Programmlauf |
|
|
123 Klara Maier
|
|
|
Meier
|
|
Begründung |
|
s1 und s2 zeigen auf dasselbe Objekt. |
|
20.3 Aufgabe 3 - Arrays |
|
20.3.1 Aufgabe |
|
Bezeichnungen der Klassen sind Stud und Aufgabe03. |
|
Erzeuge ein Array für drei Objekte der Klasse Stud. Erzeuge anschließend in einer Schleife für jedes Arrayelement ein neues Objekt der Klasse Stud und speichere es im Array. |
|
Weise jedem Objekt einen Namen zu. Der Name soll aus dem Text "Name" und dem aktuellen Schleifenindex bestehen, also beispielsweise: Name0, Name1, Name2. |
|
Gib danach mit einer for-each-Schleife die Namen aller gespeicherten Objekte auf der Konsole aus. |
|
|
|
20.3.2 Lösung mit Erläuterungen |
|
|
package studierende;
|
|
|
public class Aufgabe03 {
|
|
|
public static void main(String[] args) {
|
|
Erzeugung eines Arrays für drei Objekte (Studierende), noch ohne Daten: null |
|
|
Stud[] arr = new Stud[3];
|
|
Schleife von 0 bis 2 |
|
|
for (int i = 0; i < arr.length; i++) {
|
|
Neues Objekt erzeugen und im Array speichern |
|
|
arr[i] = new Stud();
|
|
Zugriff auf das Objekt, Name eintragen |
|
|
arr[i].name = "Name" + i;
|
|
|
}
|
|
For-each-Schleife über alle Elemente des Arrays. s ist jeweils ein Stud-Objekt |
|
|
for (Stud s : arr) {
|
|
|
System.out.println(s.name);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
20.3.3 Lösung ohne Erläuterungen |
|
|
package studierende;
|
|
|
public class Aufgabe03 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud[] arr = new Stud[3];
|
|
|
for (int i = 0; i < arr.length; i++) {
|
|
|
arr[i] = new Stud();
|
|
|
arr[i].name = "Name" + i;
|
|
|
}
|
|
|
for (Stud s : arr) {
|
|
|
System.out.println(s.name);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
20.4 Aufgabe 4 - Mehrere Klassen |
|
20.4.1 Aufgabe |
|
Erstellen Sie zu obigem zusätzlich eine Klasse Note mit den Attributen: |
|
|
|
|
Richten Sie eine bidirektionale Beziehung ein, so dass von Studierenden auf Noten und von Noten auf Studierende geschlossen werden kann. Realisieren Sie folgende Ausgaben: |
|
- Für alle Studierenden nacheinander die Ausgabe aller noten
- Liste aller Studierenden mit Note 1 in Informatik
|
|
Die Ausgabe sollte beispielhaft so aussehen: |
|
|
Maier hat folgende Noten:
|
|
|
Mathe: 2
|
|
|
Informatik: 1
|
|
|
|
|
|
Hirn hat folgende Noten:
|
|
|
Mathe: 3
|
|
|
Informatik: 2
|
|
|
|
|
|
Studierende mit Note 1 in Informatik:
|
|
|
Paul Maier
|
|
|
|
|
|
20.4.2 Lösung |
|
Klasse Aufgabe04 |
|
|
package studierende;
|
|
|
|
|
|
public class Aufgabe04 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s1 = new Stud();
|
|
|
s1.mNr = 1001;
|
|
|
s1.name = "Maier";
|
|
|
s1.vName = "Paul";
|
|
|
|
|
|
Stud s2 = new Stud();
|
|
|
s2.mNr = 2000;
|
|
|
s2.name = "Hirn";
|
|
|
s2.vName = "Ottilie";
|
|
|
|
|
|
Note n1 = new Note("Mathe", 2, s1);
|
|
|
Note n2 = new Note("Informatik", 1, s1);
|
|
|
Note n3 = new Note("Mathe", 3, s2);
|
|
|
Note n4 = new Note("Informatik", 2, s2);
|
|
|
|
|
|
s1.addNote(n1);
|
|
|
s1.addNote(n2);
|
|
|
s2.addNote(n3);
|
|
|
s2.addNote(n4);
|
|
|
|
|
|
System.out.println(s1.name + " hat folgende Noten:");
|
|
|
for (Note n : s1.noten) {
|
|
|
System.out.println(n.fach + ": " + n.note);
|
|
|
}
|
|
|
System.out.println(s2.name + " hat folgende Noten:");
|
|
|
for (Note n : s2.noten) {
|
|
|
System.out.println(n.fach + ": " + n.note);
|
|
|
}
|
|
|
System.out.println("\nStudierende mit Note 1 in Informatik:");
|
|
|
Note[] alleNoten = { n1, n2 };
|
|
|
for (Note n : alleNoten) {
|
|
|
if (n.fach.equals("Informatik") amp;amp; n.note == 1) {
|
|
|
System.out.println(n.student.vName + " " + n.student.name);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
Klasse Note |
|
|
package studierende;
|
|
|
|
|
|
class Note {
|
|
|
String fach;
|
|
|
int note;
|
|
|
Stud student;
|
|
|
|
|
|
public Note(String fach, int note, Stud student) {
|
|
|
this.fach = fach;
|
|
|
this.note = note;
|
|
|
this.student = student;
|
|
|
}
|
|
|
}
|
|
Klasse Stud |
|
|
package studierende;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
class Stud {
|
|
|
int mNr;
|
|
|
String name;
|
|
|
String vName;
|
|
Anlegen einer Liste, die mehrere Objekte der Klasse Note speichern kann. |
|
|
List<Note> noten = new ArrayList<>();
|
|
Die Methode add() gehört zur Klasse ArrayList. Sie hängt ein neues Element an die Liste an. |
|
|
void addNote(Note n) {
|
|
|
noten.add(n);
|
|
|
}
|
|
|
}
|
|
Möglicher Programmlauf |
|
|
Maier hat folgende Noten:
|
|
|
Mathe: 2
|
|
|
Informatik: 1
|
|
20.4.3 Programmbeschreibung |
|
In diesem Programm werden mehrere Objekte miteinander verbunden. Ein Studierender kann mehrere Noten besitzen. Gleichzeitig soll auch jede Note einem Studierenden zugeordnet werden könnnen, wodurch eine Beziehung zwischen den Klassen Stud und Note entsteht. Dies wird hier Assoziation genannt. |
|
In der Klasse Stud findet sich folgende Anweisung: |
|
|
List<Note> noten = new ArrayList<>();
|
|
Dies bedeutet: |
|
- Es handelt sich um eine Liste.
- In dieser Liste dürfen nur Objekte der Klasse Note gespeichert werden.
|
|
Beispielsweise: |
|
|
noten.add(n1);
|
|
|
noten.add(n2);
|
|
Dadurch werden zwei Notenobjekte in die Liste eingetragen. |
|
Die Methode addNote() fügt eine Note zur Notenliste hinzu: |
|
|
void addNote(Note n) {
|
|
|
noten.add(n);
|
|
|
}
|
|
Der Parameter: Note n ist eine Referenz auf ein Objekt der Klasse Note. Mit: |
|
|
noten.add(n);
|
|
wird dieses Objekt in die Liste gespeichert. |
|
Die Klasse Note enthält Stud student. Damit ist bei jeder Note das Objekt des zugehörigen Studenten hinterlegt. Das ist die zweite Richtung der Beziehung. |
|
Betrachten wir den Konstruktor der Klasse Note: |
|
|
public Note(String fach, int note, Stud student)
|
|
Damit werden beim Erzeugen eines Notenobjekts |
|
- Fach,
- Note und
- zugehöriger Studierender
|
|
übergeben. Beispiel: |
|
|
Note n1 = new Note("Mathe", 2, s1);
|
|
Die Zeile |
|
|
this.student = student;
|
|
ist zentral. Sie bedeutet, dass das aktuelle Objekt der Klasse Note eine Referenz auf den übergebenen Studierenden speichert. |
|
Die zweite Verbindung entsteht im Hauptprogramm. Durch |
|
|
s1.addNote(n1);
|
|
wird zusätzlich die Note im Studierendenobjekt gespeichert. |
|
Das Ergebnis ist eine bidirektionale Assoziation: |
|
- Vom Studierenden kann auf die Noten geschlossen werden
- Die Noten erlauben den Schluss auf den zugehörigen Studierenden.
|
|
20.5 Aufgabe 5 - Eingabe |
|
20.5.1 Aufgabe |
|
Ausgangspunkt: Klasse Stud wie oben. |
|
Aufgabe: Namen und Matrikelnummer eines Studierenden über die Konsole einlesen, in einem Objekt speichern und auf der Konsole ausgeben. Etwa so: |
|
|
Matrikelnummer eingeben: 1007
|
|
|
Vorname eingeben: Pierre
|
|
|
Name eingeben: Picard
|
|
|
|
|
|
--- Daten des Studierenden ---
|
|
|
Matrikelnummer: 1007
|
|
|
Vorname: Pierre
|
|
|
Name: Picard
|
|
|
|
20.5.2 Lösung |
|
Klasse Aufgabe05 |
|
|
package studierende;
|
|
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
public class Aufgabe05 {
|
|
|
public static void main(String[] args) {
|
|
Scanner-Objekt für Eingaben erzeugen |
|
|
Scanner sc = new Scanner(System.in);
|
|
Studierenden-Objekt erzeugen |
|
|
Stud s = new Stud();
|
|
Eingaben |
|
|
System.out.print("Matrikelnummer eingeben: ");
|
|
|
s.mNr = Integer.parseInt(sc.nextLine());
|
|
|
System.out.print("VornameN eingeben: ");
|
|
|
s.vName = sc.nextLine();
|
|
|
System.out.print("Namen eingeben: ");
|
|
|
s.name = sc.nextLine();
|
|
Ausgabe |
|
|
s.ausgeben();
|
|
Scanner schließen |
|
|
sc.close();
|
|
|
}
|
|
|
}
|
|
Klasse Stud |
|
|
package studierende;
|
|
|
|
|
|
class Stud {
|
|
|
int mNr;
|
|
|
String name;
|
|
|
String vName;
|
|
|
|
|
|
void ausgeben() {
|
|
|
System.out.println("\n--- Daten des Studierenden ---");
|
|
|
System.out.println("Matrikelnummer: " + mNr);
|
|
|
System.out.println("Vorname: " + vName);
|
|
|
System.out.println("Name: " + name);
|
|
|
}
|
|
|
}
|
|
20.6 Aufgabe 6 - Record |
|
20.6.1 Aufgabe |
|
Erstelle ein Java-Programm zur Verwaltung einfacher Studierendendaten mit einem record. |
|
Anforderungen |
|
- Lege einen record mit dem Namen Stud an.
- Der record soll folgende Attribute besitzen: name vom Typ String, sem ("Semester") vom Typ int.
- Erzeuge in der main()-Methode zwei Objekte des Typs Stud.
- Weise beiden Objekten identische Werte zu.
- Gib die einzelnen Attribute über die automatisch erzeugten Zugriffsmethoden aus.
- Gib anschließend das gesamte Objekt mit toString() aus.
- Vergleiche beide Objekte mit equals() und gib das Ergebnis aus.
|
|
|
|
20.6.2 Lösung |
|
Klasse HP |
|
|
package studierende;
|
|
|
|
|
|
record Stud(String name, int sem) {
|
|
|
}
|
|
|
public class Aufgabe06 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s1 = new Stud("Maier", 3);
|
|
|
Stud s2 = new Stud("Maier", 3);
|
|
Zugriff auf Werte (Getter-Methoden) |
|
|
System.out.println(s1.name());
|
|
|
System.out.println(s1.sem());
|
|
Ausgabe mit toString() |
|
|
System.out.println(s1);
|
|
Einsatz von equals() |
|
|
System.out.println(s1.equals(s2));
|
|
|
}
|
|
|
}
|
|
Programmlauf |
|
|
Maier
|
|
|
3
|
|
|
Stud[name=Maier, sem=3]
|
|
|
true
|
|
20.6.3 Exkurs: Wiederholung zu records |
|
Oben wird mit folgendem Befehl ein Record eingerichtet: |
|
|
record Stud(String name, int sem) {}
|
|
Er besitzt somit zwei Attribute: |
|
|
|
|
Daraus erzeugt Java automatisch: |
|
- private final Attribute
- einen Konstruktor
- Getter-Methoden (name() und sem())
- eine toString()-Methode
- equals() und hashCode() (Methoden der Klasse Object, die jede Java-Klasse automatisch erbt.)
|
|
Beispielhafte Verwendung in einem Hauptprogramm: |
|
|
public class Test
|
|
|
public static void main(String[] args) {
|
|
|
Stud s = new Stud("Maier", 3);
|
|
Erklärung new Stud("Maier", 3) ruft den automatisch erzeugten Konstruktor auf. Das Objekt wird in der Variablen s gespeichert. |
|
Die Ausgabe mit toString() wird wie folgt realisiert. Der Ausdruck println(s) in der Anweisung ... |
|
|
System.out.println(s);
|
|
... ruft automatisch s.toString() auf. Dies liefert dann hier z.B. Stud[name=Maier, sem=3]. |
|
20.7 Aufgabe 7 - Vererbung |
|
Erstellen Sie ein Java-Programm zur Verwaltung von Fahrzeugen. |
|
Oberklasse Fahrzeug |
|
Legen Sie eine Klasse Fahrzeug an. Die Klasse soll folgende Attribute besitzen: |
|
- fzNr (Fahrzeugnummer)
- hersteller
- baujahr
|
|
Erstellen Sie außerdem: |
|
- einen Konstruktor zur Übergabe aller Attribute
- eine Methode anzeigen(), die alle Fahrzeugdaten ausgibt
|
|
Unterklasse PKW |
|
Legen Sie eine Klasse PKW an, die von Fahrzeug erbt und folgende zusätzlichen Attribute hat: |
|
- sitze (Anzahl der ...)
- typ (Fahrzeugtyp)
|
|
Erstellen Sie: |
|
- einen Konstruktor
- einen Aufruf des Oberklassen-Konstruktors mit super(...)
- eine überschreibende Methode anzeigen()
|
|
Die Methode soll zunächst die Ausgabe der Oberklasse nutzen und anschließend die zusätzlichen PKW-Daten ausgeben. |
|
Klasse Aufgabe07 |
|
Erstellen Sie eine Klasse Aufgabe07 mit einem Hauptprogramm (main()). Darin werden ... |
|
- ein Objekt der Klasse Fahrzeug und
- ein Objekt der Klasse PKW
|
|
erzeugt. Geben Sie anschließend die Daten beider Objekte mit der Methode anzeigen() aus. Die Ausgabe soll so aussehen: |
|
|
--- Fahrzeug ---
|
|
|
Fahrzeugnummer: 1
|
|
|
Hersteller: MAN
|
|
|
Baujahr: 2015
|
|
|
|
|
|
--- PKW ---
|
|
|
Fahrzeugnummer: 2
|
|
|
Hersteller: VW
|
|
|
Baujahr: 2022
|
|
|
Sitze: 5
|
|
|
Typ: Kombi
|
|
|
|
20.7.1 Lösung |
|
Klasse Aufgabe07 |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class Aufgabe07 {
|
|
|
|
|
|
public static void main(String[] args) {
|
|
Objekt der Oberklasse |
|
|
Fahrzeug f = new Fahrzeug(1, "MAN", 2015);
|
|
|
System.out.println("--- Fahrzeug ---");
|
|
|
f.anzeigen();
|
|
Objekt der Subklasse |
|
|
PKW p = new PKW(2, "VW", 2022, 5, "Kombi");
|
|
|
System.out.println("\n--- PKW ---");
|
|
|
p.anzeigen();
|
|
|
}
|
|
|
}
|
|
Klasse Fahrzeug |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class Fahrzeug {
|
|
|
int fzNr;
|
|
|
String hersteller;
|
|
|
int baujahr;
|
|
Konstruktor mit Parameterübergabe. |
|
|
public Fahrzeug(int fzNr, String hersteller, int baujahr) {
|
|
|
this.fzNr = fzNr;
|
|
|
this.hersteller = hersteller;
|
|
|
this.baujahr = baujahr;
|
|
|
}
|
|
Methode zur Ausgabe |
|
|
void anzeigen() {
|
|
|
System.out.println("Fahrzeugnummer: " + fzNr);
|
|
|
System.out.println("Hersteller: " + hersteller);
|
|
|
System.out.println("Baujahr: " + baujahr);
|
|
|
}
|
|
|
}
|
|
Klasse PKW |
|
|
package fahrzeuge;
|
|
|
|
|
|
public class PKW extends Fahrzeug {
|
|
|
int sitze;
|
|
|
String typ;
|
|
Konstruktor in der Subklasse. Mit Hilfe des Schlüsselworts super kann der Konstruktor der Oberklasse integriert werden |
|
|
public PKW(int fzNr, String hersteller, int baujahr, int sitze, String typ) {
|
|
|
super(fzNr, hersteller, baujahr);
|
|
|
this.sitze = sitze;
|
|
|
this.typ = typ;
|
|
|
}
|
|
Methode überschreiben (Override). Die Attribute der Oberklasse werden wieder mit super hinzugenommen. |
|
|
@Override
|
|
|
void anzeigen() {
|
|
|
super.anzeigen();
|
|
|
System.out.println("Sitze: " + sitze);
|
|
|
System.out.println("Typ: " + typ);
|
|
|
}
|
|
|
}
|
|
20.7.2 Erläuterung |
|
Diese Aufgabe zeigt ein einfaches Beispiel für das Konzept Vererbung der objektorientierten Theorie. Die Idee hinter dem Vererbungskonzept ist: Gemeinsame Eigenschaften werden in einer allgemeinen Oberklasse gespeichert. Spezielle Subklassen erweitern diese Oberklasse um zusätzliche Eigenschaften und Methoden. |
|
Im Beispiel bedeutet das: |
|
- Ein PKW ist ebenfalls ein Fahrzeug.
- Deshalb übernimmt die Klasse PKW die Eigenschaften der Klasse Fahrzeug.
|
|
Die Methode void anzeigen() in Fahrzeug gibt die Fahrzeugdaten aus. Aufruf in Aufgabe07: |
|
|
f.anzeigen();
|
|
Das Objekt führt dann seine eigene Methode aus. |
|
Die Subklasse PKW entsteht durch diese Anweisung: |
|
|
public class PKW extends Fahrzeug
|
|
Das Schlüsselwort extends bedeutet, dass die Klasse PKW von der Klasse Fahrzeug Attribute und Methoden erbt. Die Klasse PKW hat zusätzlich die Attrribute int sitze und String typ. |
|
Im Konstruktor der Subklasse ... |
|
|
public PKW(int fzNr, String hersteller,
|
|
|
int baujahr, int sitze, String typ)
|
|
... werden sowohl die geerbten Attribute als auch die neuen Attribute übergeben. |
|
Mit super(...) wird der Konstruktor der Oberklasse aufgerufen. Dies bedeutet, die Oberklasse übernimmt selbst die Initialisierung ihrer Attribute. Danach werden die zusätzlichen PKW-Attribute gesetzt. |
|
Methoden überschreiben (Override) |
|
Die Methode anzeigen() existiert bereits in der Oberklasse. In PKW wird sie erneut definiert. Das ist entlang einer Vererbungshierachie möglich und wird Überschreiben bzw. Override genannt. Die Unterklasse ersetzt damit die geerbte Methode durch eine eigene Version. Mit super.anzeigen() in der Klasse PKW wird zuerst die Methode der Oberklasse ausgeführt. |
|
Zusammenfassung |
|
Die Klasse PKW erweitert die Klasse Fahrzeug. Dadurch können gemeinsame Eigenschaften zentral gespeichert werden. Die Vererbung vermeidet doppelte Programmierung und macht Programme übersichtlicher und leichter erweiterbar. |
|
20.8 Aufgabe 8 - Kapselung |
|
20.8.1 Aufgabe |
|
Richte ein Klasse Stud mit den privaten Attributen name, matrNr, semester und studiengang ein und demonstriere Getter- und Setter-Zugriffe. Stelle sicher, dass bei einer Semesterzahl > 15 die Fehlermeldung "Ungültiges Semester" folgt. |
|
Erstelle für die Attribute passende Getter- und Setter-Methoden. Der Setter für semester soll überprüfen, ob das Semester gültig ist. Es soll gelten: |
|
- Semester muss größer als 0 sein
- Semester darf maximal 15 sein
|
|
Falls ein ungültiger Wert eingegeben wird, soll eine Fehlermeldung erscheinen. |
|
Das Hauptprogramm |
|
Erstelle eine Klasse Aufgabe08 mit einer main()-Methode. Darin soll: |
|
- ein Objekt der Klasse Stud erzeugt werden
- die Attribute über Setter beschrieben werden
- die Werte über Getter ausgegeben werden
|
|
So soll die Ausgabe aussehen: |
|
|
Name: Müller
|
|
|
Matrikelnummer: 12345
|
|
|
Semester: 3
|
|
|
Studiengang: Informatik
|
|
20.8.2 Lösung |
|
Klasse Stud |
|
|
class Stud {
|
|
Private Attribute, die damit geschützt sind (->Sichtbarkeitsmodifizierer) |
|
|
private String name;
|
|
|
private int matrNr;
|
|
|
private int semester;
|
|
|
private String studiengang;
|
|
Getter und Setter für das Attribut name. |
|
|
public String getName() {
|
|
|
return name;
|
|
|
}
|
|
|
public void setName(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
Getter und Setter für das Attribut matrNr (Matrikelnummer). |
|
|
public int getMatrNr() {
|
|
|
return matrNr;
|
|
|
}
|
|
|
public void setMatrNr(int matrNr) {
|
|
|
this.matrNr = matrNr;
|
|
|
}
|
|
Getter und Setter für das Attribut semester. Mit Prüfung, ob Semesteranzahl korrekt. |
|
|
public int getSemester() {
|
|
|
return semester;
|
|
|
}
|
|
|
public void setSemester(int semester) {
|
|
|
if (semester > 0 amp;amp; semester <= 15) {
|
|
|
this.semester = semester;
|
|
|
} else {
|
|
|
System.out.println("Ungültiges Semester!");
|
|
|
}
|
|
|
}
|
|
Getter und Setter für das Attribut studiengang. |
|
|
public String getStudiengang() {
|
|
|
return studiengang;
|
|
|
}
|
|
|
public void setStudiengang(String studiengang) {
|
|
|
this.studiengang = studiengang;
|
|
|
}
|
|
|
}
|
|
Klasse Aufgabe08 |
|
|
public class Aufgabe08 {
|
|
|
public static void main(String[] args) {
|
|
|
Stud s = new Stud();
|
|
|
|
|
|
s.setName("Müller");
|
|
|
s.setMatrNr(12345);
|
|
|
s.setSemester(3);
|
|
|
s.setStudiengang("Informatik");
|
|
|
|
|
|
System.out.println("Name: " + s.getName());
|
|
|
System.out.println("Matrikelnummer: " + s.getMatrNr());
|
|
|
System.out.println("Semester: " + s.getSemester());
|
|
|
System.out.println("Studiengang: " + s.getStudiengang());
|
|
|
}
|
|
|
}
|
|
20.8.3 Erläuterung |
|
In dieser Aufgabe wird gezeigt, wie in Java mit privaten Attributen, Gettern und Settern gearbeitet wird. Alle Attribute der Klasse Stud sind mit dem Modifizierer private geschützt. Dadurch kann von außen nicht direkt auf sie zugegriffen werden. Der Zugriff erfolgt ausschließlich über die sogenannten Getter- und Setter-Methoden. |
|
Im Hauptprogramm wird ein Objekt der Klasse Stud erzeugt. Anschließend werden die Attribute mit Setter-Methoden beschrieben und mit Getter-Methoden wieder ausgegeben. |
|
Dabei können auch Kontrollen der Eingaben einbebaut werden. Dies wird bei der Methode setSemester() gezeigt. Dort wird geprüft, ob das angegebene Semester zwischen 1 und 15 liegt. Wird ein ungültiger Wert eingegeben, erscheint die Meldung Ungültiges Semester. |
|
Insgesamt zeigt damit das Projekt an einem einfachen Beispiel: |
|
- Datenkapselung
- Zugriffsschutz mit private
- Verwendung von Getter- und Setter-Methoden
- einfache Plausibilitätsprüfungen in Methoden
- Objekterzeugung und Methodennutzung in Java
|
|
20.9 Aufgabe 9 - Overload |
|
20.9.1 Aufgabe |
|
Erstellen Sie ein Java-Programm zur Verwaltung von Studierendendaten. Legen Sie eine Klasse Stud mit folgenden Attributen des Typs private an: |
|
- name
- matrNr
- semester
- studiengang
|
|
Erstellen Sie für alle Attribute passende Getter- und Setter-Methoden. Zum Beispiel: |
|
|
public String getName()
|
|
|
public void setName(String name)
|
|
Erstellen Sie mehrere Methoden mit der Bezeichnung anzeigen(), die unterschiedliche Parameterlisten besitzen, womit eine Methodenüberladung entsteht: |
|
- Variante 1 - Keine Parameter. Die Methode soll alle Daten des Studierenden ausgeben.
- Variante 2 - Boolean-Parameter, z.B. anzeigen(boolean nurName). Ist der Parameter true, soll nur der Name ausgegeben werden. Ist der Parameter false, sollen alle Daten ausgegeben werden. Hinweis: Die Methode darf die parameterlose Methode anzeigen() erneut aufrufen.
- Variante 3 - Textparameter, z.B. anzeigen(String text). Die Methode soll einen frei wählbaren Text zusammen mit dem Namen ausgeben. Beispiel: "Student: Müller".
- Variante 4 - Zwei Parameter, z.B. anzeigen(String text, int semester). Die Methode soll einen Text, den Namen und das Semester ausgeben. Beispiel: "Info: Müller (Semester 3)"
|
|
Erstellen Sie zusätzlich eine Klasse Test mit einer main()-Methode. Im Hauptprogramm erzeugen Sie ein Objekt der Klasse Stud, beschreiben das Objekt mit Hilfe der Setter-Methoden und rufen anschließend alle Varianten der Methode anzeigen() auf. Zum Beispiel so: |
|
Beispielausgabe: |
|
|
Strolch, 54321, 3, Informatik
|
|
|
Name: Strolch
|
|
|
Student: Strolch
|
|
|
Info: Strolch (Semester 3)
|
|
20.9.2 Lösung |
|
Klasse Stud |
|
|
package studierende;
|
|
|
|
|
|
class Stud {
|
|
|
private String name;
|
|
|
private int matrNr;
|
|
|
private int semester;
|
|
|
private String studiengang;
|
|
Getter und Setter |
|
|
public String getName() { return name; }
|
|
|
public void setName(String name) { this.name = name; }
|
|
|
|
|
|
public int getMatrNr() { return matrNr; }
|
|
|
public void setMatrNr(int matrNr) { this.matrNr = matrNr; }
|
|
|
|
|
|
public int getSemester() { return semester; }
|
|
|
public void setSemester(int semester) { this.semester = semester; }
|
|
|
|
|
|
public String getStudiengang() { return studiengang; }
|
|
|
public void setStudiengang(String studiengang) { this.studiengang = studiengang; }
|
|
Überladene Methoden anzeigen() 1. keine Parameter #8594; alle Daten anzeigen |
|
|
public void anzeigen() {
|
|
|
System.out.println(name + ", " + matrNr + ", " + semester + ", " + studiengang);
|
|
|
}
|
|
2. nur Name anzeigen |
|
|
public void anzeigen(boolean nurName) {
|
|
|
if (nurName) {
|
|
|
System.out.println("Name: " + name);
|
|
|
} else {
|
|
|
anzeigen(); // ruft Methode 1 auf
|
|
|
}
|
|
|
}
|
|
3. frei wählbarer Text + Name |
|
|
public void anzeigen(String text) {
|
|
|
System.out.println(text + ": " + name);
|
|
|
}
|
|
4. zwei Parameter -> Name und Semester |
|
|
public void anzeigen(String text, int semester) {
|
|
|
System.out.println(text + ": " + name + " (Semester " + semester + ")");
|
|
|
}
|
|
|
}
|
|
Klasse Aufgabe09 |
|
|
Package studierende;
|
|
|
|
|
|
public class Aufgabe09 {
|
|
|
public static void main(String[] args) {
|
|
Werte eintragen |
|
|
Stud s = new Stud();
|
|
|
s.setName("Strolch");
|
|
|
s.setMatrNr(54321);
|
|
|
s.setSemester(3);
|
|
|
s.setStudiengang("Informatik");
|
|
|
|
|
Aufrufe der überladenen Methoden |
|
|
s.anzeigen(); // alle Daten
|
|
|
s.anzeigen(true); // nur Name
|
|
|
s.anzeigen("Student"); // Text + Name
|
|
|
s.anzeigen("Info", s.getSemester()); // Text + Name + Semester
|
|
|
}
|
|
|
}
|
|
20.9.3 Erläuterung |
|
Mehrere Methoden dürfen denselben Namen besitzen, wenn sich ihre Parameterlisten unterscheiden. Beispiele: |
|
|
anzeigen()
|
|
|
anzeigen(boolean nurName)
|
|
|
anzeigen(String text)
|
|
|
anzeigen(String text, int semester)
|
|
Java erkennt beim Aufruf automatisch, welche Methode gemeint ist. |
|
21 Weitere Übungsaufgaben |
|
Jetzt nochmals einführende Aufgaben, wieder inhaltlich von vorne beginnend. |
|
|
|
21.1 Aufgabe 10 - Erste Klasse und erstes Objekt |
|
21.1.1 Aufgabenstellung |
|
Erstellen Sie eine Klasse Student mit den Attributen: |
|
- name vom Typ String
- alter vom Typ int
|
|
Implementieren Sie außerdem eine Methode vorstellen(), die den Namen und das Alter auf der Konsole ausgibt. |
|
Schreiben Sie danach ein Hauptprogramm, in dem: |
|
- ein Objekt der Klasse Student erzeugt wird
- die Attribute gesetzt werden
- die Methode vorstellen() aufgerufen wird
|
|
21.1.2 Lösung |
|
|
package studierende;
|
|
|
|
|
|
class Student {
|
|
|
String name;
|
|
|
int alter;
|
|
|
|
|
|
void vorstellen() {
|
|
|
System.out.println("Ich heiße " + name + " und bin " + alter + " Jahre alt.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Test {
|
|
|
public static void main(String[] args) {
|
|
|
Student s1 = new Student();
|
|
|
s1.name = "Anna";
|
|
|
s1.alter = 20;
|
|
|
|
|
|
s1.vorstellen();
|
|
|
}
|
|
|
}
|
|
Anmerkung: Testen Sie das Unterbringen aller Klassen in einer einzigen Datei. |
|
21.2 Aufgabe 11 - Konstruktor |
|
21.2.1 Aufgabenstellung |
|
Erweitern Sie die Klasse Student so, dass Name und Alter bereits beim Erzeugen des Objekts übergeben werden. Dazu soll ein Konstruktor implementiert werden. |
|
Erzeugen Sie im Hauptprogramm Test ein Objekt mit diesem Konstruktor und geben Sie die Daten mit einer Methode aus. |
|
21.2.2 Lösung |
|
|
package studierende;
|
|
|
class Student {
|
|
|
String name;
|
|
|
int alter;
|
|
|
|
|
|
Student(String name, int alter) {
|
|
|
this.name = name;
|
|
|
this.alter = alter;
|
|
|
}
|
|
|
|
|
|
void vorstellen() {
|
|
|
System.out.println("Ich heiße " + name + " und bin " + alter + " Jahre alt.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Test {
|
|
|
public static void main(String[] args) {
|
|
|
Student s1 = new Student("Max", 22);
|
|
|
s1.vorstellen();
|
|
|
}
|
|
|
}
|
|
21.3 Aufgabe 12 - Array von Objekten |
|
21.3.1 Aufgabenstellung |
|
Erstellen Sie mehrere Objekte der Klasse Student und speichern Sie diese in einem Array. Geben Sie anschließend alle Studierenden mit einer Schleife aus. |
|
21.3.2 Lösung |
|
|
package studierende;
|
|
|
|
|
|
class Student {
|
|
|
String name;
|
|
|
|
|
|
Student(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
|
|
|
|
void anzeigen() {
|
|
|
System.out.println("Student: " + name);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Test {
|
|
|
public static void main(String[] args) {
|
|
|
Student[] gruppe = new Student[3];
|
|
|
|
|
|
gruppe[0] = new Student("Anna");
|
|
|
gruppe[1] = new Student("Ben");
|
|
|
gruppe[2] = new Student("Clara");
|
|
|
|
|
|
for (Student s : gruppe) {
|
|
|
s.anzeigen();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
21.4 Aufgabe 13 - Kapselung |
|
21.4.1 Aufgabenstellung |
|
Erstellen Sie eine Klasse Konto mit einem privaten Attribut kontostand vom Typ double. Implementieren Sie dazu: |
|
- eine Methode einzahlen(double betrag), die den Kontostand erhöht
- eine Methode getKontostand(), die den aktuellen Kontostand zurückgibt
|
|
Testen Sie die Klasse in einer main-Methode. |
|
21.4.2 Lösung |
|
|
package banken;
|
|
|
|
|
|
class Konto {
|
|
|
private double kontostand;
|
|
|
public void einzahlen(double betrag) {
|
|
|
kontostand = kontostand + betrag;
|
|
|
}
|
|
|
public double getKontostand() {
|
|
|
return kontostand;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Aufgabe13 {
|
|
|
public static void main(String[] args) {
|
|
|
Konto k = new Konto();
|
|
|
k.einzahlen(100.0);
|
|
|
k.einzahlen(50.0);
|
|
|
System.out.println("Kontostand: " + k.getKontostand());
|
|
|
}
|
|
|
}
|
|
21.5 Aufgabe 14 - Vererbung |
|
21.5.1 Aufgabenstellung |
|
Erstellen Sie eine Oberklasse Person mit dem Attribut name und der Methode vorstellen(). Leiten Sie davon eine Klasse Student ab, die zusätzlich das Attribut studiengang besitzt. Schreiben Sie ein Hauptprogramm Aufgabe14, in dem ein Objekt der Klasse Student erzeugt und getestet wird. |
|
21.5.2 Lösung |
|
|
package personen;
|
|
|
class Person {
|
|
|
String name;
|
|
|
void vorstellen() {
|
|
|
System.out.println("Ich heiße " + name + ".");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Student extends Person {
|
|
|
String studiengang;
|
|
|
|
|
|
void anzeigen() {
|
|
|
System.out.println(name + " studiert " + studiengang + ".");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Aufgabe14 {
|
|
|
public static void main(String[] args) {
|
|
|
Student s = new Student();
|
|
|
s.name = "Paula";
|
|
|
s.studiengang = "Informatik";
|
|
|
|
|
|
s.vorstellen();
|
|
|
s.anzeigen();
|
|
|
}
|
|
|
}
|
|
21.6 Aufgabe 15 - Override |
|
21.6.1 Aufgabenstellung |
|
Verwenden Sie wieder die Klassen Person und Student. Die Methode vorstellen() soll in der Klasse Student überschrieben werden, sodass zusätzlich der Studiengang ausgegeben wird. Testen Sie das Verhalten im Hauptprogramm Aufgabe15. |
|
21.6.2 Lösung |
|
|
package personen;
|
|
|
|
|
|
class Person {
|
|
|
String name;
|
|
|
void vorstellen() {
|
|
|
System.out.println("Ich heiße " + name + ".");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Student extends Person {
|
|
|
String studiengang;
|
|
|
|
|
|
@Override
|
|
|
void vorstellen() {
|
|
|
System.out.println("Ich heiße " + name + " und studiere " + studiengang + ".");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Aufgabe15 {
|
|
|
public static void main(String[] args) {
|
|
|
Student s = new Student();
|
|
|
s.name = "Tom";
|
|
|
s.studiengang = "Wirtschaftsinformatik";
|
|
|
s.vorstellen();
|
|
|
}
|
|
|
}
|
|
21.7 Aufgabe 16 - Polymorphie |
|
21.7.1 Aufgabenstellung |
|
Erstellen Sie eine Oberklasse Tier mit der Methode lautGeben(). Leiten Sie davon zwei Klassen ab: Hund und Katze. Überschreiben Sie die Methode jeweils passend. Katzen sagen Miau, Hunde sagen Wuff. |
|
Speichern Sie mehrere Tier-Objekte in einem Array vom Typ Tier und lassen Sie alle Tiere ihre Laute ausgeben. |
|
21.7.2 Lösung |
|
|
package tiere;
|
|
|
|
|
|
class Tier {
|
|
|
void lautGeben() {
|
|
|
System.out.println("Unbekanntes Tiergeräusch");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Hund extends Tier {
|
|
|
@Override
|
|
|
void lautGeben() {
|
|
|
System.out.println("Wuff");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Katze extends Tier {
|
|
|
@Override
|
|
|
void lautGeben() {
|
|
|
System.out.println("Miau");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Aufgabe16 {
|
|
|
public static void main(String[] args) {
|
|
|
Tier[] tiere = new Tier[3];
|
|
|
tiere[0] = new Hund();
|
|
|
tiere[1] = new Katze();
|
|
|
tiere[2] = new Hund();
|
|
|
|
|
|
for (Tier t : tiere) {
|
|
|
t.lautGeben();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
21.8 Aufgabe 17 - Abstrakte Klasse |
|
21.8.1 Aufgabenstellung |
|
Erstellen Sie eine abstrakte Klasse Fahrzeug mit der abstrakten Methode fahren(). Leiten Sie davon eine Klasse Auto ab und implementieren Sie die Methode. Testen Sie die Klassen im Hauptprogramm. |
|
21.8.2 Lösung |
|
Immer: Package fahrzeuge |
|
|
abstract class Fahrzeug {
|
|
|
abstract void fahren();
|
|
|
}
|
|
|
|
|
|
class Auto extends Fahrzeug {
|
|
|
@Override
|
|
|
void fahren() {
|
|
|
System.out.println("Das Auto fährt.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Aufgabe17 {
|
|
|
public static void main(String[] args) {
|
|
|
Fahrzeug f = new Auto();
|
|
|
f.fahren();
|
|
|
}
|
|
|
}
|
|
21.8.3 Exkurs - Abstrakte Klasse |
|
Eine abstrakte Klasse ist eine Klasse, von der normalerweise keine direkten Objekte erzeugt werden. Sie dient als gemeinsame Grundlage für andere Klassen. |
|
Beispiel: |
|
|
abstract class Fahrzeug {
|
|
|
String marke;
|
|
|
}
|
|
Von Fahrzeug soll nur geerbt werden: |
|
|
class PKW extends Fahrzeug {
|
|
|
}
|
|
Der folgende Aufruf wäre nicht erlaubt: |
|
|
Fahrzeug f = new Fahrzeug(); // Fehler!
|
|
Eine abstrakte Methode ist eine Methode ohne Programmcode. Sie legt nur fest, dass eine Methode vorhanden sein muss. |
|
Beispiel: |
|
|
abstract class Fahrzeug {
|
|
|
abstract void fahren();
|
|
|
}
|
|
Die erbende Klasse muss die Methode dann konkret ausprogrammieren: |
|
|
class PKW extends Fahrzeug {
|
|
|
@Override
|
|
|
void fahren() {
|
|
|
System.out.println("Der PKW fährt.");
|
|
|
}
|
|
|
}
|
|
Es gilt: |
|
- Eine abstrakte Klasse kann normale und abstrakte Methoden enthalten.
- Enthält eine Klasse mindestens eine abstrakte Methode, muss auch die Klasse selbst als abstract gekennzeichnet werden.
|
|
21.9 Aufgabe 18 - Interface |
|
21.9.1 Aufgabenstellung |
|
Erstellen Sie ein Interface Beweglich mit der Methode bewegen(). Implementieren Sie dieses Interface in einer Klasse Mensch. Testen Sie die Implementierung im Hauptprogramm. |
|
21.9.2 Lösung |
|
Immer: package menschen |
|
|
interface Beweglich {
|
|
|
void bewegen();
|
|
|
}
|
|
|
|
|
|
class Mensch implements Beweglich {
|
|
|
@Override
|
|
|
public void bewegen() {
|
|
|
System.out.println("Der Mensch läuft.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class Aufgabe18 {
|
|
|
public static void main(String[] args) {
|
|
|
Beweglich b = new Mensch();
|
|
|
b.bewegen();
|
|
|
}
|
|
|
}
|
|
21.9.3 Exkurs - Interface |
|
Das Programm zeigt, wie ein Interface verwendet wird. |
|
Mit ... |
|
|
interface Beweglich {
|
|
|
void bewegen();
|
|
|
}
|
|
... wird das Interface Beweglich definiert. Es enthält die Methode: |
|
|
void bewegen();
|
|
Die Methode besitzt noch keinen Programmcode. Das Interface legt also nur fest: "Jede Klasse, die Beweglich sein will, muss eine Methode bewegen() besitzen." |
|
Die Klasse Mensch |
|
|
class Mensch implements Beweglich {
|
|
Die Klasse Mensch übernimmt das Interface mit: |
|
|
implements Beweglich
|
|
Dadurch verpflichtet sich die Klasse, die Methode bewegen() bereitzustellen. |
|
Umsetzung der Methode |
|
|
@Override
|
|
|
public void bewegen() {
|
|
|
System.out.println("Der Mensch läuft.");
|
|
|
}
|
|
Hier wird die im Interface verlangte Methode konkret programmiert. Die Annotation @Override bedeutet: Diese Methode überschreibt bzw. erfüllt eine Vorgabe aus dem Interface. |
|
Das Hauptprogramm |
|
|
Beweglich b = new Mensch();
|
|
Hier passiert folgendes: |
|
- rechts wird ein Objekt der Klasse Mensch erzeugt
- links wird es in einer Variablen vom Typ Beweglich gespeichert
|
|
Die Variable kennt also nur das Verhalten des Interfaces. Der Methodenaufruf b.bewegen() funktioniert, weil das Interface die Methode bewegen() definiert. |
|
Zur Laufzeit wird die Methode der Klasse Mensch ausgeführt: |
|
|
Der Mensch läuft.
|
|
Bedeutung des Beispiels |
|
Das Interface beschreibt eine Fähigkeit: "Kann sich bewegen". Andere Klassen könnten ebenfalls Beweglich implementieren: |
|
|
class Auto implements Beweglich
|
|
|
class Hund implements Beweglich
|
|
|
class Roboter implements Beweglich
|
|
Alle müssten eine Methode bewegen() besitzen, aber jeweils mit unterschiedlichem Verhalten. |
|
Das ist ein wichtiger Gedanke der objektorientierten Programmierung: |
|
- gemeinsames Verhalten definieren
- konkrete Umsetzung den Klassen überlassen
|
|
21.10 Aufgabe 19 - Zusammenspiel mehrerer Klassen |
|
21.10.1 Aufgabenstellung |
|
Erstellen Sie die zwei Klassen Kurs und Student. Ein Objekt der Klasse Student soll einem Kurs zugeordnet sein. |
|
Implementieren Sie passende Attribute, Konstruktoren und eine Methode, die ausgibt, welcher Student welchen Kurs besucht. |
|
Testen Sie das Zusammenspiel im Hauptprogramm. |
|
21.10.2 Lösung |
|
|
class Kurs {
|
|
|
String name;
|
|
|
Kurs(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Student {
|
|
|
String name;
|
|
|
Kurs kurs;
|
|
|
Student(String name, Kurs kurs) {
|
|
|
this.name = name;
|
|
|
this.kurs = kurs;
|
|
|
}
|
|
|
void anzeigen() {
|
|
|
System.out.println(name + " besucht den Kurs " + kurs.name + ".");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class HP {
|
|
|
public static void main(String[] args) {
|
|
|
Kurs k1 = new Kurs("Programmierung 1");
|
|
|
Student s1 = new Student("Eva", k1);
|
|
|
s1.anzeigen();
|
|
|
}
|
|
|
}
|
|
21.10.3 Exkurs - Verknüpfung |
|
Das Beispiel zeigt eine Verknüpfung (Assoziation) zwischen den Klassen Student und Kurs: Ein Studierender gehört hier zu genau einem Kurs. |
|
Die Verknüpfung entsteht durch das Attribut: |
|
|
Kurs kurs;
|
|
in der Klasse Student. Dadurch kann ein Objekt der Klasse Student auf ein Objekt der Klasse Kurs verweisen. |
|
Im Hauptprogramm steht: |
|
|
Kurs k1 = new Kurs("Programmierung 1");
|
|
Damit wird zuerst ein Kursobjekt erzeugt. Danach wird mit: |
|
|
Student s1 = new Student("Eva", k1);
|
|
der Studierenden Eva das Kursobjekt k1 übergeben. |
|
Im Konstruktor: |
|
|
this.kurs = kurs;
|
|
wird die Referenz gespeichert. Der Student "kennt" danach "seinen" Kurs. |
|
Die Ausgabe: |
|
|
System.out.println(name + " besucht den Kurs " + kurs.name + ".");
|
|
greift über die Verknüpfung auf das Objekt kurs zu und dort auf dessen Attribut name. |
|
Die Ausgabe: |
|
|
Eva besucht den Kurs Programmierung 1.
|
|
Kurzform: |
|
- Student enthält eine Referenz auf Kurs
- dadurch entsteht eine Assoziation zwischen beiden Klassen
- Objekte können so miteinander zusammenarbeiten
|
|
21.11 Aufgabe 20 - vom Klassendiagramm zu Java |
|
21.11.1 Aufgabe |
|
Das folgende Klassendiagramm stammt aus [Staud 2026]. Es ist die Abbildung 3.8-1. Vgl. dort für eine Beschreibung. |
|
Erstellen Sie ein Java-Programm, das dieses Klassendiagramm umsetzt, soweit das mit einer Programmiersprache möglich ist. D.h. die Beziehungen werden nicht datenbankartig umgesetzt, sondern durch Objektverweise und List - Elemente. |
|
Legen Sie Beispielsdaten an (zwei Studierende) und demonstrieren Sie den Methodeneinsatz. |
|

|
|
|
|
21.11.2 Lösung |
|
Eine einfache Java-Umsetzung des UML-Diagramms sieht so aus, dabei werden die n:m-Beziehungen mit List<> umgesetzt. Das Prüfungsdreieck wird als eigene Klasse Pruefungsgeschehen modelliert. |
|
Die einzelnen Klassen und Programme sind in einer Datei HochschuleDemo.java zusammengefasst. Das dient hier der vereinfachten Darstellung und Demonstrationszwecken, ist aber i.d.R. nicht empfehlenswert. |
|
HochschuleDemo.java |
|
|
import java.time.LocalDate;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
class Dozent {
|
|
|
int dozNr;
|
|
|
String anrede, name, vorname, ort, plz, strasse, email;
|
|
|
|
|
|
List<Lehrveranstaltung> lehrveranstaltungen = new ArrayList<>();
|
|
|
List<Studierender> betreuteStudierende = new ArrayList<>();
|
|
|
|
|
|
Dozent(int dozNr, String name, String vorname) {
|
|
|
this.dozNr = dozNr;
|
|
|
this.name = name;
|
|
|
this.vorname = vorname;
|
|
|
}
|
|
|
|
|
|
void haltenVorlesung(Lehrveranstaltung lv) {
|
|
|
lehrveranstaltungen.add(lv);
|
|
|
lv.dozenten.add(this);
|
|
|
}
|
|
|
|
|
|
void betreuen(Studierender s) {
|
|
|
betreuteStudierende.add(s);
|
|
|
s.betreuer = this;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Studierender {
|
|
|
String matrikelNr, name, vname, plz, ort, strasse, studiengang;
|
|
|
LocalDate beginnStudium, endeStudium;
|
|
|
int fachsem;
|
|
|
|
|
|
Dozent betreuer;
|
|
|
|
|
|
List<Lehrveranstaltung> besuchteLehrveranstaltungen = new ArrayList<>();
|
|
|
List<Pruefungsgeschehen> pruefungen = new ArrayList<>();
|
|
|
|
|
|
Studierender(String matrikelNr, String name, String vname) {
|
|
|
this.matrikelNr = matrikelNr;
|
|
|
this.name = name;
|
|
|
this.vname = vname;
|
|
|
}
|
|
|
|
|
|
void immatrikulieren() {
|
|
|
beginnStudium = LocalDate.now();
|
|
|
System.out.println(vname + " " + name + " wurde immatrikuliert.");
|
|
|
}
|
|
|
|
|
|
void exmatrikulieren() {
|
|
|
endeStudium = LocalDate.now();
|
|
|
System.out.println(vname + " " + name + " wurde exmatrikuliert.");
|
|
|
}
|
|
|
|
|
|
void besucht(Lehrveranstaltung lv) {
|
|
|
besuchteLehrveranstaltungen.add(lv);
|
|
|
lv.studierende.add(this);
|
|
|
}
|
|
|
|
|
|
int anzahl() {
|
|
|
return pruefungen.size();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Lehrveranstaltung {
|
|
|
String bezLV;
|
|
|
String studiengang;
|
|
|
int semesterSPO;
|
|
|
|
|
|
List<Dozent> dozenten = new ArrayList<>();
|
|
|
List<Studierender> studierende = new ArrayList<>();
|
|
|
List<Pruefungsgeschehen> pruefungen = new ArrayList<>();
|
|
|
|
|
|
Lehrveranstaltung(String bezLV, String studiengang, int semesterSPO) {
|
|
|
this.bezLV = bezLV;
|
|
|
this.studiengang = studiengang;
|
|
|
this.semesterSPO = semesterSPO;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Pruefungstyp {
|
|
|
int prTypNr;
|
|
|
String bezPruef;
|
|
|
int laenge;
|
|
|
|
|
|
Pruefungstyp(int prTypNr, String bezPruef, int laenge) {
|
|
|
this.prTypNr = prTypNr;
|
|
|
this.bezPruef = bezPruef;
|
|
|
this.laenge = laenge;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Pruefungsgeschehen {
|
|
|
Studierender pruefungsteilnehmer;
|
|
|
Lehrveranstaltung pruefungsgegenstand;
|
|
|
Pruefungstyp pruefungstyp;
|
|
|
int note;
|
|
|
|
|
|
Pruefungsgeschehen(
|
|
|
Studierender pruefungsteilnehmer,
|
|
|
Lehrveranstaltung pruefungsgegenstand,
|
|
|
Pruefungstyp pruefungstyp,
|
|
|
int note) {
|
|
|
|
|
|
this.pruefungsteilnehmer = pruefungsteilnehmer;
|
|
|
this.pruefungsgegenstand = pruefungsgegenstand;
|
|
|
this.pruefungstyp = pruefungstyp;
|
|
|
this.note = note;
|
|
|
|
|
|
pruefungsteilnehmer.pruefungen.add(this);
|
|
|
pruefungsgegenstand.pruefungen.add(this);
|
|
|
}
|
|
|
|
|
|
void anzeigen() {
|
|
|
System.out.println(
|
|
|
pruefungsteilnehmer.vname + " " + pruefungsteilnehmer.name
|
|
|
+ " | " + pruefungsgegenstand.bezLV
|
|
|
+ " | " + pruefungstyp.bezPruef
|
|
|
+ " | Note: " + note);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class HochschuleDemo {
|
|
|
public static void main(String[] args) {
|
|
|
|
|
|
Dozent d1 = new Dozent(1, "Müller", "Anna");
|
|
|
|
|
|
Studierender s1 = new Studierender("1001", "Maier", "Paul");
|
|
|
Studierender s2 = new Studierender("1002", "Schulz", "Eva");
|
|
|
|
|
|
Lehrveranstaltung lv1 =
|
|
|
new Lehrveranstaltung("Objektorientierung", "Wirtschaftsinformatik", 2);
|
|
|
|
|
|
Pruefungstyp pt1 = new Pruefungstyp(1, "Klausur", 90);
|
|
|
|
|
|
d1.haltenVorlesung(lv1);
|
|
|
|
|
|
s1.immatrikulieren();
|
|
|
s2.immatrikulieren();
|
|
|
|
|
|
s1.besucht(lv1);
|
|
|
s2.besucht(lv1);
|
|
|
|
|
|
d1.betreuen(s1);
|
|
|
|
|
|
Pruefungsgeschehen p1 =
|
|
|
new Pruefungsgeschehen(s1, lv1, pt1, 2);
|
|
|
|
|
|
p1.anzeigen();
|
|
|
|
|
|
System.out.println("Anzahl Prüfungen von "
|
|
|
+ s1.vname + " " + s1.name + ": " + s1.anzahl());
|
|
|
}
|
|
|
}
|
|
Programmlauf mit den beispielhaften Daten und Auswertungen: |
|
|
Paul Maier wurde immatrikuliert.
|
|
|
Eva Schulz wurde immatrikuliert.
|
|
|
Paul Maier | Objektorientierung | Klausur | Note: 2
|
|
|
Anzahl Prüfungen von Paul Maier: 1
|
|
22 Literatur |
|
Habelitz 2022 Habelitz, Hans-Peter: Programmieren lernen mit Java. (7. Auflage). Print-Ausgabe. Bonn 2022 (Rheinwerk). |
|
Habelitz 2025 Habelitz, Hans-Peter: Programmieren lernen mit Java. (8. Auflage). E-Book. Bonn 2025 (Rheinwerk) |
|
Kofler 2022 Kofler, Michael: Java. Der Grundkurs. Bonn 2022 (Rheinwerk) |
|
Pepper 2007 Pepper, Peter: Programmieren lernen. Eine grundlegende Einführung mit Java (3. Auflage), Berlin und Heidelberg 2007 (Springer-Verlag) |
|
Ratz et al. 2018 Ratz, Dietmar; Schulmeister-Zimolong, Dennis; Seese, Detlef; Wiesenberger, Jan: Grundkurs Programmieren in Java (8. Auflage). München 2018 |
|
Steppan 2020 Steppan, Berhard: Einstieg in Java mit Eclipse. München 2020 (Hanser) |
|
Ullenboom 2022 Ullenboom, Christian: Java ist auch eine Insel. Einführung, Ausbildung, Praxis. (16. Auflage). Bonn 2022 (Rheinwerk-Verlag) |
|
|
|
|