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?
<< zurück | Galileo Computing / <openbook> /Java-Insel | vor >>
Java ist auch eine Insel von Christian Ullenboom Programmieren mit der Java Standard Edition Version 6
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 |
| 6 Eigene Klassen schreiben
|  | 6.1 Eigene Klassen mit Eigenschaften deklarieren
|  |  | 6.1.1 Attribute deklarieren
|  |  | 6.1.2 Methoden deklarieren
|  |  | 6.1.3 Die this-Referenz
|  | 6.2 Privatsphäre und Sichtbarkeit
|  |  | 6.2.1 Für die Öffentlichkeit: public
|  |  | 6.2.2 Paketsichtbar
|  |  | 6.2.3 Kein Public Viewing – Passwörter sind privat
|  |  | 6.2.4 Wieso nicht freie Methoden und Variablen für alle?
|  |  | 6.2.5 Privat ist nicht ganz privat: Es kommt darauf an, wer’s sieht
|  |  | 6.2.6 Zugriffsmethoden für Attribute deklarieren
|  |  | 6.2.7 Setter und Getter nach der JavaBeans-Spezifikation
|  | 6.3 Statische Methoden und statische Attribute
|  |  | 6.3.1 Warum statische Eigenschaften sinnvoll sind
|  |  | 6.3.2 Statische Eigenschaften mit static
|  |  | 6.3.3 Statische Eigenschaften über Referenzen nutzen?
|  |  | 6.3.4 Warum die Groß- und Kleinschreibung wichtig ist
|  |  | 6.3.5 Statische Eigenschaften und Objekteigenschaften
|  |  | 6.3.6 Statische Variablen zum Datenaustausch
|  |  | 6.3.7 Statische Blöcke als Klasseninitialisierer
|  | 6.4 Konstanten und Aufzählungen
|  |  | 6.4.1 Konstanten über öffentliche statische finale Variablen
|  |  | 6.4.2 Eincompilierte Belegungen der Klassenvariablen
|  |  | 6.4.3 Typ(un)sicherere Aufzählungen
|  |  | 6.4.4 Aufzählungen mit enum
|  | 6.5 Objekte anlegen und zerstören
|  |  | 6.5.1 Konstruktoren schreiben
|  |  | 6.5.2 Der Standard-Konstruktor
|  |  | 6.5.3 Parametrisierte und überladene Konstruktoren
|  |  | 6.5.4 Konstruktor nimmt ein Objekt vom eigenen Typ an (Copy-Konstruktor)
|  |  | 6.5.5 Einen anderen Konstruktor der gleichen Klasse aufrufen
|  |  | 6.5.6 Initialisierung der Objekt- und Klassenvariablen
|  |  | 6.5.7 Finale Werte im Konstruktor und in statischen Blöcken setzen
|  |  | 6.5.8 Exemplarinitialisierer (Instanzinitialisierer)
|  |  | 6.5.9 Ihr fehlt uns nicht – der Garbage-Collector
|  |  | 6.5.10 Implizit erzeugte String-Objekte
|  |  | 6.5.11 Private Konstruktoren, Utility-Klassen, Singleton, Fabriken
|  | 6.6 Assoziationen zwischen Objekten
|  |  | 6.6.1 Unidirektionale 1:1-Beziehung
|  |  | 6.6.2 Bidirektionale 1:1-Beziehungen
|  |  | 6.6.3 Unidirektionale 1:n-Beziehung
|  | 6.7 Vererbung
|  |  | 6.7.1 Vererbung in Java
|  |  | 6.7.2 Spielobjekte modelliert
|  |  | 6.7.3 Einfach- und Mehrfachvererbung
|  |  | 6.7.4 Sichtbarkeit protected
|  |  | 6.7.5 Konstruktoren in der Vererbung und super
|  |  | 6.7.6 Automatische und explizite Typanpassung
|  |  | 6.7.7 Das Substitutionsprinzip
|  |  | 6.7.8 Typen mit dem binären Operator instanceof testen
|  |  | 6.7.9 Methoden überschreiben
|  |  | 6.7.10 Mit super an die Eltern
|  |  | 6.7.11 Kovariante Rückgabetypen
|  |  | 6.7.12 Array-Typen und Kovarianz
|  |  | 6.7.13 Zusammenfassung zur Sichtbarkeit
|  | 6.8 Dynamisches Binden
|  |  | 6.8.1 Unpolymorph bei privaten, statischen und finalen Methoden
|  |  | 6.8.2 Polymorphie bei Konstruktoraufrufen
|  |  | 6.8.3 Finale Klassen
|  |  | 6.8.4 Nicht überschreibbare (finale) Methoden
|  | 6.9 Abstrakte Klassen und abstrakte Methoden
|  |  | 6.9.1 Abstrakte Klassen
|  |  | 6.9.2 Abstrakte Methoden
|  | 6.10 Schnittstellen
|  |  | 6.10.1 Deklarieren von Schnittstellen
|  |  | 6.10.2 Implementieren von Schnittstellen
|  |  | 6.10.3 Markierungsschnittstellen
|  |  | 6.10.4 Ein Polymorphie-Beispiel mit Schnittstellen
|  |  | 6.10.5 Die Mehrfachvererbung bei Schnittstellen
|  |  | 6.10.6 Keine Kollisionsgefahr bei Mehrfachvererbung
|  |  | 6.10.7 Erweitern von Interfaces – Subinterfaces
|  |  | 6.10.8 Vererbte Konstanten bei Schnittstellen
|  |  | 6.10.9 Schnittstellenmethoden, die nicht implementiert werden müssen
|  |  | 6.10.10 Abstrakte Klassen und Schnittstellen im Vergleich
|  | 6.11 Geschachtelte (innere) Klassen, Schnittstellen, Aufzählungen
|  |  | 6.11.1 Statische innere Klassen und Schnittstellen
|  |  | 6.11.2 Mitglieds- oder Elementklassen
|  |  | 6.11.3 Lokale Klassen
|  |  | 6.11.4 Anonyme innere Klassen
|  |  | 6.11.5 this und Vererbung
|  | 6.12 Generische Datentypen
|  |  | 6.12.1 Einfache Klassenschablonen
|  |  | 6.12.2 Einfache Methodenschablonen
|  |  | 6.12.3 Umsetzen der Generics, Typlöschung und Raw-Types
|  |  | 6.12.4 Einschränken der Typen
|  |  | 6.12.5 Generics und Vererbung, Invarianz
|  |  | 6.12.6 Wildcards
|  | 6.13 Die Spezial-Oberklasse Enum
|  |  | 6.13.1 Methoden auf Enum-Objekten
|  |  | 6.13.2 enum mit eigenen Konstruktoren und Methoden
|  | 6.14 Dokumentationskommentare mit JavaDoc
|  |  | 6.14.1 Einen Dokumentationskommentar setzen
|  |  | 6.14.2 Mit javadoc eine Dokumentation erstellen
|  |  | 6.14.3 HTML-Tags in Dokumentationskommentaren
|  |  | 6.14.4 Generierte Dateien
|  |  | 6.14.5 Dokumentationskommentare im Überblick
|  |  | 6.14.6 JavaDoc und Doclets
|  |  | 6.14.7 Veraltete (deprecated) Klassen, Konstruktoren und Methoden
## 6.3 Statische Methoden und statische Attribute Exemplarvariablen sind eng mit ihrem Objekt verbunden. Wird ein Objekt geschaffen, erhält es einen eigenen Satz von Exemplarvariablen, die zusammen den Zustand des Objekts repräsentieren. Ändert eine Objektmethode den Wert einer Exemplarvariable in einem Objekt, so hat dies keine Auswirkungen auf die Daten der anderen Objekte; jedes Objekt speichert eine individuelle Belegung. Es gibt jedoch auch Situationen, in denen Eigenschaften oder Methoden nicht direkt einem individuellen Objekt zugeordnet werden. Dazu gehören zum Beispiel die Methoden: max() (etwa in Math.max(1, –2)): liefert das Maximum zweier Zahlen. sin() (etwa in Math.sin(Math.PI/2.0) ): bestimmt den Sinus. Integer.parseInt(): konvertiert einen String in eine Ganzzahl. JOptionPane.showInputDialog(): zeigt einen Eingabedialog. Color.HSBtoRGB() [Ja, die Methode beginnt unüblicherweise mit einem Großbuchstaben. ] : konvertiert Farben vom HSB-Farbraum in den RGB-Farbraum. Integer.MAX_VALUE: ist die größte darstellbare int-Ganzzahl. PI aus Math: bestimmt die Zahl 3,1415 ... Diese genannten Eigenschaften sind keinem konkreten Objekt mit seinem ureigenen Objektzustand zuzuordnen als vielmehr der Klasse. Diese Art von Zugehörigkeit wird in Java durch statische Eigenschaften unterstützt. Da sie zu keinem Objekt gehören wie Objekteigenschaften, nennen wir sie auch Klasseneigenschaften. Die Sinus-Funktion ist ein Beispiel für eine statische Methode der Mathe-Klasse, und MAX_INTEGER ist ein statisches Attribut der Klasse Integer. ### 6.3.1 Warum statische Eigenschaften sinnvoll sind Statische Eigenschaften haben gegenüber Objekteigenschaften den Vorteil, dass sie im Programm ausdrücken, keinen Zustand vom Objekt zu nutzen. Betrachten wir noch einmal Funktionen aus der Klasse Math. Wenn sie Objektmethoden wären, so würden sie in der Regel mit einem Objektzustand arbeiten. Die Funktionen hätten keine Parameter und würden ihre Arbeitswerte nicht aus den Argumenten, sondern aus dem internen Zustand des Objekts nehmen. Das macht aber keine Math-Funktion. Um den Sinus eines Winkels zu berechnen, benötigen wir kein spezifisches Mathe-Objekt. Anders herum würde eine Methode wie setName() eines Spieles nicht statisch sein können, da ganz individuell einem Spieler der Name gesetzt werden und nicht alle Spieler-Objekte immer den gleichen Namen tragen sollten. Statische Funktionen sind aus diesem Grunde häufiger als statische Variablen, da sie ihre Arbeitswerte ausschließlich aus den Parametern ziehen. Statische Variablen werden in erster Linie als Konstanten verwendet. ### 6.3.2 Statische Eigenschaften mit static Um statische Eigenschaften in Java umzusetzen, fügen wir vor der Deklaration einer Variable oder einer Methode das Schlüsselwort static hinzu. Für den Zugriff verwenden wir statt der Referenzvariablen einfach den Klassennamen. In der UML sind statische Eigenschaften unterstrichen gekennzeichnet. Deklarieren wir eine statische Funktion und eine statische Variable für eine Klasse GameUtils. Eine Funktion soll testen, ob Bezeichner, die im Spiel etwa für die Gegenstände verwendet werden, korrekt sind; ein korrekter Bezeichner ist nicht zu lang und enthält kein Sonderzeichen. Die Konstante MAX_ID_LEN steht für die maximale Bezeichnerlänge. Listing 6.17 GameUtils.java
    public class GameUtils
    {
      public static final double MAX_ID_LEN = 20 /* chars */;

      public static boolean isGameIdentifier( String name )
      {
        if ( name == null )
          return false;

        return name.length() <= MAX_ID_LEN && name.matches( "\\w+" );
      }
    }
Hier klicken, um das Bild zu vergrößern Abbildung 6.2 Statische Eigenschaften werden in der UML unterstrichen Die statischen Eigenschaften werden mit dem Klassennamen GameUtils angesprochen: Listing 6.18 GameUtilsDemo.java, Ausschnitt
    System.out.println( GameUtils.isGameIdentifier( "Superpig" ) );   // true
    System.out.println( GameUtils.isGameIdentifier( "Superpig II" ) );// false
Tipp Falls eine Klasse nur statische Eigenschaften deklariert, spricht nichts dagegen, einen privaten Konstruktor anzugeben – das verhindert den äußeren Aufbau von Objekten.
Das Kapitel »Konstruktoren schreiben« erklärt Konstruktoren genauer und auch weitere Anwendungsfälle für private Konstruktoren. Hier klicken, um das Bild zu vergrößern ### 6.3.3 Statische Eigenschaften über Referenzen nutzen? Besitzt eine Klasse eine Klasseneigenschaft, so kann sie auch wie ein Objektattribut über die Referenz angesprochen werden. Dies bedeutet, dass es prinzipiell zwei Möglichkeiten gibt, wenn ein Objektexemplar existiert und die Klasse ein statisches Attribut hat. Bleiben wir bei unserem obigen Beispiel mit der Klasse GameUtils. Wir können für den Zugriff auf MAX_ID_LEN schreiben: Listing 6.19 GameUtilsDemo.java, Ausschnitt
    System.out.println( GameUtils.MAX_ID_LEN );           // Genau richtig
    GameUtils ut = new GameUtils();
    System.out.println( ut.MAX_ID_LEN );                  // Nicht so gut
    System.out.println( ((GameUtils) null).MAX_ID_LEN );  // Auch gar nicht gut so
Die beiden unteren Anweisungen führen zum gleichen Ziel. Doch betrachten wir allein das zweite Codesegment, so ist für uns nicht sichtbar, dass MAX_ID_LEN eine statische Variable ist. Aus diesem Grund sollten wir immer statische Eigenschaften über ihren Klassennamen ansprechen; Eclipse gibt hier auch eine Meldung aus, wenn wir es nicht so machen. ### 6.3.4 Warum die Groß- und Kleinschreibung wichtig ist Die Vorgabe der Namenskonvention sagt, Klassennamen sind mit Großbuchstaben zu vergeben und Variablennamen mit Kleinbuchstaben. Treffen wir auf eine Anweisung wie Math.max(a, b), so wissen wir sofort, dass max() eine statische Methode sein muss, weil davor ein Bezeichner steht, der großgeschrieben ist. Dieser kennzeichnet also keine Referenz, sondern einen Klassennamen. Daher sollten wir in unseren Programmen großgeschriebene Objektnamen meiden. Das folgende Beispiel demonstriert gut, warum Referenzvariablen mit Kleinbuchstaben und Klassennamen mit Großbuchstaben beginnen sollten.
    String StringModifier = "What is the Matrix?";
    String t = StringModifier.trim();
Die trim()-Methode ist nicht statisch, wie die Anweisung durch die Großschreibung der Variable suggeriert. Das gleiche Problem haben wir, wenn wir Klassen mit Kleinbuchstaben benennen. Auch dies kann irritieren.
    class player
    {
      static void move() { }
    }
Jetzt könnte jemand player.move() schreiben, und der Leser würde annehmen, dass player wegen seiner Kleinschreibung eine Referenzvariable ist, und move() eine Objektmethode. Wir sehen an diesem Beispiel, dass es wichtig ist, die Groß-/Kleinschreibung zu verfolgen. ### 6.3.5 Statische Eigenschaften und Objekteigenschaften Wie wir oben gesehen haben, können wir über eine Objektreferenz auch statische Eigenschaften nutzen. Wir wollen uns aber noch einmal vergewissern, wie Objekteigenschaften und statische Eigenschaften gemischt werden können. Erinnern wir uns daran, dass unsere ersten Programme aus der main()-Methode bestanden, aber unsere anderen Methoden auch static sein mussten. Dies ist sinnvoll, da eine statische Methode – ohne explizite Angabe eines aufrufenden Objekts – nur andere statische Methoden aufrufen kann. Wie sollte auch eine statische Methode eine Objektmethode aufrufen können, wenn es kein zugehöriges Objekt gibt? Andersherum kann aber jede Objektmethode eine beliebige statische Methode direkt aufrufen. Genauso verhält es sich mit Attributen. Eine statische Methode kann keine Objektattribute nutzen, da es kein implizites Objekt gibt, auf dessen Eigenschaften zugegriffen werden könnte. #### this-Referenzen und statische Eigenschaften Auch der Einsatz der this-Referenz ist bei statischen Eigenschaften nicht möglich. Dies trifft in erster Linie statische Methoden, die eine this-Referenz verwenden wollen.
Hinweis In statischen Funktionen gibt es kein this.
    class InStaticNoThis
    {
      String name;

      static void setNameOfCurly()
      {
        name = "Jiefeng";           // Compilerfehler
        this.name = "Jiefeng";      // Compilerfehler
      }
    }
### 6.3.6 Statische Variablen zum Datenaustausch Der Wert einer statischen Variable wird bei dem Klassenobjekt gespeichert und nicht bei einem Exemplar der Klasse. Wie wir aber gesehen haben, kann jedes Exemplar einer Klasse auch auf die statischen Variablen der Klasse zugreifen. Da eine statische Variable aber nur einmal pro Klasse vorliegt, führt dies dazu, dass mehrere Objekte sich eine Variable teilen. Somit wird ein Austausch von Informationen über die Objektgrenze hinaus erlaubt. Hier klicken, um das Bild zu vergrößern Dazu ein Beispiel: Objekte tauschen über eine gemeinsame statische Variable Daten aus. Listing 6.20 ShareData.java
    class ShareData
    {
      private static int share;

      public void memorize( int i )
      {
        share = i;
      }

      public int retrieve ()
      {
        return share;
      }
      public static void main( String[] args )
      {
        ShareData s1 = new ShareData();
        ShareData s2 = new ShareData();
        s1.memorize( 2 );
        System.out.println( s2.retrieve() );    // 2
      }
    }
Doch kein Vorteil ohne Nachteil. Es kann bei nebenläufigen Zugriffen zu Problemen kommen. Deshalb müssen wir spezielle Synchronisationsmechanismen nutzen – die das Beispiel allerdings nicht verwendet. ### 6.3.7 Statische Blöcke als Klasseninitialisierer Eine Art Konstruktor für das Klassenobjekt selbst (nicht die Exemplare der Klasse) ist ein static-Block, der ein oder mehrmals in eine Klasse gesetzt werden kann. Jeder Block wird genau dann ausgeführt, wenn die Klasse vom Klassenlader in die virtuelle Maschine geladen wird. [In der Regel geschieht dies nur einmal während eines Programmlaufs. Unter gewissen Umständen – ein eigener Klassenlader für die Klasse – kann jedoch eine Klasse auch aus dem Speicher entfernt und dann mit einem anderen Klassenlader wieder neu geladen werden. Dann werden die static-Blöcke neu ausgeführt. ] Listing 6.21 StaticBlock.java
    class StaticBlock
    {
      static
      {
        System.out.println( "Eins" );
      }
      public static void main( String[] args )
      {
        System.out.println( "Jetzt geht's los." );
      }
      static
      {
        System.out.println( "Zwei" );
      }
    }
Lädt der Klassenlader die Klasse StaticBlock, so führt er zuerst den ersten Block mit der Ausgabe »Eins« aus und dann den Block mit der Ausgabe »Zwei«. Da die Klasse StaticBlock auch das main() besitzt, führt die virtuelle Maschine anschließend die Start-Funktion aus.
Beispiel Mit diesem Trick lassen sich auch Programme ohne main()-Funktion schreiben. In den statischen Block wird einfach das Hauptprogramm geschrieben. Da die virtuelle Maschine aber immer noch nach dem main() sucht, müssen wir die Laufzeitumgebung schon vorher beenden. Dies geschieht dadurch, dass mit System.exit() die Bearbeitung abgebrochen wird: Listing 6.22 StaticNowMain.java
    class StaticNowMain
    {
      static
      {
        System.out.println( "Jetzt bin ich das Hauptprogramm" );
        System.exit( 0 );
      }
    }
Nicht jede Laufzeitumgebung nimmt das jedoch ohne Murren hin. Mit diesem Vorgehen ist der Nachteil verbunden, dass bei Ausnahmen im versteckten Hauptprogramm manche virtuelle Maschinen unsinnige Fehler melden – etwa den, dass die Klasse StaticNowMain nicht gefunden wurde, oder auch eine ExceptionInInitializerError, die an Stelle einer vernünftigen Exception kommt.
### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.
Name |
E-Mail |
Ihr Kommentar |
<< zurück | <top> | vor >>

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