Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Die Funktionsbibliothek
10 Threads und nebenläufige Programmierung
11 Raum und Zeit
12 Datenstrukturen und Algorithmen
13 Dateien und Datenströme
14 Die eXtensible Markup Language (XML)
15 Grafische Oberflächen mit Swing
16 Grafikprogrammierung
17 Netzwerkprogrammierung
18 Verteilte Programmierung mit RMI und Web-Services
19 JavaServer Pages und Servlets
20 Applets
21 Midlets und die Java ME
22 Datenbankmanagement mit JDBC
23 Reflection und Annotationen
24 Logging und Monitoring
25 Sicherheitskonzepte
26 Java Native Interface (JNI)
27 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort

Download:
- ZIP, ca. 12,5 MB
Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren mit der Java Standard Edition Version 6
Buch: Java ist auch eine Insel

Java ist auch eine Insel
7., aktualisierte Auflage
geb., mit DVD (November 2007)
1.492 S., 49,90 Euro
Galileo Computing
ISBN 978-3-8362-1146-8
Pfeil 6 Eigene Klassen schreiben
Pfeil 6.1 Eigene Klassen mit Eigenschaften deklarieren
Pfeil 6.1.1 Attribute deklarieren
Pfeil 6.1.2 Methoden deklarieren
Pfeil 6.1.3 Die this-Referenz
Pfeil 6.2 Privatsphäre und Sichtbarkeit
Pfeil 6.2.1 Für die Öffentlichkeit: public
Pfeil 6.2.2 Paketsichtbar
Pfeil 6.2.3 Kein Public Viewing – Passwörter sind privat
Pfeil 6.2.4 Wieso nicht freie Methoden und Variablen für alle?
Pfeil 6.2.5 Privat ist nicht ganz privat: Es kommt darauf an, wer’s sieht
Pfeil 6.2.6 Zugriffsmethoden für Attribute deklarieren
Pfeil 6.2.7 Setter und Getter nach der JavaBeans-Spezifikation
Pfeil 6.3 Statische Methoden und statische Attribute
Pfeil 6.3.1 Warum statische Eigenschaften sinnvoll sind
Pfeil 6.3.2 Statische Eigenschaften mit static
Pfeil 6.3.3 Statische Eigenschaften über Referenzen nutzen?
Pfeil 6.3.4 Warum die Groß- und Kleinschreibung wichtig ist
Pfeil 6.3.5 Statische Eigenschaften und Objekteigenschaften
Pfeil 6.3.6 Statische Variablen zum Datenaustausch
Pfeil 6.3.7 Statische Blöcke als Klasseninitialisierer
Pfeil 6.4 Konstanten und Aufzählungen
Pfeil 6.4.1 Konstanten über öffentliche statische finale Variablen
Pfeil 6.4.2 Eincompilierte Belegungen der Klassenvariablen
Pfeil 6.4.3 Typ(un)sicherere Aufzählungen
Pfeil 6.4.4 Aufzählungen mit enum
Pfeil 6.5 Objekte anlegen und zerstören
Pfeil 6.5.1 Konstruktoren schreiben
Pfeil 6.5.2 Der Standard-Konstruktor
Pfeil 6.5.3 Parametrisierte und überladene Konstruktoren
Pfeil 6.5.4 Konstruktor nimmt ein Objekt vom eigenen Typ an (Copy-Konstruktor)
Pfeil 6.5.5 Einen anderen Konstruktor der gleichen Klasse aufrufen
Pfeil 6.5.6 Initialisierung der Objekt- und Klassenvariablen
Pfeil 6.5.7 Finale Werte im Konstruktor und in statischen Blöcken setzen
Pfeil 6.5.8 Exemplarinitialisierer (Instanzinitialisierer)
Pfeil 6.5.9 Ihr fehlt uns nicht – der Garbage-Collector
Pfeil 6.5.10 Implizit erzeugte String-Objekte
Pfeil 6.5.11 Private Konstruktoren, Utility-Klassen, Singleton, Fabriken
Pfeil 6.6 Assoziationen zwischen Objekten
Pfeil 6.6.1 Unidirektionale 1:1-Beziehung
Pfeil 6.6.2 Bidirektionale 1:1-Beziehungen
Pfeil 6.6.3 Unidirektionale 1:n-Beziehung
Pfeil 6.7 Vererbung
Pfeil 6.7.1 Vererbung in Java
Pfeil 6.7.2 Spielobjekte modelliert
Pfeil 6.7.3 Einfach- und Mehrfachvererbung
Pfeil 6.7.4 Sichtbarkeit protected
Pfeil 6.7.5 Konstruktoren in der Vererbung und super
Pfeil 6.7.6 Automatische und explizite Typanpassung
Pfeil 6.7.7 Das Substitutionsprinzip
Pfeil 6.7.8 Typen mit dem binären Operator instanceof testen
Pfeil 6.7.9 Methoden überschreiben
Pfeil 6.7.10 Mit super an die Eltern
Pfeil 6.7.11 Kovariante Rückgabetypen
Pfeil 6.7.12 Array-Typen und Kovarianz
Pfeil 6.7.13 Zusammenfassung zur Sichtbarkeit
Pfeil 6.8 Dynamisches Binden
Pfeil 6.8.1 Unpolymorph bei privaten, statischen und finalen Methoden
Pfeil 6.8.2 Polymorphie bei Konstruktoraufrufen
Pfeil 6.8.3 Finale Klassen
Pfeil 6.8.4 Nicht überschreibbare (finale) Methoden
Pfeil 6.9 Abstrakte Klassen und abstrakte Methoden
Pfeil 6.9.1 Abstrakte Klassen
Pfeil 6.9.2 Abstrakte Methoden
Pfeil 6.10 Schnittstellen
Pfeil 6.10.1 Deklarieren von Schnittstellen
Pfeil 6.10.2 Implementieren von Schnittstellen
Pfeil 6.10.3 Markierungsschnittstellen
Pfeil 6.10.4 Ein Polymorphie-Beispiel mit Schnittstellen
Pfeil 6.10.5 Die Mehrfachvererbung bei Schnittstellen
Pfeil 6.10.6 Keine Kollisionsgefahr bei Mehrfachvererbung
Pfeil 6.10.7 Erweitern von Interfaces – Subinterfaces
Pfeil 6.10.8 Vererbte Konstanten bei Schnittstellen
Pfeil 6.10.9 Schnittstellenmethoden, die nicht implementiert werden müssen
Pfeil 6.10.10 Abstrakte Klassen und Schnittstellen im Vergleich
Pfeil 6.11 Geschachtelte (innere) Klassen, Schnittstellen, Aufzählungen
Pfeil 6.11.1 Statische innere Klassen und Schnittstellen
Pfeil 6.11.2 Mitglieds- oder Elementklassen
Pfeil 6.11.3 Lokale Klassen
Pfeil 6.11.4 Anonyme innere Klassen
Pfeil 6.11.5 this und Vererbung
Pfeil 6.12 Generische Datentypen
Pfeil 6.12.1 Einfache Klassenschablonen
Pfeil 6.12.2 Einfache Methodenschablonen
Pfeil 6.12.3 Umsetzen der Generics, Typlöschung und Raw-Types
Pfeil 6.12.4 Einschränken der Typen
Pfeil 6.12.5 Generics und Vererbung, Invarianz
Pfeil 6.12.6 Wildcards
Pfeil 6.13 Die Spezial-Oberklasse Enum
Pfeil 6.13.1 Methoden auf Enum-Objekten
Pfeil 6.13.2 enum mit eigenen Konstruktoren und Methoden
Pfeil 6.14 Dokumentationskommentare mit JavaDoc
Pfeil 6.14.1 Einen Dokumentationskommentar setzen
Pfeil 6.14.2 Mit javadoc eine Dokumentation erstellen
Pfeil 6.14.3 HTML-Tags in Dokumentationskommentaren
Pfeil 6.14.4 Generierte Dateien
Pfeil 6.14.5 Dokumentationskommentare im Überblick
Pfeil 6.14.6 JavaDoc und Doclets
Pfeil 6.14.7 Veraltete (deprecated) Klassen, Konstruktoren und Methoden


Galileo Computing - Zum Seitenanfang

6.4 Konstanten und Aufzählungen Zur nächsten ÜberschriftZur vorigen Überschrift

In Programmen gibt es Variablen, die sich ändern wie ein Schleifenzähler, aber auch andere, die sich beim Ablauf eines Programms nicht ändern. Dazu gehören etwa die Startzeit der Tagesschau oder die Ausmaße einer DIN-A4-Seite [Ein DIN-A4-Blatt ist 29,7 Zentimeter hoch und 21,0 Zentimeter breit. ] . Die Werte sollten nicht wiederholt im Quellcode stehen, sondern über ihre Namen angesprochen werden. Dazu werden Variablen deklariert, denen genau der konstante Wert zugewiesen wird; die Konstanten heißen dann symbolische Konstanten.

In Java gibt es zur Deklaration von Konstanten zwei Möglichkeiten:

  • Öffentliche statische finale Variablen nehmen konstante Werte auf.
  • Aufzählungen über ein enum (die intern aber auch nur öffentliche final statische Werte sind).

Galileo Computing - Zum Seitenanfang

6.4.1 Konstanten über öffentliche statische finale Variablen Zur nächsten ÜberschriftZur vorigen Überschrift

Statische Variablen werden auch verwendet, um symbolische Konstanten zu deklarieren. Damit die Variablen unveränderlich bleiben, gesellt sich der Modifizierer final hinzu. Dem Compiler wird auf diese Weise mitgeteilt, dass dieser Variable nur einmal ein Wert zugewiesen werden darf. Für Variablen bedeutet dies: Es sind Konstanten, jeder spätere Schreibzugriff wäre ein Fehler.

Konstante Werte haben wir schon bei GameUtils eingesetzt:

Listing 6.23 GameUtils, Ausschnitt

public class GameUtils 
{ 
  public static final double MAX_ID_LEN = 20 /* chars */; 
  ... 
}

Da im Quellcode das Vorkommen von Zahlen wie die 20 undurchsichtig wären, sind symbolische Namen zwingend. Stehen dennoch Zahlen ohne offensichtliche Bedeutung im Quellcode, so werden sie magische Zahlen (engl. magic numbers) genannt. Es gilt, diese Werte in Konstanten zu fassen und sinnvoll zu benennen.


Tipp Tipp Es ist eine gute Idee, die Namen von Konstanten durchgehend großzuschreiben, um ihre Bedeutung hervorzuheben.


Der Zugriff auf die Variablen sieht genauso aus wie ein Zugriff auf andere statische Variablen.


Beispiel Beispiel Greife auf Konstanten zurück:

System.out.println( Math.PI ); 
int len = GameUtils.MAX_ID_LEN; 
if ( string.length() >= GameUtils.MAX_ID_LEN ) 
  System.out.println( "Zu lang!" );


Galileo Computing - Zum Seitenanfang

6.4.2 Eincompilierte Belegungen der Klassenvariablen Zur nächsten ÜberschriftZur vorigen Überschrift

Finale Klassenvariablen können in der Entwicklung mit einer größeren Anzahl von Klassen zu einem Problem werden. Das liegt an der Eigenschaft der finalen Werte, dass sie sich nicht ändern können und sich daher sicher an der Stelle einsetzen lassen, wo sie gebraucht werden. Ein Beispiel:

class Finance 
{ 
  public static final int TAX = 19; 
}

Greift eine andere Klasse auf die Variable TAX zu, ist das im Quellcode nicht als direkter Variablenzugriff Finance.TAX kodiert, sondern der Compiler hat das Literal 19 direkt an jede Aufrufstelle eingesetzt. Dies ist eine Optimierung des Compilers, die er laut Java-Spezifikation machen kann.

Das ist zwar nett, bringt aber gewaltige Probleme mit sich, etwa dann, wenn sich die Konstante einmal ändert. Dann muss nämlich auch jede Klasse übersetzt werden, die Bezug auf die Konstante hatte. Werden die abhängigen Klassen nicht neu übersetzt, ist in ihnen immer noch der alte Wert eincompiliert.

Die Lösung ist, die Bezug nehmenden Klassen neu zu übersetzen und sich am besten anzugewöhnen, bei einer Änderung einer Konstante gleich alles neu zu compilieren. Ein anderer Weg transformiert die finale Variable in eine später initialisierte Form:

class Finance 
{ 
  public static final int TAX = Integer.valueOf( 19 ); 
}

Die Initialisierung findet in jedem Konstruktor statt, und die Konstante mit dem Literal 19 ist zunächst einmal verschwunden. Der Compiler wird also beim Zugriff auf Finance.TAX nicht die 19 vorfinden und daher das Literal an den Aufrufstellen nicht einbauen können. In der Klassendatei wird der Bezug Finance.TAX weiterhin zu finden sein, und eine Änderung der Konstante erzwingt keine neue Übersetzung der Klassen.


Galileo Computing - Zum Seitenanfang

6.4.3 Typ(un)sicherere Aufzählungen Zur nächsten ÜberschriftZur vorigen Überschrift

Konstanten sind eine wertvolle Möglichkeit, den Quellcode aussagekräftiger zu machen. Das gilt auch für Aufzählungen, also diverse Konstanten, die für unterschiedliche Ausprägungen stehen. Eine Klasse Materials soll zum Beispiel Konstanten für die Beschaffenheit eines Materials deklarieren:

Listing 6.24 Materials.java

public class Materials 
{ 
  public static final int SOFT   = 0; 
  public static final int HARD   = 1; 
  public static final int DRY    = 2; 
  public static final int WET    = 3; 
  public static final int SMOOTH = 4; 
  public static final int ROUGH  = SMOOTH + 1; 
}

Für ihre Belegungen ist es günstig, sie relativ zum Vorgänger zu wählen, um das Einfügen in der Mitte zu vereinfachen. Das sehen wir bei der vorletzten Variable ROUGH.

Einfache Konstantentypen – wie bei uns int – bringen jedoch den Nachteil mit sich, dass die Konstanten nicht unbedingt von jedem angewendet werden müssen und ein Programmierer die Zahlen oder Zeichenketten eventuell direkt einsetzt. Dieses Problem ergibt sich zum Beispiel dann, wenn ein Font-Objekt für die grafische Oberfläche angelegt werden soll, aber unser Gedächtnis versagt, in welcher Reihenfolge die Parameter zu füllen sind. Ein Fallbeispiel:

Font f = new Font( "Dialog", 12, Font.BOLD );

Leider ist dies falsch, denn die Argumente für die Zeichensatzgröße und den Schriftstil sind vertauscht, es müsste new Font("Dialog", Font.BOLD, 12) heißen. Das Problem ist, dass die Konstanten nur Namen für Werte eines frei zugänglichen Grundtyps (auch hier int) sind und nur die Variablenbelegung, also der Wert, an die Funktion übergeben wird. Niemand kann verbieten, dass die Werte direkt eingetragen werden. Das führt dann zu Fehlern wie im oberen Fall. In diesem ist 12 die Ganzzahl für den Schriftstil, obwohl es dafür nur die Werte 0, 1, 2 geben sollte. Mit Zeichenketten als Werten der Konstanten kommen wir der Lösung auch nicht näher.


Hinweis Hinweis Ganzzahlen haben aber durchaus ihren Vorteil, wenn es Mischungen von Aufzählungen gibt, also etwa ein hartes und raues Material. Das lässt sich durch Materials.HARD + Materials.ROUGH darstellen – was aber nur dann gut funktioniert, wenn jede Konstante ein Bit im Wort einnimmt, wenn also die Werte der Konstanten 1, 2, 4, 8, 16, ... lauten.


Eine gute Möglichkeit, von Ganzzahlen wegzukommen, ist, Objekte einer Klasse als Konstanten einzusetzen. Java bietet seit der Version 5 ein Sprachkonstrukt über das neue Schlüsselwort enum für richtige Aufzählungen.


Geschichte Sun hat in Java diverse Schlüsselwörter reserviert, aber enum nicht seit Beginn. Als dann in Java 5 plötzlich ein neues Schlüsselwort hinzukam, mussten Entwickler viel Quellcode anpassen und Variablennamen ändern, denn gerne wurde für den Variablentyp java.util.Enumeration der Variablenname »enum« gewählt.



Galileo Computing - Zum Seitenanfang

6.4.4 Aufzählungen mit enum topZur vorigen Überschrift

In der Schreibweise für Aufzählungen ersetzt das Schlüsselwort enum das Schlüsselwort class und ist auch ähnlich zu nutzen. (Eine enum-Deklaration erlaubt auch die Deklaration von Methoden und Variablen. Somit verhält sie sich wie eine bekannte Klassendeklaration, nur dass keine Unterklassen und Oberklassen möglich sind.)

Aufzählungen für Wochentage sind ein gutes Beispiel:

Listing 6.25 com/tutego/weekday/Weekday.java

package com.tutego.weekday; 
 
public enum Weekday 
{ 
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY 
}

Die Konstantennamen werden wie üblich großgeschrieben.

Enums nutzen

Um zu verstehen, wie sich Enums nutzen lassen, ist es hilfreich zu wissen, wie sie der Compiler umsetzt. Intern erstellt der Compiler eine normale Klasse, in unserem Fall Weekday. Alle Aufzählungselemente sind dann statische Variablen (Konstanten) vom Typ des Enums:

class Weekday 
{ 
  public static final Weekday MONDAY; 
  public static final Weekday TUESDAY; 
  ... 
}

Jetzt ist es einfach, diese Werte zu nutzen, da sie wie jede andere statische Variable angesprochen werden:

Weekday weekend = Weekday.SATURDAY;

Hinter den Aufzählungen stehen also einzelne Objekte, die sich – wie alle anderen – weiterverarbeiten lassen, das heißt: etwa in eine Datenstruktur einsetzen lassen.

enum-Konstanten in switch

enum-Konstanten sind in switch-Anweisungen möglich. (Das ist möglich, da sie intern über eine Ganzzahl als Identifizierer verfügen, den der Compiler für die Aufzählung einsetzt.)

Initialisieren wir eine Variable vom Typ Weekday, und nutzen wir eine Fallunterscheidung mit der Aufzählung für einen Test auf das Wochenende:

Listing 6.26 WeekdayDemo.java, Ausschnitt main()

Weekday day = Weekday.MONDAY; 
switch ( day ) 
{ 
  case SATURDAY:               // nicht Weekday.SATURDAY! 
  case SUNDAY: System.out.println( "Wochenende. Party!" ); 
}

Standard-Methoden der Enums

Die erzeugten enum-Objekte bekommen standardmäßig eine Reihe von zusätzlichen Eigenschaften. Sie überschreiben sinnvoll toString(), hashCode() und equals() aus Object und implementieren zusätzlich Serializable und Comparable [Die Ordnung der Konstanten ist die Reihenfolge, in der sie geschrieben sind. ] , aber nicht Cloneable, da Aufzählungsobjekte nicht geklont werden können. Es liefert toString() den Name, der Konstante, sodass Weekday.SUNDAY.toString().equals("SUNDAY") wahr ist. Zusätzlich erbt jedes Aufzählungsobjekt von der Spezialklasse Enum, die später erklärt wird.

Referenzen auf Enum-Objekte können null sein

Dass die Aufzählungen nur Objekte sind, hat eine wichtige Konsequenz. Blicken wir zunächst auf eine Variablendeklaration vom Typ eines enum, die mit einem Wochentag initialisiert ist:

Weekday day = Weekday.MONDAY;

Die Variable day speichert einen Verweis auf das Weekday.MONDAY-Objekt. Das Unschöne an Referenz-Variablen ist allerdings, dass sie auch mit null belegt werden können, was so gesehen kein Element der Aufzählung ist:

Weekday day = null;

Wenn solch eine null-Referenz in einem switch landet, gibt es eine NullPointerException, da versteckt im switch ein Zugriff auf die im Enum-Objekt gespeicherte Ordinalzahl stattfindet.

Methoden, die Elemente einer Aufzählung, also Objektverweise, entgegennehmen, sollten im Allgemeinen auf null testen und eine Ausnahme auslösen, um diesen fehlerhaften Teil anzuzeigen:

public void setWeekday( Weekday day ) 
{ 
  if ( day == null ) 
    throw new IllegalArgumentException( "null is not a valid argument!" ); 
  this.day = day; 
}

Innere Aufzählungen

Es gibt »normale« Aufzählungen, die an normale Klassen erinnern, und auch »innere« Aufzählungen, die an innere Klassen erinnern. Mit anderen Worten: Weekday kann auch innerhalb einer anderen Klasse deklariert werden. Ist die innere Aufzählung öffentlich, kann sie jeder nutzen. Sie folgt aber den gleichen Sichtbarkeiten wie Klassen, da sie ja nichts anderes als Klassen sind, die der Compiler generiert.

Statische Imports von Aufzählungen

Die Aufzählung Weekday hatten wir in das Paket com.tutego.weekday gesetzt. Um auf eine Konstante wie MONDAY zugreifen zu können, wollen wir unterschiedliche import-Varianten nutzen.


Import-Anweisung Zugriff

import com.tutego.weekday.Weekday;

Weekday.MONDAY

import com.tutego.weekday.*;

Weekday.MONDAY

import static com.tutego.weekday.Weekday.*;

MONDAY


Nehmen wir im Paket als zweites Beispiel eine innere Aufzählung der Klasse Week hinzu:

package com.tutego.weekday; 
 
public class Week 
{ 
  public enum Weekday { 
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY 
  } 
}

Import-Anweisung Zugriff

import com.tutego.weekday.Week;

Week.Weekday.MONDAY

import com.tutego.weekday.Week.Weekday;

Weekday.MONDAY

import static com.tutego.weekday.Week.Weekday.*

MONDAY




Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






<< zurück



Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de