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 Generics, innere Klassen
10 Die Klassenbibliothek
11 Threads und nebenläufige Programmierung
12 Datenstrukturen und Algorithmen
13 Raum und Zeit
14 Dateien und Datenströme
15 Die eXtensible Markup Language (XML)
16 Grafische Oberflächen mit Swing
17 Grafikprogrammierung
18 Netzwerkprogrammierung
19 Verteilte Programmierung mit RMI und Web–Services
20 JavaServer Pages und Servlets
21 Applets
22 Midlets und die Java ME
23 Datenbankmanagement mit JDBC
24 Reflection und Annotationen
25 Logging und Monitoring
26 Sicherheitskonzepte
27 Java Native Interface (JNI)
28 Dienstprogramme für die Java-Umgebung
Stichwort

Download:
- ZIP, ca. 14,1 MB
Buch bestellen
Ihre Meinung?

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

Java ist auch eine Insel (8. Aufl.)
8., aktual. Auflage, geb., mit DVD
1.475 S., 49,90 Euro
Galileo Computing
ISBN 978-3-8362-1371-4
Pfeil 3 Klassen und Objekte
Pfeil 3.1 Objektorientierte Programmierung
Pfeil 3.1.1 Warum überhaupt OOP?
Pfeil 3.1.2 Denk ich an Java, denk ich an Wiederverwendbarkeit
Pfeil 3.2 Eigenschaften einer Klasse
Pfeil 3.2.1 Die Klasse Point
Pfeil 3.3 Die UML (Unified Modeling Language)
Pfeil 3.3.1 Hintergrund und Geschichte zur UML
Pfeil 3.3.2 Wichtige Diagrammtypen der UML
Pfeil 3.3.3 UML-Werkzeuge
Pfeil 3.4 Neue Objekte erzeugen
Pfeil 3.4.1 Anlegen eines Exemplars einer Klasse mit dem new-Operator
Pfeil 3.4.2 Deklarieren von Referenzvariablen
Pfeil 3.4.3 Zugriff auf Variablen und Methoden mit dem ».«
Pfeil 3.4.4 Konstruktoren nutzen
Pfeil 3.5 Pakete und import-Deklarationen nutzen
Pfeil 3.5.1 Volle Qualifizierung und import-Deklaration
Pfeil 3.5.2 import *
Pfeil 3.6 Mit Referenzen arbeiten
Pfeil 3.6.1 Zuweisungen bei Referenzen
Pfeil 3.6.2 Methoden mit nicht-primitiven Parametern
Pfeil 3.7 Identität und Gleichheit
Pfeil 3.7.1 Identität von Objekten
Pfeil 3.7.2 Gleichheit und die Methode equals()
Pfeil 3.7.3 Die null-Referenz
Pfeil 3.8 Wrapper-Klassen und Autoboxing
Pfeil 3.8.1 Erzeugen von Wrapper-Objekten
Pfeil 3.8.2 Konvertierungen in eine String-Repräsentation
Pfeil 3.8.3 Die Klasse Integer
Pfeil 3.8.4 Die Klassen Double und Float für Fließkommazahlen
Pfeil 3.8.5 Die Basisklasse Number für numerische Wrapper-Objekte
Pfeil 3.8.6 Die Boolean-Klasse
Pfeil 3.8.7 Autoboxing: Boxing und Unboxing
Pfeil 3.9 Compilationseinheiten und eigene Pakete schnüren
Pfeil 3.9.1 Die package-Anweisung
Pfeil 3.9.2 Importieren von Klassen mit import
Pfeil 3.9.3 Hierarchische Strukturen und das Default-Package
Pfeil 3.9.4 Paketnamen
Pfeil 3.9.5 Klassen mit gleichen Namen in unterschiedlichen Paketen
Pfeil 3.9.6 Compilationseinheit (Compilation Unit)
Pfeil 3.9.7 Statischer Import
Pfeil 3.9.8 Eine Verzeichnisstruktur für eigene Projekte
Pfeil 3.10 Arrays
Pfeil 3.10.1 Deklaration von Arrays
Pfeil 3.10.2 Arrays mit Inhalt
Pfeil 3.10.3 Die Länge eines Arrays über das Attribut length
Pfeil 3.10.4 Zugriff auf die Elemente über den Index
Pfeil 3.10.5 Array-Objekte mit new erzeugen
Pfeil 3.10.6 Fehler bei Arrays
Pfeil 3.10.7 Die erweiterte for-Schleife
Pfeil 3.10.8 Arrays mit nicht-primitiven Elementen
Pfeil 3.10.9 Mehrdimensionale Arrays
Pfeil 3.10.10 Vorinitialisierte Arrays
Pfeil 3.10.11 Mehrere Rückgabewerte
Pfeil 3.10.12 Methode mit variabler Argumentanzahl (Vararg)
Pfeil 3.10.13 Klonen kann sich lohnen – Arrays vermehren
Pfeil 3.10.14 Feldinhalte kopieren
Pfeil 3.10.15 Die Klasse Arrays zum Vergleichen, Füllen und Suchen
Pfeil 3.11 Der Einstiegspunkt für das Laufzeitsystem: main()
Pfeil 3.11.1 Kommandozeilen-Argumente verarbeiten
Pfeil 3.11.2 Der Rückgabewert von main() und System.exit()
Pfeil 3.12 Zum Weiterlesen


Galileo Computing - Zum Seitenanfang

3.8 Wrapper-Klassen und Autoboxing Zur nächsten ÜberschriftZur vorigen Überschrift

Die Klassenbibliothek bietet für jeden primitiven Datentyp spezielle Klassen an. Diese so genannten Wrapper-Klassen (auch »Ummantelungsklasse«, »Mantelklasse« oder »Envelope Class« genannt) haben zwei wichtige Aufgaben:

  • Wrapper-Klassen ermöglichen über statische Funktionen die Konvertierung eines primitiven Datentyps in einen String (Formatierung) und vom String zurück in einen primitiven Datentyp (Parsen).
  • 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. Wrapper-Objekte kapseln einen einfachen primitiven Wert in einem Objekt.

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, das 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.

Im Folgenden sollen zunächst grundlegende Eigenschaften der Wrapper-Klassen vorgestellt werden. Detailliertere Beschreibungen zu den Funktionen etwa der numerischen Klassen gibt es im Mathe-Kapitel 5. Der Klasse Character werden wir uns am Anfang von Kapitel 4 widmen, wenn es um Zeichen und Zeichenketten geht.


Galileo Computing - Zum Seitenanfang

3.8.1 Erzeugen von Wrapper-Objekten Zur nächsten ÜberschriftZur vorigen Überschrift

Wrapper-Objekte lassen sich auf drei Arten aufbauen:

  • über Konstruktoren der Wrapper-Klassen
  • über statische valueOf()-Funktionen, denen ein primitiver Ausdruck oder ein String übergeben wird
  • über Boxing: Aus einem primitiven Wert erstellt der Compiler mit Hilfe der valueOf()-Funktionen automatisch das Wrapper-Object.

Beispiel Erzeuge einige Wrapper-Objekte:

Integer int1 = new Integer( 29 );        // Constructor 
Long    lng1 = new Long( 0xC0B0L );      // Constructor 
Double  dobl = new Double( 12.3 );       // Constructor 
Integer int2 = Integer.valueOf( 30 );    // valueOf() 
Long    lng2 = Long.valueOf( 0xC0B0L );  // valueOf() 
Boolean bool = true;                     // Boxing 
int     int3 = 42;                       // Boxing

Wrapper-Objekte sind immutable

Ist ein Wrapper-Objekt erst einmal erzeugt, lässt sich der im Wrapper-Objekt gespeicherte Wert nachträglich nicht mehr verändern. 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 (er ist immutable), heißen Objekte mit dieser Eigenschaft auch Werte-Objekte. Wollen wir den Inhalt eines Integer-Objekts io zum Beispiel um eins erhöhen, so müssen wir ein neues Objekt aufbauen:

int i = 12; 
Integer io = Integer.valueOf( i ); 
io = Integer.valueOf( io.intValue() + 1 ); 
i = io.intValue();

Die Variable io referenziert nun ein zweites Integer-Objekt, und der Wert vom ersten io-Objekt mit 12 bleibt unangetastet.


Galileo Computing - Zum Seitenanfang

3.8.2 Konvertierungen in eine String-Repräsentation Zur nächsten ÜberschriftZur vorigen Überschrift

Einige Wrapper-Klassen bieten statische toString(value)-Methoden zur Konvertierung des primitiven Elements in einen String an:

Listing 3.6 WrapperToString.java, main()

String s1 = Integer.toString( 1234567891 ), 
       s2 = Long.toString( 123456789123L ), 
       s3 = Float.toString( 12.345678912f ), 
       s4 = Double.toString( 12.345678912 ), 
       s5 = Boolean.toString( true ); 
System.out.println( s1 );  // 1234567891 
System.out.println( s2 );  // 123456789123 
System.out.println( s3 );  // 12.345679 
System.out.println( s4 );  // 12.345678912 
System.out.println( s5 );  // true

Der String erscheint immer in der englisch geschriebenen Variante. So steht bei den Dezimalzahlen ein Punkt statt des uns vertrauten Kommas.

Weiterhin überschreiben alle Klassen die Objektmethode toString() aus java.lang.Object so, dass sie eine String-Repräsentation zurückgeben. Dass es gleichlautende statische Methoden toString() und eine Objektmethode toString() gibt, sollte uns nicht verwirren; während die Klassenmethode den Arbeitswert zur Konvertierung aus dem Argument zieht, nutzt die Objektmethode den gespeicherten Wert im Wrapper-Objekt.


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).)


Galileo Computing - Zum Seitenanfang

3.8.3 Die Klasse Integer Zur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse Integer kapselt den Wert einer Ganzzahl vom Typ int in einem Objekt und bietet Konstanten, statische Methoden zur Konvertierung in einen String und zurück sowie weitere Hilfsfunktionen mathematischer Natur an.

Um aus dem String eine Zahl zu machen, nutzen wir Integer.parseInt(String).


Beispiel Konvertiere die Zahl 12.345, die als String vorliegt, in eine Ganzzahl:

String number = "12345"; 
int integer = 0; 
try 
{ 
  integer = Integer.parseInt( number ); 
} 
catch ( NumberFormatException e ) { 
  System.err.println( "Fehler beim Konvertieren" ); 
}

Die NumberFormatException ist eine nicht-geprüfte Exception – mehr zu Ausnahmen in Kapitel 8, »Exceptions« –, muss also nicht zwingend in einem try-catch-Block stehen.



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() erlaubt keine länderspezifischen Tausendertrennzeichen – in Deutschland den Punkt.


Galileo Computing - Zum Seitenanfang

3.8.4 Die Klassen Double und Float für Fließkommazahlen Zur nächsten ÜberschriftZur vorigen Überschrift

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, »Mathematisches«, noch genauer auf die Objekt- und Klassenmethoden zurück.


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


Galileo Computing - Zum Seitenanfang

3.8.5 Die Basisklasse Number für numerische Wrapper-Objekte Zur nächsten ÜberschriftZur vorigen Überschrift

Alle numerischen Wrapper-Klassen können den gespeicherten Wert in einem beliebigen anderen numerischen Typ liefern. Die Methodennamen setzen sich – wie zum Beispiel doubleValue() und intValue() – aus dem Namen des gewünschten Typs 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.

Galileo Computing - Zum Seitenanfang

3.8.6 Die Boolean-Klasse Zur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse Boolean kapselt den Datentyp boolean. Sie deklariert als Konstanten zwei Boolean-Objekte, TRUE und FALSE.


final class java.lang.Boolean 
implements Serializable, Comparable<Boolean>

  • static final Boolean FALSE, static final Boolean TRUE
    Konstanten für Wahrheitswerte.
  • Boolean( boolean value )
  • Boolean( String s )
    Erzeugt ein neues Boolean-Objekt.
  • static Boolean valueOf( String str )
    Parst den String und gibt Boolean.TRUE oder Boolean.FALSE zurück. Die Funktion 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.


Galileo Computing - Zum Seitenanfang

3.8.7 Autoboxing: Boxing und Unboxing topZur vorigen Überschrift

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 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 (alle Wrapper-Objekte sind immuntable), sondern i nur andere Integer-Objekte für 13 und 14 referenziert.

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.7 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.8 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 1.000 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.9 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 1.111 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


Ihr Kommentar

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






<< zurück
  Zum Katalog
Zum Katalog: Java ist auch eine Insel





Java ist auch eine Insel
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Tipp
Zum Katalog: Coding for Fun





 Coding for Fun


 Buchempfehlungen
Zum Katalog: Objektorientierte Programmierung





 Objektorientierte
 Programmierung


Zum Katalog: Einstieg in Eclipse 3.4






 Einstieg in
 Eclipse 3.4


Zum Katalog: Java 6 lernen mit Eclipse






 Java 6 lernen
 mit Eclipse


Zum Katalog: NetBeans Platform 6






 NetBeans
 Platform 6


Zum Katalog: Java und XML






 Java und XML


Zum Katalog: Visual C# 2008






 Visual C# 2008


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: C++ von A bis Z






 C++ von A bis Z


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2009
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