Wichtig für Smartphonebenutzer
Klassen sind wie Felder
Referenzdatentypen. Eine Klasse ist sozusagen eine Ansammlung von Variablen von verschiedenen Datentypen, die Klasse kann auch Methoden enthalten (z.B. zur Manipulation des Inhalts der Variablen in der Klasse). Mit einer Klasse ist es uns möglich verschiedene Datentypen zu einer
Komponentenvariable (Datentyp) zusammenzufügen. Diese
Komponentenvariable bezeichnet man als
Objekt oder
Instanz.
Um es etwas verständlicher zu machen habe ich das Programm "Namensliste" neu geschrieben. Hier ist nun unser Programm:
public class Namensliste {
public static class Liste {
public String vorname;
public String nachname;
public String geburtsdatum;
}
public static void main(String[] args) {
// Erzeuge ein Objekt person
Liste person = new Liste();
// Initialisiere Werte
person.vorname = "Franz";
person.nachname = "Mustermaier";
person.geburtsdatum = "22.06.1976";
// Gib die Person auf der Konsole aus
System.out.println("Vorname : " + person.vorname);
System.out.println("Nachname : " + person.nachname);
System.out.println("Geburtsdatum: " + person.geburtsdatum);
}
}
In dieser Zeile:
public static class Liste {
Erstellen wir die Klasse "Liste" das Schlüsselwort
public steht für eine öffentliche Klasse, auf die jeder Zugriff hat. Da es eine innere Klasse ist. kann nur in der Klasse "Namensliste" darauf zugegriffen werden. Das Schlüsselwort
static gibt dem Kompiler an dass es eine innere Klasse ist. Mit dem Schlüsselwort
class und dem Bezeichner erstellen wir eine Klasse (Bei dem Bezeichner gelten alle Regeln wie bei den Variablenbezeichner auch, nur dass hier der Bezeichner mit einem Großbuchstaben beginnt. Die Variablen der Klasse stehen im zugehörigen Anweisungsblock
{}.
In diesen Zeilen deklarieren wir die
Objektvariablen der Klasse:
public String vorname;
public String nachname;
public String geburtsdatum;
Mit dem Schlüsselwort
public sind die Variablen öffentlich, damit hat man außerhalb der Klasse die Möglichkeit die Werte der Variablen z.B. zu ändern.
Jetzt deklarieren und erzeugen mit dem
new-Operator das Objekt "person".
Liste person = new Liste();
In den nächste Zeilen übergeben wir Werte an die Variablen des Objektes "person":
person.vorname = "Franz";
person.nachname = "Mustermaier";
person.geburtsdatum = "22.06.1976";
Mit dem Objektbezeichner gefolgt von dem
.-Operator und dem Bezeichner der gewünschten Variable übergeben wir einen Wert mit dem
=-Operator der Variable.
Hier geben wir die Werte auf der Konsole aus:
System.out.println("Vorname : " + person.vorname);
System.out.println("Nachname : " + person.nachname);
System.out.println("Geburtsdatum: " + person.geburtsdatum);
Eine Klasse verfügt immer über einen
Konstruktor (
Default-Konstruktor), wenn wir keinen erstellen, erstellt der Compiler selber einen Default-Konstruktor. Im Konstruktor können wir z.B. Standardwerte initialisieren oder Objekte und Felder erzeugen. Erweitern wir unser Beispiel mit einem Default-Konstruktor:
...
public String geburtsdatum;
public Liste() {
vorname = "leer";
nachname = "leer";
geburtsdatum = "leer";
}
...
Mit
public geben wir an dass auf dem Konstruktor öffentlich ist und mit dem
new-Operator darauf zugegriffen werden kann (ein Konstruktor wird nur
einmal beim erzeugen des Objektes durch den
new-Operator aufgerufen. Der Bezeichner des Konstruktors muss exakt den selben Bezeichner wie den der Klasse haben. In den beiden
() steht die
Parameterliste, weil es sich hier um den
Default-Konstruktor handelt ist die Parameterliste leer.
Es wird schon aufgefallen sein, wenn ein Objekt erzeugt dass nach dem
new-Operator der
Konstruktor der
Klasse steht.
Nehmen wir an, wir wollen unsere Klasse "Liste" in mehreren Programmen nutzen. Dann sollten wir diese in eine externe Datei schreiben. Dafür erstellen wir eine neu Datei im Projekt mit dem Klassennamen und kopieren unser Klasse Liste hinein:
public class Liste {
public String vorname;
public String nachname;
public String geburtsdatum;
public Liste() {
vorname = "leer";
nachname = "leer";
geburtsdatum = "leer";
}
}
Da es jetzt keine innere Klasse ist, müssen wir das Schlüsselwort
static vor
class weg lassen.
Jetzt schreiben wir einen
Konstruktor mit einer
Parameterliste:
...
geburtsdatum = "leer";
}
public Liste(String vorname,
String nachname, String geburtsdatum) {
this.vorname = vorname;
this.nachname = nachname;
this.geburtsdatum = geburtsdatum;
}
...
Nun haben wir einen Konstruktor mit drei Parameter. Wie wir sehen, haben die Parameter genau die selben Namen (Bezeichner) wie die Objektvariablen. Jetzt haben wir ein Problem, wie weiß der Compiler welche Variable gemeint ist? Mit dem
this Schlüsselwort haben wir eine elegant Lösung. Das
this Schlüsselwort zeigt immer auf das
Objekt und damit ist es uns dann auch möglich die Variablen richtig zuzuweisen. Die Variablen in der Parameterliste sind nur im
Anweisungsblock des
Konstruktors gültig.
Jetzt bleibt es uns überlassen mit welchem Konstruktor wir das Objekt erzeugen:
Liste person = new Liste();
oder
Liste person = new Liste("Bernd", "Huber", "11.9.1955");
In der
Objektorientierten Programmierung (OOP), ist es nicht gerne gesehen seine Objektvariablen öffentlich zu deklarieren, deshalb setzen wir alle drei Objektvariablen auf
private. Damit kann man einen unbefugten Zugriff auf die Objektvariablen verhindern.
public class Liste {
private String vorname;
private String nachname;
private String geburtsdatum;
...
Damit wir jetzt außerhalb der Klasse auf die Variablen zugreifen können, müssen wir und die passenden
get- und
set-Methoden schreiben. Die
get-Methode gibt die dazugehörige Variable des Objektes mit dem Schlüsselwort
return zurück (mit return wird die Methode sofort beendet, deshalb sollte
return immer am Ende des Methodenblocks sein). In der
set-Methode wird ein Wert der dazugehörigen Variable des Objektes übergeben. Ergänzen wir unsere Klasse "Liste" damit:
...
this.geburtsdatum = geburtsdatum;
}
public String getVorname() {
return vorname;
}
public void setVorname(String vorname) {
this.vorname = vorname;
}
public String getNachname() {
return nachname;
}
public void setNachname(String nachname) {
this.nachname = nachname;
}
public String getGeburtsdatum() {
return geburtsdatum;
}
public void setGeburtsdatum(String geburtsdatum) {
this.geburtsdatum = geburtsdatum;
}
...
Schauen wir uns eine get-Methode genauer an:
public String getVorname() {
return vorname;
}
Mit dem Schlüsselwort
public legen wir fest dass die Methode öffentlich ist. Wenn die Methode einen
Rückgabewert haben soll, müssen wir den Datentyp angeben, hier ist es ein String. Bei einer Methode wie die
set-Methode hat man keinen
Rückgabewert und gibt dafür das Schlüsselwort
void an. Der
Methodenname sollte mit einem Kleinbuchstaben anfangen. Für eine get-Methode muss nicht unbedingt ein get am Anfang stehen, das Selbe gilt auch für die set-Methode, get und set dient nur um den Code übersichtlicher zu machen. Es wäre auch möglich "wievieleBratwürsteHabIch()" zu nennen. Eine Methode darf mehrere Werte in der
Parameterliste enthalten, aber nur ein
Rückgabewert.
Jetzt ändern wir noch den Code in der Klasse "Namensliste" ab damit der wieder kompatibel mit der Klasse "Liste" ist:
...
// Erzeuge ein Objekt person
Liste person = new Liste();
// Initialisiere Werte
person.setVorname("Franz");
person.setNachname("Mustermaier");
person.setGeburtsdatum("22.06.1976");
// Gib die Person auf der Konsole aus
System.out.println("Vorname : " + person.getVorname());
System.out.println("Nachname : " + person.getNachname());
System.out.println("Geburtsdatum: " + person.getGeburtsdatum());
...
Wie man sehen kann ist der Code mit
get- und
set-Methoden viel verständlicher geworden.
Jetzt wollen wir unser Programm eine Menü und eine Eingabeaufforderung spendieren. Da wir jetzt Klassen kennen schreiben wir uns gleich mal eine für die Eingabeaufforderung. Wir erstellen uns eine neue Klasse Namens "Input". Hier ist einfach mal der ganze Programmcode dazu:
import java.util.Scanner;
public class Input {
// Mit private wird das Erzeugen eines
// Objektes verhindert
private Input() {
;
}
// Scanner fängt die Tastatureingabe ab
private static Scanner extrahieren() {
return new Scanner(System.in);
}
// Tastatureingabe wird als int übergeben
public static int inputInt() {
return extrahieren().nextInt();
}
// Tastatureingabe wird als String übergeben
public static String inputString() {
return extrahieren().nextLine();
}
}
Als erstes fällt der leere Default-Konstruktor auf:
private Input() {
-
}
Da ein
Default-Konstruktor vom Compiler normalerweise einen öffentlichen Konstruktor mit
public erzeugt, müssen wir uns einen Default-Konstruktor selber schreiben, da unserer Klasse kein Objekt erzeugt werden soll verwenden wir das Schlüsselwort
private. Wenn der Konstruktor nicht öffentlich ist kann auch kein Objekt der Klasse "Input" mit dem
new-Operator außerhalb der Klasse erzeugt werden.
private static Scanner extrahieren() {
return new Scanner(System.in);
}
Auf die Methode "extrahieren()" soll von außen nicht zugreifbar sein, deshalb verwenden wir wieder das Schlüsselwort
private. Die Methode soll als
Rückgabewert ein
namenloses Objekt vom Datentypen Scanner zurückgeben. Dieses Objekt braucht keinen Bezeichner da es erzeugt wird und dessen Referenz einfach weiter übergeben wird und danach nicht mehr verwendet wird. Das Schlüsselwort
static teilt dem Compiler mit dass die Methode eine
Klassenmethode ist und kein
Objektmethode ist. Bei
Objektmethoden muss ein Objekt mit dem
new-Operator erzeugt werden, um Zugriff auf die Methoden zu bekommen. Eine
Klassenmethode wird durch die
Klasse aufgerufen und nicht durch den Bezeichner des Objektes.
public static int inputInt() {
return extrahieren().nextInt();
}
Die beiden Methoden "inputInt()" und "inputString()" sind auch
Klassenmethoden, auf die aber öffentlich zugegriffen werden kann. Der Rückgabewert ist ein int Wert oder ein String. Die Methode "extrahieren()" hat als Rückgabewert ein
namenloses Objekt dessen Datentyp Scanner ist. Mit der Methode "nextInt()" oder "nextLine()" übergeben wir die Tastatureingabe als int-Wert oder String als Rückgabewert der Methoden "inputInt()" oder "inputString()".
Jetzt erstellen wir uns noch eine neue Klasse "Menue". Hier ist die gesamte Klasse "Menue":
public class Menue {
// Deklariere ein Feld
private Liste[] personen;
// Deklariere ein Objekt
private Liste person;
// Default-Konstruktor
public Menue() {
// Erzeuge ein Feld mit 100 Elementen
personen = new Liste[100];
// Initialisiert die Standardwerte der Felder
for(int i = 0; i < personen.length; i++) {
personen[i] = new Liste("--", "--", "--");
}
// Übergibt die Referenz des ausgewählten Feldes
// dem Objekt person
setPerson(personen[0]);
}
public boolean hauptMenue() {
// Gebe das Menü auf der Konsole aus
System.out.println("+-----------------------+");
System.out.println("| Namensliste |");
System.out.println("+-+---------------------+");
System.out.println("|1| Namen eingeben |");
System.out.println("|2| Namen anzeigen |");
System.out.println("|3| Eintrag wechseln |");
System.out.println("|4| Beenden |");
System.out.println("+-+---------------------+");
System.out.print(" > ");
// Liest die Tastatureingabe aus und gibt den
// Rückgabewert der Methode pruefeEingabe
return pruefeEingabe(Input.inputInt()) ;
}
private boolean pruefeEingabe(int eingabe) {
// Entscheidungsanweisungen des Menüs
if(eingabe == 1) {
// Eingabe wird aufgerufen
namenEingabe();
}
else if(eingabe == 2) {
// Ausgabe wird aufgerufen
namenAusgabe();
}
else if(eingabe == 3) {
// Eintrag wird gewechselt
eintragWechseln();
}
else if(eingabe == 4) {
// Rückgabewert für die Hauptschleife
// mit dessen das Programm beendet wird
return false;
}
else {
// Bei fehlerhafter eingabe wird
// eine Warnung auf der Konsole ausgegeben
eingabeFehler();
}
// Rückgabewert für die Hauptschleife
// das Programm läuft weiter
return true;
}
private void namenEingabe() {
// Eingabe
System.out.println("-------------------------");
System.out.print("Vorname : ");
person.setVorname(Input.inputString());
System.out.println("-------------------------");
System.out.print("Nachnamer : ");
person.setNachname(Input.inputString());
System.out.println("-------------------------");
System.out.print("Geburtsdatum : ");
person.setGeburtsdatum(Input.inputString());
System.out.println("-------------------------");
}
private void namenAusgabe() {
// Ausgabe
System.out.println("-------------------------");
System.out.println("Vorname : " + person.getVorname());
System.out.println("-------------------------");
System.out.println("Nachnamer : " + person.getNachname());
System.out.println("-------------------------");
System.out.println("Geburtsdatum : " + person.getGeburtsdatum());
System.out.println("-------------------------");
}
private void eintragWechseln() {
// Wiederholungsanweisung für das Menüpunkt
// eintragWechseln
while (true) {
System.out.println("+-----------------------+");
System.out.println("|Es können Eintrage von |");
System.out.println("|1-100 ausgewählt werden|");
System.out.println("+-----------------------+");
System.out.print("> ");
int eingabe = (Input.inputInt());
// Bei richtiger Eingabe wird die
// Wiederholungsanweisung mit brake
// verlassen
if (eingabe > 0 && eingabe < 100) {
person = personen[eingabe-1];
break;
}
// Bei fehlerhafter Eingabe wird eine
// Warnung auf der Konsole ausgegeben
else {
eingabeFehler();
}
}
}
private void setPerson(Liste person) {
// Referenz wird übergeben
this.person = person;
}
private void eingabeFehler() {
// Warnung wird in der Konsole ausgegeben
System.out.println("+-----------------------+");
System.out.println("|Fehler bei der Eingabe!|");
System.out.println("+-----------------------+");
}
}
Gehen wir den Code einfach mal durch:
private Liste[] personen;
Hier deklarieren wir ein
Feld mit
private, in dem die Einträge gespeichert werden.
private Liste person;
In der Zeile deklarieren wir ein
Objekt das auch
private ist.
public Menue() {
// Erzeuge ein Feld mit 100 Elementen
personen = new Liste[100];
// Initialisiert die Standardwerte der Felder
for(int i = 0; i < personen.length; i++) {
personen[i] = new Liste("--", "--", "--");
}
// Übergibt die Referenz des ausgewählten Feldes
// dem Objekt person
setPerson(personen[0]);
}
Im Default-Konstruktor wird in Zeile 3 für das
Feld "personen" 100 Elemente mit dem
new-Operator erzeugt. Da bisher die einzelnen Referenzen der Elemente des Feldes auf
null zeigen (eine
null-Referenz zeigt auf keinen Speicheradresse), wird mit der for-Wiederholungsanweisung den
Referenzen eine Speicheradresse übergeben und Standardwerte initialisiert. In Zeile 10 wird dem Objekt "person" eine Referenz des Feldes "personen" durch die "setPerson()" Methode übergeben, mit dieser Methode wird das aktuelle Element festgelegt in dem die Eingaben übergeben werden sollen. Das
Objekt "person" ist sozusagen zuständig die Eingaben in dem ausgewählten Element des
Feldes "personen" zu übergeben.
public boolean hauptMenue() {
// Gebe das Menü auf der Konsole aus
System.out.println("+-----------------------+");
System.out.println("| Namensliste |");
System.out.println("+-+---------------------+");
System.out.println("|1| Namen eingeben |");
System.out.println("|2| Namen anzeigen |");
System.out.println("|3| Eintrag wechseln |");
System.out.println("|4| Beenden |");
System.out.println("+-+---------------------+");
System.out.print(" > ");
// Liest die Tastatureingabe aus und gibt den
// Rückgabewert der Methode pruefeEingabe
return pruefeEingabe(Input.inputInt()) ;
}
Die Methode" hauptMenue()" gibt das Menü auf der Konsole aus und erwartet eine Tastatureingabe. In Zeile 14 sind einige Informationen die auf Anhieb nicht gleich sichtbar sind. Mit "Input.inputInt()" erwarten wir einen Ganzzahligen Wert als Eingabe (wie wir sehen können ist diese Methode eine
Klassenmethode, da wir sie mit dem
Klassennamen gefolgt mit dem
.-Operator und dem
Methodennamen aufrufen. Wie wir wissen hat die" inputInt()" Methode einen Rückgabewert der der Methode "pruefeEingabe" durch die
Parameterliste übergeben wird diese Methode hat den Rückgabewert boolean der gleichzeitig auch der Rückgabewert der Methode "hauptMenue()" ist.
private boolean pruefeEingabe(int eingabe) {
// Entscheidungsanweisungen des Menüs
if(eingabe == 1) {
// Eingabe wird aufgerufen
namenEingabe();
}
else if(eingabe == 2) {
// Ausgabe wird aufgerufen
namenAusgabe();
}
else if(eingabe == 3) {
// Eintrag wird gewechselt
eintragWechseln();
}
else if(eingabe == 4) {
// Rückgabewert für die Hauptschleife
// mit dessen das Programm beendet wird
return false;
}
else {
// Bei fehlerhafter eingabe wird
// eine Warnung auf der Konsole ausgegeben
eingabeFehler();
}
// Rückgabewert für die Hauptschleife
// das Programm läuft weiter
return true;
}
In der Methode "pruefeEingabe" wird die Variable aus der Parameterliste in einer if-Entscheidungsanweisung überprüft und bei zutreffenden Wert die dazugehörige Methode aufgerufen. Als Rückgabewert wird true zurückgegeben oder wenn die If-Anweisung den korrekten Wert in Zeile 15 erhält und damit den Rückgabewert false bekommt.
private void namenEingabe() {
// Eingabe
System.out.println("-------------------------");
System.out.print("Vorname : ");
person.setVorname(Input.inputString());
System.out.println("-------------------------");
System.out.print("Nachnamer : ");
person.setNachname(Input.inputString());
System.out.println("-------------------------");
System.out.print("Geburtsdatum : ");
person.setGeburtsdatum(Input.inputString());
System.out.println("-------------------------");
}
In der Methode" namenEingeben()", werden nacheinander drei Eingabeauforderungen in der Konsole erstellt. "Input.inputString()" gibt die Eingabe als String zurück, mit der
set-Methode wird der String durch das
Objektes "person" ein
Element des
Feldes "personen" übergeben, auf das die
Referenz "person" zeigt.
private void namenAusgabe() {
// Ausgabe
System.out.println("-------------------------");
System.out.println("Vorname : " + person.getVorname());
System.out.println("-------------------------");
System.out.println("Nachnamer : " + person.getNachname());
System.out.println("-------------------------");
System.out.println("Geburtsdatum : " + person.getGeburtsdatum());
System.out.println("-------------------------");
}
Diese Methode gibt den Inhalt des aktuellen Elements durch das Objekt "person" aus.
private void eintragWechseln() {
// Wiederholungsanweisung für das Menüpunkt
// eintragWechseln
while (true) {
System.out.println("+-----------------------+");
System.out.println("|Es können Eintrage von |");
System.out.println("|1-100 ausgewählt werden|");
System.out.println("+-----------------------+");
System.out.print("> ");
int eingabe = (Input.inputInt());
// Bei richtiger Eingabe wird die
// Wiederholungsanweisung mit brake
// verlassen
if (eingabe > 0 && eingabe < 100) {
person = personen[eingabe-1];
break;
}
// Bei fehlerhafter Eingabe wird eine
// Warnung auf der Konsole ausgegeben
else {
eingabeFehler();
}
}
}
Durch die Methode "eintragWechseln()" wird eine Eingabeaufforderung in der Konsole erstellt. Eine If-Anweisung überprüft ob die Variable "eingabe" größer ist als 0 und kleiner als 101 ist, damit die Variable als Index des Feldes" personen" verwendet werden kann, wenn nicht wird eine Fehlermeldung auf der Konsole ausgegeben und die Eingabeaufforderung wird nochmal wiederholt. Weil der Index des Feldes "personen" mit 0 beginnt aber wir mit der 1 als ersten Eintrag angeben müssen wir bei der Indexangabe in Zeile 18 die Variable"eingabe" mit 1 subtrahieren, damit es keinen Fehler gibt.
private void setPerson(Liste person) {
// Referenz wird übergeben
this.person = person;
}
Die Methode "setPersonen()" übergibt dem Objekt "person"eine Referenz.
private void eingabeFehler() {
// Warnung wird in der Konsole ausgegeben
System.out.println("+-----------------------+");
System.out.println("|Fehler bei der Eingabe!|");
System.out.println("+-----------------------+");
}
Die Methode "eingabeFehler()" gibt eine Fehlermeldung auf der Konsole aus.
Jetzt ändern wir noch den Code in der Klasse Namensliste. Hier ist der Code:
public class Namensliste {
public static void main(String[] args) {
// Deklariere Variable
boolean wiederholen = true;
// Deklariere und erzeuge eine Objekt
Menue menue = new Menue();
// Hauptschleife des Programms
while (wiederholen) {
// Menu auf der Konsole ausgeben
wiederholen = menue.hauptMenue();
}
}
}
In Zeile 5 wird eine Variable mit dem Datentyp boolean deklariert und mit true initialisiert. In der Zeile 7 wird das Objekt "menue" deklariert und initialisiert. Die while-Anweisung wird solange wiederholt, bis die Variable den Rückgabewert true von der Objektmethode "hauptMenue()" erhällt.
Jetzt haben wir unser Programm fertig und können es ausführen.