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 |
| 3 Klassen und Objekte
|  | 3.1 Objektorientierte Programmierung
|  |  | 3.1.1 Warum überhaupt OOP?
|  |  | 3.1.2 Wiederverwertbarkeit
|  | 3.2 Eigenschaften einer Klasse
|  |  | 3.2.1 Die Klasse Point
|  | 3.3 Die UML (Unified Modeling Language)
|  |  | 3.3.1 Hintergrund und Geschichte zur UML
|  |  | 3.3.2 Wichtige Diagrammtypen der UML
|  | 3.4 Neue Objekte erzeugen
|  |  | 3.4.1 Anlegen eines Exemplars einer Klasse mit dem new-Operator
|  |  | 3.4.2 Deklarieren von Referenzvariablen
|  |  | 3.4.3 Zugriff auf Variablen und Methoden mit dem ».«
|  |  | 3.4.4 Konstruktoren nutzen
|  |  | 3.4.5 Die API-Dokumentation
|  | 3.5 Import und Pakete
|  | 3.6 Mit Referenzen arbeiten
|  |  | 3.6.1 Die null-Referenz
|  |  | 3.6.2 Zuweisungen bei Referenzen
|  |  | 3.6.3 Funktionen mit nicht-primitiven Parametern
|  | 3.7 Identität und Gleichheit
|  |  | 3.7.1 Identität von Objekten
|  |  | 3.7.2 Gleichheit und die Methode equals()
|  | 3.8 Wrapper-Klassen und Autoboxing
|  |  | 3.8.1 Die Basisklasse Number für numerische Wrapper-Objekte
|  |  | 3.8.2 Die Klasse Integer
|  |  | 3.8.3 Unterschiedliche Ausgabeformate
|  |  | 3.8.4 Autoboxing: Boxing und Unboxing
|  |  | 3.8.5 Die Boolean-Klasse
|  |  | 3.8.6 Die Klassen Double und Float für Fließkommazahlen
|  | 3.9 Arrays
|  |  | 3.9.1 Deklaration von Arrays
|  |  | 3.9.2 Arrays mit Inhalt
|  |  | 3.9.3 Die Länge eines Arrays über das Attribut length
|  |  | 3.9.4 Zugriff auf die Elemente über den Index
|  |  | 3.9.5 Array-Objekte erzeugen
|  |  | 3.9.6 Fehler bei Arrays
|  |  | 3.9.7 Vorinitialisierte Arrays
|  |  | 3.9.8 Die erweiterte for-Schleife
|  |  | 3.9.9 Arrays mit nicht-primitiven Elementen
|  |  | 3.9.10 Mehrdimensionale Arrays
|  |  | 3.9.11 Die Wahrheit über die Array-Initialisierung
|  |  | 3.9.12 Mehrere Rückgabewerte
|  |  | 3.9.13 Methode mit variabler Argumentanzahl (Vararg)
|  |  | 3.9.14 Klonen kann sich lohnen – Arrays vermehren
|  |  | 3.9.15 Feldinhalte kopieren
|  |  | 3.9.16 Die Klasse Arrays zum Vergleichen, Füllen und Suchen
|  | 3.10 Der Einstiegspunkt für das Laufzeitsystem main()
|  |  | 3.10.1 Kommandozeilen-Argumente verarbeiten
|  |  | 3.10.2 Der Rückgabewert von main() und System.exit()
|  | 3.11 Eigene Pakete schnüren
|  |  | 3.11.1 Die package-Anweisung
|  |  | 3.11.2 Importieren von Klassen mit import
|  |  | 3.11.3 Hierarchische Strukturen und das Default-Package
|  |  | 3.11.4 Paketnamen
|  |  | 3.11.5 Klassen mit gleichen Namen in unterschiedlichen Paketen
|  |  | 3.11.6 Statisches Import
|  |  | 3.11.7 Eine Verzeichnisstruktur für eigene Projekte
|  | 3.12 Zum Weiterlesen
## 3.8 Wrapper-Klassen und Autoboxing Wrapper-Klassen (auch »Ummantelungsklasse«, »Mantelsklasse« oder »Envelope Class« genannt) haben in der Java-Welt zwei wichtige Aufgaben: Die Datenstrukturen, die in Java Verwendung finden, können nur Objekte aufnehmen. So stellt sich das Problem, wie primitive Datentypen diesen Containern hinzugefügt werden können. Die Klassenbibliothek bietet daher für jeden primitiven Datentyp eine entsprechende Wrapper-Klasse an. Exemplare dieser Klassen kapseln je einen Wert des zugehörigen primitiven Typs. Zusätzlich zu dieser Eigenschaft bieten die Wrapper-Klassen Funktionen zum Zugriff auf den Wert und einige Umwandlungsfunktionen. Es existieren Wrapper-Klassen zu allen primitiven Datentypen.
Tabelle 3.1 Wrapper-Klassen und primitive Datentypen
Wrapper-Klasse | Primitiver Typ
Byte | byte
Short | short
Integer | int
Long | long
Double | double
Float | float
Boolean | boolean
Character | char
Für void, was kein Datentyp ist, existiert die Klasse Void. Sie deklariert nur die Konstante TYPE vom Typ Class<Void> und ist für Reflection (das Auslesen von Eigenschaften einer Klasse) interessanter. #### Erzeugen von Wrapper-Objekten Wrapper-Objekte lassen sich auf drei Arten aufbauen: Über Konstruktoren der Wrapper-Klassen. Über statische valueOf()-Methoden, denen ein primitiver Ausdruck oder ein String übergeben wird. Über Boxing: Aus einem primitiven Wert erstellt der Compiler mithilfe der valueOf()-Methoden das Wrapper-Object.
Beispiel Erzeuge einige Wrapper-Objekte:
    Integer i1 = new Integer( 29 );
    Integer i2 = Integer.valueOf( 30 );
    Long    lo = new Long( 0xC0B0L );
    Double  db = new Double( 12.3 );
    Boolean bl = true;
#### Wrapper-Objekte sind immutable Ist ein Wrapper-Objekt erst einmal erzeugt, kann der Wert nachträglich nicht mehr verändert werden. Um dies auch wirklich sicherzustellen, sind die konkreten Wrapper-Klassen allesamt final. Die Wrapper-Klassen sind nur als Ummantelung und nicht als vollständiger Datentyp gedacht. Da sich der Wert nicht mehr ändern lässt, heißen Objekte mit dieser Eigenschaft auch Werte-Objekte. Wollen wir den Inhalt eines Integer-Objekts io um eins erhöhen, so müssen wir Folgendes schreiben:
    int i = 12;
    Integer io = new Integer( i );
    io = new Integer( io.intValue() + 1 );
    i = io.intValue();
#### Konvertierungen in einen String Alle Wrapper-Objekte überschreiben die Objektmethode toString() aus java.lang.Object so, dass sie eine String-Repräsentation zurückgeben. Verwirrend mag sein, dass es neben der überschriebenen Objektmethode auch statische toString()-Funktionen mit Parameter gibt. Während aber die statische Methode den Arbeitswert zur Konvertierung aus dem Argument zieht, nutzt die Objektmethode den gespeicherten Wert im Wrapper-Objekt.
    int          number = 12345;
    String stringNumber = Integer.toString( number );   // 12345
Tipp Ein Java-Idiom zur Konvertierung ist auch folgende Anweisung:
    String s = "" + number;
Anweisungen, die ausschließlich zum Konvertieren über das Wrapper-Objekt gehen, wie new Integer(v).toString(), lassen sich problemlos umschreiben in Integer.toString(v). Zudem bietet sich auch die überladene statische Funktion String.valueOf(v) an, die auf alle möglichen Datentypen definiert ist. (Doch nutzt valueOf(v) intern auch nur WrapperKlasse.toString(v).)
Hinweis Bei der Darstellung von Zahlen ist eine landestypische (länderspezifische) Formatierung sinnvoll. Dafür bietet die Klasse java.text.NumberFormat eine Methode format(double) und format(int).
    System.out.println( NumberFormat.getInstance().format( 10000000 )); // 10.000.000
    System.out.println( NumberFormat.getInstance().format( 1234.567 )); // 1.234,567
### 3.8.1 Die Basisklasse Number für numerische Wrapper-Objekte Alle numerischen Wrapper-Klassen können den gespeicherten Wert in einem beliebigen anderen numerischen Typ liefern. Die Methodennamen setzen sich – wie zum Beispiel doubleValue() – aus den Namen des Basistyps und »Value« zusammen. Technisch gesehen überschreiben die Wrapper-Klassen Byte, Short, Integer, Long, Float und Double aus einer Klasse Number [Zusätzlich erweitern BigDecimal und BigInteger die Klasse Number und haben damit ebenfalls die xxxValue()-Methoden. In Java 5 kommen AtomicInteger und AtomicLong hinzu, die aber nicht immutable sind wie die anderen Klassen. ] die xxxValue()-Methoden [Nur die Methoden byteValue() und shortValue() sind nicht abstrakt und müssen nicht überschrieben werden. Diese Methoden rufen intValue() auf und konvertieren den Wert über eine Typanpassung auf byte und short. ] .
    abstract class java.lang.Number
    implements Serializable
byte byteValue() Liefert den Wert der Zahl als byte. abstract double doubleValue() Liefert den Wert der Zahl als double. abstract float floatValue() Liefert den Wert der Zahl als float. abstract int intValue() Liefert den Wert der Zahl als int. abstract long longValue() Liefert den Wert der Zahl als long. short shortValue() Liefert den Wert der Zahl als short. Hier klicken, um das Bild zu vergrößern ### 3.8.2 Die Klasse Integer Die Klasse Integer kapselt den Wert einer Ganzzahl vom Typ int in einem Objekt. Hier klicken, um das Bild zu vergrößern #### String in eine Ganzzahl umwandeln Um aus dem String eine Zahl zu machen, nutzen wir Integer.parseInt(), wie schon im String-Kapitel 4 beschrieben. Eine spezialisierte Methode für eine gegebene Basis ist parse Int(String, int radix). Diese ist gut für Hexadezimalzahlen mit der Basis 16. Einige Anwendungsfälle:
Tabelle 3.2 Beispiele für Integer.parseInt() mit unterschiedlichen Zahlenbasen
Konvertieraufruf | Ergebnis
parseInt("0",10) | 0
parseInt("473",10) | 473
parseInt("-0",10) | 0
parseInt("-FF",16) | –255
parseInt("1100110",2) | 102
parseInt("2147483647",10) | 2147483647
parseInt("-2147483648",10) | –2147483648
parseInt("2147483648",10) | throws NumberFormatException
parseInt("99",8) | throws NumberFormatException
parseInt("Papa",10) | throws NumberFormatException
parseInt("Papa",27) | 500050
    final class java.lang.Integer
    extends Number
    implements Comparable<Integer>
static int parseInt( String s ) Erzeugt aus der Zeichenkette die entsprechende Zahl. Die Basis ist 10. static int parseInt( String s, int radix ) Erzeugt die Zahl mit der gegebenen Basis. parseInt() nutzt länderspezifische Tausendertrennzeichen nicht. ### 3.8.3 Unterschiedliche Ausgabeformate Neben der toString()-Methode, die eine Zahl als String-Repräsentation im vertrauten Dezimalsystem ausgibt, gibt es vier weitere Varianten für die binäre, hexadezimale und oktale Darstellung sowie für die Darstellung einer beliebigen Basis. Die Methoden sind allerdings nicht in der Oberklasse Number deklariert, da nur die Klassen Integer und Long die Methoden implementieren. Alle folgenden Ausgabemethoden sind statisch.
    final class Long | Integer
    extends Number
    implements Comparable<Long> | Comparable<Integer>, Serializable
static String toBinaryString( int | long i ) Erzeugt eine Binärrepräsentation (Basis 2) der vorzeichenlosen Zahl. static String toOctalString( int | long i ) Erzeugt eine Oktalzahlrepräsentation (Basis 8) der vorzeichenlosen Zahl. static String toHexString( int | long i ) Erzeugt eine Hexadezimalrepräsentation (Basis 16) der vorzeichenlosen Zahl. static String toString( int | long i, int radix ) Erzeugt eine String-Repräsentation der Zahl zur angegebenen Basis. Wir dürfen nicht vergessen, dass das Format der Übergabe int beziehungsweise long ist und nicht byte. Dies führt zu Ausgaben, die einkalkuliert werden müssen. Genauso werden führende Nullen grundsätzlich nicht mit ausgegeben. Listing 3.5 ToHex.java, main()
    System.out.println( "15=" + Integer.toHexString(15) );   // 15=f
    System.out.println( "16=" + Integer.toHexString(16) );   // 16=10
    System.out.println( "127=" + Integer.toHexString(127) ); // 127=7f
    System.out.println( "128=" + Integer.toHexString(128) ); // 128=80
    System.out.println( "255=" + Integer.toHexString(255) ); // 255=ff
    System.out.println( "256=" + Integer.toHexString(256) ); // 256=100
    System.out.println( "-1=" + Integer.toHexString(-1) );   // –1=ffffffff
### 3.8.4 Autoboxing: Boxing und Unboxing Neu seit Java 5 ist das Autoboxing. [Das dürfte dann die erste Spracheigenschaft sein, die Java von C# übernimmt. Sonst hat C# ja fast alles von Java übernommen. ] Dies bedeutet, dass primitive Datentypen und Wrapper-Objekte bei Bedarf ineinander umgewandelt werden. Ein Beispiel:
    int i     = 4711;
    Integer j = i;               // steht für  j = Integer.valueOf(i)    (1)
    int k     = j;               // steht für  k = j.intValue()          (2)
Die Anweisung in (1) nennt sich Boxing und erstellt automatisch ein Wrapper-Objekt, sofern erforderlich. Schreibweise (2) ist das Unboxing und steht für das Beziehen des Elements aus dem Wrapper-Objekt. Das bedeutet: Überall dort, wo der Compiler ein primitives Element erwartet, aber ein Wrapper-Objekt vorhanden ist, entnimmt er den Wert mit einer passenden xxxValue()-Methode aus dem Wrapper. #### Operatoren ++, -- Der Compiler konvertiert nach festen Regeln, und auch die Operatoren ++, -- sind erlaubt.
    Integer i = 12;
    i = i + 1;                   // (1)
    i++;                         // (2)
    System.out.println( i );     // 14
Wichtig ist, dass weder (1) noch (2) das Original-Integer-Objekt mit der 12 ändern, sondern nur neue Objekte für 13 und 14 nutzen. #### Boxing für dynamische Datenstrukturen (Ausblick) Am angenehmsten ist die Schreibweise dann, wenn etwa in Datenstrukturen primitive Elemente abgelegt werden sollen.
    List list = new ArrayList();
    list.add( Math.sin(Math.PI / 4) );
Allerdings warnt der Compiler hier; er wünscht sich eine typisierte Liste, also
    List<Double> list = new ArrayList<Double>();
Leider ist es so, dass der Typ der Liste tatsächlich mit dem Wrapper-Typ Double festgelegt werden muss und nicht mit dem Primitivtyp double. Aber vielleicht ändert sich das ja noch irgendwann ... #### Mehr Probleme als Lösungen? Mit dem Autoboxing ist eine Reihe von Unregelmäßigkeiten verbunden, die der Programmierer beachten muss, um Fehler zu vermeiden. Eine davon hängt mit dem Unboxing zusammen, das der Compiler immer dann vornimmt, wenn ein Ausdruck einen primitiven Wert erwartet. Wenn kein primitives Element erwartet wird, wird auch kein Unboxing vorgenommen. Listing 3.6 com/tutego/insel/lang/Autoboxing.java, main() Teil 1
    Integer i1 = new Integer( 1 );
    Integer i2 = new Integer( 1 );

    System.out.println( i1 >= i2 );   // true
    System.out.println( i1 <= i2 );   // true
    System.out.println( i1 == i2 );   // false
Der Vergleich mit == ist weiterhin ein Referenzvergleich, und es findet kein Unboxing auf primitive Werte statt, sodass es auf einen Vergleich von primitiven Werten hinausliefe. Daher muss bei zwei unterschiedlichen Integer-Objekten dieser Vergleich immer falsch sein. Das ist natürlich problematisch, da die alte mathematische Regel »aus i <= j und i >= j folgt automatisch i == j« nicht mehr gilt. Wenn es die unterschiedlichen Integer-Objekte für gleiche Werte nicht gäbe, bestünde auch das Problem nicht. Die Probleme hören aber damit nicht auf. Sun hat versucht, das Problem mit dem == damit zu lösen, dass über Boxing gebildete Integer-Objekte einem Pool entstammen. Da jedoch nicht beliebig viele Objekte aus einem Pool kommen können, gilt die Gleichheit der über Boxing gebildeten Objekte nur in einem ausgewählten Wertebereich zwischen –128 und +127, also dem Wertebereich eines Bytes. Listing 3.7 com/tutego/insel/lang/Autoboxing.java, main() Teil 2
    Integer j1 = 2;
    Integer j2 = 2;
    System.out.println( j1 == j2 );   // true
    Integer k1 = 127;
    Integer k2 = 127;
    System.out.println( k1 == k2 );   // true
    Integer l1 = 128;
    Integer l2 = 128;
    System.out.println( l1 == l2 );   // false
    Integer m1 = 1000;
    Integer m2 = 1000;
    System.out.println( m1 == m2 );   // false
Wir betonten bereits, dass auch bei Wrapper-Objekten der Vergleich mit == immer ein Referenz-Vergleich ist. Da 2 und 127 im Wertebereich zwischen –128 und +127 liegen, entstammen die entsprechenden Integer-Objekte dem Pool. Das gilt für 128 und 1000 nicht; sie sind immer neue Objekte. Damit ergibt auch der ==-Vergleich false. Es ist interessant zu wissen, was nun genau passiert, wenn Boxing eine Zahl in ein Wrapper-Objekt umwandelt. In diesem Moment wird nicht der Konstruktor aufgerufen, sondern die statische valueOf()-Funktion. Sie kümmert sich auch um das Pooling. Listing 3.8 com/tutego/insel/lang/Autoboxing.java, main() Teil 3
    Integer n1 = new Integer( 10 );
    Integer n2 = Integer.valueOf( 10 );
    Integer n3 = 10;
    Integer n4 = 10;
    System.out.println( n1 == n2 );   // false
    System.out.println( n2 == n3 );   // true
    System.out.println( n1 == n3 );   // false
    System.out.println( n3 == n4 );   // true
Abschlussfrage Welche Ausgabe kommt auf den Bildschirm? Ändert sich etwas, wenn i und j auf 1111 stehen?
    Integer i = 1, j = 1;
    boolean b = (i <= j && j <= i && i != j);
    System.out.println( b );
#### Keine Konvertierung null zu 0 Beim Unboxing führt der Compiler bzw. die Laufzeitumgebung keine Konvertierung von null auf 0 durch. Mit anderen Worten: Bei der folgenden versuchten Zuweisung gibt es keinen Compilerfehler, aber zur Laufzeit eine NullPointerException.
    int n = (Integer) null;            // java.lang.NullPointerException zur Laufzeit
### 3.8.5 Die Boolean-Klasse Die Klasse Boolean kapselt den Datentyp boolean. Sie deklariert als Konstanten zwei Boolean-Objekte TRUE und FALSE für die Literale true und false. Hier klicken, um das Bild zu vergrößern
    final class java.lang.Boolean
    implements Serializable, Comparable<Boolean>
Boolean( boolean value ) Boolean( String s ) Erzeugt ein neues Boolean-Objekt. static final Boolean FALSE static final Boolean TRUE Konstanten für Wahrheitswerte. static Boolean valueOf( String str ) Parst den String und gibt Boolean.TRUE oder Boolean.FALSE zurück. Die Methode hat gegenüber dem Konstruktor Boolean(boolean) den Vorteil, dass sie immer das gleiche Wahr- oder Falsch-Objekt (Boolean.TRUE oder Boolean.FALSE) zurückgibt, anstatt neue Objekte zu erzeugen. Daher ist es selten nötig, den Konstruktor aufzurufen und immer neue Boolean-Objekte aufzubauen. public static boolean parseBoolean( String s ) Parst den String und liefert entweder true oder false. Der Konstruktor beziehungsweise valueOf() und parseBoolean() nehmen Strings entgegen, wobei die Groß-/Kleinschreibung unwichtig ist. Die Zeichenfolge muss nur entweder »true« oder »false« sein. So ergibt auch »tRuE« ein Boolean-Objekt mit dem Inhalt true. ### 3.8.6 Die Klassen Double und Float für Fließkommazahlen Die Klassen Double und Float haben wie die anderen Wrapper-Klassen eine Doppelfunktionalität. Sie kapseln zum einen eine Fließkommazahl als Objekt und bieten statische Utility-Funktionen. Wir kommen im Kapitel 5 noch genauer auf die Funktionen zurück. Hier klicken, um das Bild zu vergrößern ### 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