Rheinwerk Computing < openbook >


 
Inhaltsverzeichnis
Materialien
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Arrays und ihre Anwendungen
5 Der Umgang mit Zeichenketten
6 Eigene Klassen schreiben
7 Objektorientierte Beziehungsfragen
8 Ausnahmen müssen sein
9 Geschachtelte Typen
10 Besondere Typen der Java SE
11 Generics<T>
12 Lambda-Ausdrücke und funktionale Programmierung
13 Architektur, Design und angewandte Objektorientierung
14 Java Platform Module System
15 Die Klassenbibliothek
16 Einführung in die nebenläufige Programmierung
17 Einführung in Datenstrukturen und Algorithmen
18 Einführung in grafische Oberflächen
19 Einführung in Dateien und Datenströme
20 Einführung ins Datenbankmanagement mit JDBC
21 Bits und Bytes, Mathematisches und Geld
22 Testen mit JUnit
23 Die Werkzeuge des JDK
A Java SE-Module und Paketübersicht
Stichwortverzeichnis


Download:

- Listings, ca. 2,7 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil5 Der Umgang mit Zeichenketten
Pfeil5.1 Von ASCII über ISO-8859-1 zu Unicode
Pfeil5.1.1 ASCII
Pfeil5.1.2 ISO/IEC 8859-1
Pfeil5.1.3 Unicode
Pfeil5.1.4 Unicode-Zeichenkodierung
Pfeil5.1.5 Escape-Sequenzen/Fluchtsymbole
Pfeil5.1.6 Schreibweise für Unicode-Zeichen und Unicode-Escapes
Pfeil5.1.7 Java-Versionen gehen mit dem Unicode-Standard Hand in Hand *
Pfeil5.2 Datentypen für Zeichen und Zeichenfolgen
Pfeil5.3 Die Character-Klasse
Pfeil5.3.1 Ist das so?
Pfeil5.3.2 Zeichen in Großbuchstaben/Kleinbuchstaben konvertieren
Pfeil5.3.3 Vom Zeichen zum String
Pfeil5.3.4 Von char in int: vom Zeichen zur Zahl *
Pfeil5.4 Zeichenfolgen
Pfeil5.5 Die Klasse String und ihre Methoden
Pfeil5.5.1 String-Literale als String-Objekte für konstante Zeichenketten
Pfeil5.5.2 Konkatenation mit +
Pfeil5.5.3 String-Länge und Test auf Leer-String
Pfeil5.5.4 Zugriff auf ein bestimmtes Zeichen mit charAt(int)
Pfeil5.5.5 Nach enthaltenen Zeichen und Zeichenfolgen suchen
Pfeil5.5.6 Das Hangman-Spiel
Pfeil5.5.7 Gut, dass wir verglichen haben
Pfeil5.5.8 String-Teile extrahieren
Pfeil5.5.9 Strings anhängen, zusammenfügen, Groß-/Kleinschreibung und Weißraum
Pfeil5.5.10 Gesucht, gefunden, ersetzt
Pfeil5.5.11 String-Objekte mit Konstruktoren und aus Wiederholungen erzeugen *
Pfeil5.6 Veränderbare Zeichenketten mit StringBuilder und StringBuffer
Pfeil5.6.1 Anlegen von StringBuilder-Objekten
Pfeil5.6.2 StringBuilder in andere Zeichenkettenformate konvertieren
Pfeil5.6.3 Zeichen(folgen) erfragen
Pfeil5.6.4 Daten anhängen
Pfeil5.6.5 Zeichen(folgen) setzen, löschen und umdrehen
Pfeil5.6.6 Länge und Kapazität eines StringBuilder-Objekts *
Pfeil5.6.7 Vergleich von StringBuilder-Exemplaren und Strings mit StringBuilder
Pfeil5.6.8 hashCode() bei StringBuilder *
Pfeil5.7 CharSequence als Basistyp
Pfeil5.8 Konvertieren zwischen Primitiven und Strings
Pfeil5.8.1 Unterschiedliche Typen in String-Repräsentationen konvertieren
Pfeil5.8.2 String-Inhalt in einen primitiven Wert konvertieren
Pfeil5.8.3 String-Repräsentation im Format Binär, Hex und Oktal *
Pfeil5.8.4 parseXXX(…)- und printXXX()-Methoden in DatatypeConverter *
Pfeil5.9 Strings zusammenhängen (konkatenieren)
Pfeil5.9.1 Strings mit StringJoiner zusammenhängen
Pfeil5.10 Zerlegen von Zeichenketten
Pfeil5.10.1 Splitten von Zeichenketten mit split(…)
Pfeil5.10.2 Yes we can, yes we scan – die Klasse Scanner
Pfeil5.11 Ausgaben formatieren
Pfeil5.11.1 Formatieren und Ausgeben mit format()
Pfeil5.12 Zum Weiterlesen
 

Zum Seitenanfang

5.8    Konvertieren zwischen Primitiven und Strings Zur vorigen ÜberschriftZur nächsten Überschrift

Bevor ein Datentyp auf dem Bildschirm ausgegeben, zum Drucker geschickt oder in einer ASCII-Datei gespeichert werden kann, muss ihn das Java-Programm in einen String konvertieren. Wenn wir etwa die Zahl 7 ohne Umwandlung ausgäben, hätten wir keine 7 auf dem Bildschirm, sondern einen Pieps aus dem Lautsprecher – je nach Implementierung. Auch umgekehrt ist eine Konvertierung wichtig: Gibt der Benutzer in einem Dialog sein Alter an, ist das zuerst immer ein String. Diesen muss die Anwendung in einem zweiten Schritt in eine Ganzzahl konvertieren, um etwa eine Altersabfrage zu realisieren.

 

Zum Seitenanfang

5.8.1    Unterschiedliche Typen in String-Repräsentationen konvertieren Zur vorigen ÜberschriftZur nächsten Überschrift

Die statischen überladenen String.valueOf(…)-Methoden liefern die String-Repräsentation eines primitiven Werts oder eines Objekts.

[zB]  Beispiel

Konvertierungen einiger Datentypen in Strings:

String s1 = String.valueOf( 10 );                    // 10

String s2 = String.valueOf( Math.PI ); // 3.141592653589793

String s3 = String.valueOf( 1 < 2 ); // true

Die valueOf(…)-Methode ist überladen, und insgesamt gibt es für jeden primitiven Datentyp eine Implementierung:

final class java.lang.String

implements CharSequence, Comparable<String>, Serializable
  • static String valueOf(boolean b)

  • static String valueOf(char c)

  • static String valueOf(double d)

  • static String valueOf(float f)

  • static String valueOf(int i)

  • static String valueOf(long l)

    Liefert die String-Repräsentation der primitiven Elemente.

  • static String valueOf(char[] data)

  • static String valueOf(char[] data, int offset, int count)

    Liefert vom char-Array oder einem Ausschnitt des char-Arrays ein String-Objekt.

Die Methode valueOf(Object)

Der valueOf(Object)-Methode kann ein beliebiges Objekt übergeben werden.

[zB]  Beispiel

Konvertierungen einiger Objekte in String-Repräsentationen:

String r = String.valueOf( new java.awt.Point() );  // java.awt.Point[x=0,y=0]

String s = String.valueOf( java.nio.file.Paths.get( "." ) ); // .

String t = String.valueOf( java.time.LocalTime.now() ); // 09:48:28.047834

Da jedes Objekt eine toString()-Methode besitzt, delegiert valueOf(Object) einfach auf diese.

Listing 5.10    java/lang/String.java, valueOf()

public static String valueOf( Object obj ) {

return (obj == null) ? "null" : obj.toString();

}

Die Implementierung von valueOf(Object obj) fragt für die String-Umsetzung einfach das Objekt obj selbst. Die Sonderbehandlung testet, ob null übergeben wurde, und liefert dann einen gültigen String mit dem Inhalt "null". Da String.valueOf(null) die Rückgabe »null« liefert, gibt auch eine Ausgabe wie System.out.println(null) den String null auf der Konsole aus, denn println(Object) ruft intern String.valueOf(…) auf. Genauso ergibt System.out. println(null + "0") die Ausgabe "null0", da null als Glied in der Additionskette steht.

final class java.lang.String

implements CharSequence, Comparable<String>, Serializable
  • static String valueOf(Object obj)

    Ist obj ungleich null, liefert die Methode obj.toString(), andernfalls die Rückgabe »null«.

 

Zum Seitenanfang

5.8.2    String-Inhalt in einen primitiven Wert konvertieren Zur vorigen ÜberschriftZur nächsten Überschrift

Für das Parsen eines Strings – zum Beispiel von "123" aus einer Benutzereingabe in die Ganzzahl 123 – ist nicht die Klasse String verantwortlich, sondern spezielle Klassen, die für jeden primitiven Datentyp vorhanden sind. Die Klassen deklarieren statische parseXXX(String)-Methoden, wie Tabelle 5.9 zeigt:

Klasse

Konvertierungsmethode

Rückgabetyp

java.lang.Boolean

parseBoolean( String s )

boolean

java.lang.Byte

parseByte( String s )

byte

java.lang.Short

parseShort( String s )

short

java.lang.Integer

parseInt( String s )

int

java.lang.Long

parseLong( String s )

long

java.lang.Double

parseDouble( String s )

double

java.lang.Float

parseFloat( String s )

float

Tabelle 5.9    Methoden zum Konvertieren eines Strings in einen primitiven Typ

Für jeden primitiven Typ gibt es eine sogenannte Wrapper-Klasse mit parseXXX(String)-Konvertiermethoden. Die Bedeutung der Klassen erklärt Abschnitt 10.5, »Wrapper-Klassen und Autoboxing«, genauer. An dieser Stelle betrachten wir nur die Konvertierfunktionalität.

Beispiel mit Double.parseDouble(String)

Die Methode Double.parseDouble(String)[ 141 ](In der Version 6 gab es einen Fehler, der zu viel Aufregung führte: Eine Zahl konnte nicht geparst werden, und der Compiler bzw. die Laufzeitumgebung ging in eine Endlosschleife. Mehr zu dem Fehler findet sich unter http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308. ) wollen wir in einem Beispiel nutzen. Der Benutzer soll in einem grafischen Dialog nach einer Fließkommazahl gefragt werden, und von dieser Zahl sollen dann der Sinus und der Kosinus auf dem Bildschirm ausgegeben werden:

Listing 5.11    src/main/java/com/tutego/insel/string/SinusAndCosinus.java, Ausschnitt

String s = javax.swing.JOptionPane.showInputDialog( "Bitte Zahl eingeben" );

double value = Double.parseDouble( s );

System.out.println( "Sinus: " + Math.sin( value ) );

System.out.println( "Kosinus: " + Math.cos( value ) );

parseXXX(String) und mögliche NumberFormatException-Fehler

Kann eine parseXXX(String)-Methode eine Konvertierung nicht durchführen, weil sich ein String wie "1lala2lö" eben nicht konvertieren lässt, dann löst sie eine NumberFormatException aus. Das ist auch der Fall, wenn parseDouble(String) als Dezimaltrenner ein Komma statt eines Punktes empfängt. Bei der statischen Methode parseBoolean(String) ist die Groß-/Kleinschreibung irrelevant.

[»]  Hinweis

Dieser NumberFormatException-Fehler kann als Test dienen, ob eine Zeichenkette eine Zahl enthält oder nicht, denn eine Prüfmethode wie Integer.isInteger(String) gibt es nicht. Eine Alternative ist, einen regulären Ausdruck zu verwenden und gegen ihn zu testen, etwa so:

stringWithNumber.matches("\\p{Digit}+")

parseXXX(…) und das Verhalten mit Plus, Minus und Leerzeichen

Repräsentiert ein String negative Zahlen, so beginnt der String mit einem »–«, positive Zahlen dürfen auch mit einem »+« beginnen. Die statische Konvertierungsmethode Integer.parseInt(String) schneidet keine Leerzeichen ab und würde einen Parserfehler melden, wenn der String etwa mit einem Leerzeichen endet. (Die Helden der Java-Bibliothek haben allerdings bei Float.parseFloat(…) und Double.parseDouble(…) anders gedacht: Hier wird die Zeichenkette vorher schlank getrimmt.)

[zB]  Beispiel

Leerzeichen zur Konvertierung einer Ganzzahl abschneiden:

String s = " 1234    ".trim();            // s = "1234"

int i = Integer.parseInt( s ); // i = 1234

Das, was bei einem String.valueOf(…) als Ergebnis erscheint – und das ist auch das, worauf zum Beispiel System.out.printXXX(…) basiert –, kann parseXXX(…) wieder in den gleichen Wert zurückverwandeln.

[»]  Hinweis

Eine Methode Character.parseCharacter(String) fehlt. Eine vergleichbare Realisierung besteht darin, auf das erste Zeichen eines Strings zuzugreifen, etwa so:

char c = s.charAt( 0 )

Lokalisiertes parseXXX(String)

Die parseXXX(…)-Methoden sind nicht lokalisiert, können also nur englisch formatierte Zeichenfolgen in primitive Werte umsetzen. Bei den Ganzzahlen ist das kein Problem, nur bei Fließkommazahlen ist das ein großes Problem, denn ein parseDouble("1,3") führt zur NumberFormatException, nur parseDouble("1.3") nicht. Für die Lösung des Problems gibt es zwei Ansätze. Einer ist, vorher den Dezimaltrenner in einen Punkt zu konvertieren:

String s = "3,1";

double d = Double.parseDouble( s.replace( ',', '.' ) ); // 3.1

Diese Lösung ist jedoch nicht gut. Viel besser ist es, auf Klassen zurückzugreifen, die lokalisiertes Parsen ermöglichen, etwa Scanner (wir kommen in Abschnitt 5.10.2 noch einmal auf diese Klasse zurück):

String s = "3,1";

double d = new Scanner( s ).useLocale( Locale.GERMANY ).nextDouble(); // 3.1
 

Zum Seitenanfang

5.8.3    String-Repräsentation im Format Binär, Hex und Oktal * Zur vorigen ÜberschriftZur nächsten Überschrift

Neben den überladenen statischen String.valueOf(primitive)-Methoden, die eine Zahl als String-Repräsentation im vertrauten Dezimalsystem liefern, und den parseXXX(…)-Umkehrmethoden der Wrapper-Klassen gibt es weitere Methoden zum Konvertieren und Parsen in der

  • binären (Basis 2),

  • oktalen (Basis 8),

  • hexadezimalen (Basis 16)

  • und in der Darstellung einer beliebigen Basis (bis 36).

Die Methoden zum Bilden der String-Repräsentation sind nicht an String, sondern zusammen mit Methoden zum Parsen an den Klassen Integer und Long festgemacht.

String-Repräsentationen aufbauen

Zum einen gibt es in den Klassen Integer und Long die allgemeinen Klassenmethoden toString(int i, int radix) für eine beliebige Radix, und zum anderen gibt es Spezialmethoden für die Radix 2, 8 und 16.

final class java.lang.Integer

extends Number

implements Comparable<Integer>, Serializable
  • static String toBinaryString(int i)

  • static String toOctalString(int i)

  • static String toHexString(int)

    Erzeugt eine Binärrepräsentation (Basis 2), Oktalzahlrepräsentation (Basis 8) oder Hexadezimalrepräsentation (Basis 16) der vorzeichenlosen Zahl.

  • static String toString(int i, int radix)

    Erzeugt eine String-Repräsentation der Zahl zur angegebenen Basis.

final class java.lang.Long

extends Number

implements Comparable<Long>, Serializable
  • static String toBinaryString(long i)

  • static String toOctalString(long i)

  • static String toHexString(long i)

    Erzeugt eine Binärrepräsentation (Basis 2), Oktalzahlrepräsentation (Basis 8) oder Hexadezimalrepräsentation (Basis 16) der vorzeichenlosen Zahl. Achtung: Wenn die Zahl negativ ist, wird i ohne Vorzeichen behandelt und 232 addiert.

  • static String toString(long i, int radix)

    Erzeugt eine String-Repräsentation der Zahl zur angegebenen Basis. Negative Zahlen bekommen auch ein negatives Vorzeichen.

Der Parametertyp ist int bzw. long und nicht byte. Dies führt zu Ausgaben, die einkalkuliert werden müssen. Genauso werden führende Nullen grundsätzlich nicht mit ausgegeben.

Anweisung

Ergebnis

Integer.toHexString(15)

f

Integer.toHexString(16)

10

Integer.toHexString(127)

7f

Integer.toHexString(128)

80

Integer.toHexString(255)

ff

Integer.toHexString(256)

100

Integer.toHexString(-1)

ffffffff

Tabelle 5.10    Beispiele für die »toHexString()«-Methode

Die Ausgaben mit printf(…) – bzw. die Formatierung mit String.format(…) – bieten eine Alternative, die in Abschnitt 5.11.1, »Formatieren und Ausgeben mit format()«, vorgestellt wird.

[»]  Hinweis

Eine Konvertierung mit toHexString(x) ist bei negativen Zahlen nicht die gleiche wie mit toString(x, 16):

System.out.println( Integer.toHexString( -10 ) );  // fffffff6

System.out.println( Integer.toString( -10, 16 ) ); // -a

Hier kommt bei toHexString(…) zum Tragen, was als Bemerkung in der Java-Dokumentation angegeben ist, nämlich dass bei negativen Zahlen die Zahl ohne Vorzeichen genommen wird (also 10) und dann 232 addiert wird. Bei toString(…) und einer beliebigen Radix ist das nicht so.

Parsen von String mit Radix

Eine Methode zum Konvertieren eines Strings in eine Ganzzahl für eine gegebene Basis findet sich in den Klassen Integer und Long. Nur in den Klassen Integer und Long gibt es die Unterstützung für eine Basis auch ungleich 10:

final class java.lang.Integer

extends Number

implements Comparable<Integer>, Serializable
  • static int parseInt(String s)

  • static int parseInt(String s, int radix)

final class java.lang.Long

extends Number

implements Comparable<Long>, Serializable
  • static long parseLong(String s)

  • static long parseLong(String s, int radix)

Einige Anwendungsfälle:

Konvertierungsaufruf

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)

inline image throws NumberFormatException

parseInt("99", 8)

inline image throws NumberFormatException

parseInt("Papa", 10)

inline image throws NumberFormatException

parseInt("Papa", 27)

500050

Tabelle 5.11    Beispiele für »Integer.parseInt()« mit unterschiedlichen Zahlenbasen

[zB]  Beispiel

Die Radix geht bis 36 (zehn Ziffern und 26 Kleinbuchstaben). Mit Radix 36 können zum Beispiel ganzzahlige IDs in Textform kompakter dargestellt werden, als wenn sie dezimal wären:

String string = Long.toString( 2656437647773L, 36 );

System.out.println( string ); // xwcmdz8d

long l = Long.parseLong( string, 36 );

System.out.println( l ); // 2656437647773
[»]  Rätsel

Welches Ergebnis ergibt der Ausdruck Long.parseLong( "" + 1 / 0., 35 )?

Parsen von Binär-, Oktal- und Hexadezimalzahlen

Im Fall von String-Konvertierung existieren für die Standardbasen 2, 8 und 16 spezielle Methoden wie toHexString(…), aber zum Parsen gibt es sie nicht. Eine Hexadezimalzahl verarbeitet parseInt(s, 16), denn eine Methode wie parseHex(String) steht nicht bereit.

[»]  Hinweis

Die Methoden parseInt(…) und parseLong(…) verhalten sich bei der String-Repräsentation von negativen Zahlen nicht so, wie zu erwarten wäre:

int i = Integer.parseInt( "7fffffff", 16 ); // 2147483647

int j = Integer.parseInt( "80000000", 16 ); // inline image NumberFormatException

0x7fffffff ist die größte darstellbare positive int-Zahl. Statt bei 0x80000000 den Wert –2.147.483.648 zu liefern, gibt es aber eine NumberFormatException. Die Java-API-Dokumentation gibt zwar auch dieses Beispiel an, stellt dieses Verhalten aber nicht besonders klar. Es gibt den Fall, dass bei negativen Zahlen und parseInt(…)/parseLong(…) auch ein Minus als Vorzeichen angegeben werden muss. Die parseXXX(…)-Methoden sind also keine Umkehrmethoden zu etwa toHexString(…), aber immer zu toString(…):

System.out.println( Integer.toString( -2147483648, 16 ) ); // -80000000

System.out.println( Integer.parseInt( "-80000000", 16 ) ); // -2147483648
 

Zum Seitenanfang

5.8.4    parseXXX(…)- und printXXX()-Methoden in DatatypeConverter * Zur vorigen ÜberschriftZur nächsten Überschrift

Das javax.xml.bind-Paket bietet eine Klasse DatatypeConverter, die eigentlich für die Abbildung von XML-Typen auf Java-Typen gedacht ist, doch auch so einige nützliche Methoden bereitstellt. Wir finden in der Klasse statische parseXXX(String)-Methoden und printXXX(…)-Methoden: Die ersten konvertieren einen String in diverse Datentypen – etwa short parseShort(String) –, und die zweiten formatieren einen bestimmten Datentyp in einen String – etwa String printShort(short). Für die meisten Methoden gibt es mit String.valueOf(…) und den parseXXX(…)/toString(…)-Methoden in den Wrapper-Klassen bessere Alternativen, und die Umwandlung von Datumswerten und Fließkommazahlen ist nicht lokalisiert, doch hervorzuheben sind folgende zwei Methoden:

final class javax.xml.bind.DatatypeConverter
  • static byte[] parseHexBinary(String lexicalXSDHexBinary)

  • static String printHexBinary(byte[] val)

Mit diesen statischen Methoden können leicht Byte-Arrays in die String-Repräsentationen hexadezimal konvertiert werden. Das ist nötig, wenn etwa Bytes in einer Text-Konfigurationsdatei abgelegt werden sollen. DatatypeConverter bietet auch Methoden für eine Base64-Kodierung, allerdings sind die geschachtelten Klassen in java.util.Base64 üblicher.

[zB]  Beispiel

Konvertiere ein Byte-Array in eine String-Repräsentation, einmal im klassischen Hex-Format, einmal in Base64-Kodierung:

byte[] bytes = { 1, 2, 3, (byte) 254, (byte) 255 };

String s1 = DatatypeConverter.printHexBinary( bytes );

String s2 = DatatypeConverter.printBase64Binary( bytes );

System.out.println( s1 ); // 010203FEFF

System.out.println( s2 ); // AQID/v8=

// Arrays.equals( bytes, DatatypeConverter.parseHexBinary( s1 ) ) == true

// Arrays.equals( bytes, DatatypeConverter.parseBase64Binary( s2 ) ) == true

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java ist auch eine Insel Java ist auch eine Insel

Jetzt Buch bestellen


 Buchempfehlungen
Zum Rheinwerk-Shop: Captain CiaoCiao erobert Java

Captain CiaoCiao erobert Java




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




Zum Rheinwerk-Shop: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Objektorientierte Programmierung

Objektorientierte Programmierung




 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2021

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.

 

[Rheinwerk Computing]



Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de



Cookie-Einstellungen ändern