Zu jedem primitiven Datentyp in Java gibt es eine korrespondierende Wrapper-Klasse. Diese kapselt die primitive Variable in einer objektorientierten Hülle und stellt eine Reihe von Methoden zum Zugriff auf die Variable zur Verfügung. Zwar wird man bei der Programmierung meist die primitiven Typen verwenden, dennoch gibt es einige Situationen, in denen die Anwendung einer Wrapper-Klasse sinnvoll sein kann:
Wrapper-Klassen existieren zu allen numerischen Typen und zu den Typen char und boolean:
|
Wrapper-Klasse |
Primitiver Typ |
| Byte | byte |
| Short | short |
| Integer | int |
| Long | long |
| Double | double |
| Float | float |
| Boolean | boolean |
| Character | char |
| Void | void |
Die Instanzierung einer Wrapper-Klasse kann meist auf zwei unterschiedliche Arten erfolgen. Einerseits ist es möglich, den korrespondierenden primitiven Typ an den Konstruktor zu übergeben, um ein Objekt desselben Werts zu erzeugen. Alternativ kann meist auch ein String an den Konstruktor übergeben werden. Dieser wird in den entsprechenden primitiven Typ konvertiert und dann zur Initialisierung der Wrapper-Klasse verwendet.
public Integer(int i); public Integer(String s) throws NumberFormatException; public Long(long l); public Long(String s); throws NumberFormatException; public Float(float f); public Float(double d); public Float(String s); throws NumberFormatException; public Double(double d); public Double(String s); throws NumberFormatException; public Boolean(boolean b); public Boolean(String s); public Character(char c);
|
|
Das in diesem Beispiel mehrfach verwendete Schlüsselwort throws deklariert Ausnahmen, die von einer Methode verursacht werden können. Wir werden darauf in Kapitel 9 zurückkommen und uns dort ausführlich mit dem Konzept der Ausnahmen beschäftigen. |
Die meisten Wrapper-Klassen besitzen zwei Methoden, um den internen Wert abzufragen. Eine der beiden liefert ihn passend zum korrespondierenden Grundtyp, die andere als String. Der Name von Methoden der ersten Art setzt sich aus dem Namen des Basistyps und der Erweiterung "Value" zusammen, beispielsweise charValue, booleanValue oder intValue. Die numerischen Methoden intValue, longValue, floatValue und doubleValue stehen dabei für alle numerischen Wrapper-Klassen zur Verfügung.
Der Name der Methode, die den internen Wert als String zurückgibt, ist toString. Diese Methode steht in allen Wrapper-Klassen zur Verfügung.
public boolean booleanValue(); public char charValue(); public int intValue(); public long longValue(); public float floatValue(); public double doubleValue(); public String toString();
Die numerischen Wrapper-Klassen stellen Konstanten zur Bezeichnung spezieller Elemente zur Verfügung. So gibt es in jeder der Klassen Byte, Short, Integer, Long, Float und Double die Konstanten MIN_VALUE und MAX_VALUE, die das kleinste bzw. größte Element des Wertebereichs darstellen. In den Klassen Float und Double gibt es zusätzlich die Konstanten NEGATIVE_INFINITY, POSITIVE_INFINITY und NaN. Sie stellen die Werte minus unendlich, plus unendlich und undefiniert dar.
Die Klasse java.lang.Math enthält Funktionen zur Fließkomma-Arithmetik. Alle Methoden dieser Klasse sind vom Typ static und können daher ohne konkretes Objekt verwendet werden. Nachfolgend wollen wir die wichtigsten von ihnen auflisten und eine kurze Beschreibung ihrer Funktionsweise geben.
java.lang.Math stellt die üblichen Winkelfunktionen und ihre Umkehrungen zur Verfügung. Winkelwerte werden dabei im Bogenmaß übergeben.
public static double sin(double x); public static double cos(double x); public static double tan(double x); public static double asin(double x); public static double acos(double x); public static double atan(double x);
Die Methoden min und max erwarten zwei numerische Werte als Argument und geben das kleinere bzw. größere von beiden zurück.
public static int min(int a, int b); public static long min(long a, long b); public static float min(float a, float b); public static double min(double a, double b); public static int max(int a, int b); public static long max(long a, long b); public static float max(float a, float b); public static double max(double a, double b);
Die nachfolgend aufgelisteten Methoden dienen zur Berechnung der Exponentialfunktion zur Basis e, zur Berechnung des natürlichen Logarithmus und zur Berechnung der Exponentialfunktion zu einer beliebigen Basis. Mit sqrt kann die Quadratwurzel einer Fließkommazahl ermittelt werden.
public static double exp(double a); public static double log(double a) throws ArithmeticException; public static double pow(double a, double b) throws ArithmeticException ; public static double sqrt(double a) throws ArithmeticException;
Mit Hilfe der Methode abs wird der absolute Betrag eines numerischen Werts bestimmt. ceil liefert die kleinste ganze Zahl größer und floor die größte ganze Zahl kleiner oder gleich dem übergebenen Argument. Mit Hilfe von round kann ein Wert gerundet werden.
public static int abs(int a); public static long abs(long a); public static float abs(float a); public static double abs(double a); public static double ceil(double a); public static double floor(double a); public static int round(float a);
Die Klasse Object ist die Superklasse aller anderen Klassen. Jede Klassendefinition, die keine extends-Klausel besitzt, wird direkt aus Object abgeleitet. Jede abgeleitete Klasse stammt schließlich von einer nicht mehr weiter abgeleiteten Klasse ab und ist damit letztlich selbst aus Object abgeleitet.
Die Klasse Object definiert einige elementare Methoden, die für alle Arten von Instanzen nützlich sind. Die Methode equals beispielsweise testet, ob zwei Objekte denselben Inhalt haben, clone kopiert ein Objekt, und toString erzeugt die String-Repräsentation eines Objektes. Damit diese Methoden in abgeleiteten Klassen funktionieren, müssen sie bei Bedarf überlagert werden. Dies gilt für equals und clone besonders dann, wenn das Objekt Referenzen enthält.
Mit der Methode getClass der Klasse Object besitzt ein beliebiges Objekt die Fähigkeit, ein passendes Klassenobjekt zu liefern. Zu jeder Klasse, die das Laufzeitsystem verwendet, wird während des Ladevorgangs ein Klassenobjekt vom Typ Class erzeugt. Die Klasse Class stellt Methoden zur Abfrage von Eigenschaften der Klasse zur Verfügung und erlaubt es, Klassen dynamisch zu laden und Instanzen dynamisch zu erzeugen.
Wir wollen uns das dynamische Laden und Instanzieren von Klassen an einem Beispiel ansehen. Das folgende Listing zeigt das Interface Hello und die Klassen A, B, C und D. Hello deklariert die Methode hello, die von den Klassen A und B implementiert wird. C besitzt ebenfalls die Methode hello, allerdings ohne das Interface Hello zu implementieren. D schließlich implementiert nicht hello, sondern hallo.
Die Hauptklasse Example0702 liest zunächst einen Klassennamen von der Standardeingabe ein. Mit der Klassenmethode forName der Klasse Class wird dann ein Klassenobjekt zu einer Klasse dieses Namens beschafft. Dieses wird verwendet, um mit der Methode newInstance der Klasse Class ein neues Objekt zu erzeugen. Dieses Objekt wird schließlich in das Interface Hello konvertiert und dessen Methode hello aufgerufen.
Das Programm ist in der Lage, die beiden Klassen A und B ordnungsgemäß zu instanzieren und ihre Methode hello aufzurufen. Bei C und D gibt es eine Ausnahme des Typs ClassCastException, weil beide Klassen nicht das Interface Hello implementieren. Alle anderen Klassennamen werden mit der Ausnahme ClassNotFoundException quittiert.
import java.io.*;
interface Hello
{
public void hello();
}
class A
implements Hello
{
public void hello()
{
System.out.println("hello A");
}
}
class B
implements Hello
{
public void hello()
{
System.out.println("hello B");
}
}
class C
{
public void hello()
{
System.out.println("hello C");
}
}
class D
{
public void hallo()
{
System.out.println("hallo D");
}
}
public class Example0702
{
public static void main(String[] args)
{
String buf = "";
BufferedReader in = new BufferedReader(
new InputStreamReader(
new DataInputStream(System.in)));
while (true) {
try {
System.out.print("Klassenname oder ende eingeben: ");
buf = in.readLine();
if (buf.equals("ende")) {
break;
}
Class c = Class.forName(buf);
Object o = c.newInstance();
((Hello)o).hello();
} catch (IOException e) {
System.out.println(e.toString());
} catch (ClassNotFoundException e) {
System.out.println("Klasse nicht gefunden");
} catch (ClassCastException e) {
System.out.println(e.toString());
} catch (InstantiationException e) {
System.out.println(e.toString());
} catch (IllegalAccessException e) {
System.out.println(e.toString());
}
}
}
}
Eine Beispielsitzung des Programms könnte so aussehen:
A hello A B hello B C java.lang.ClassCastException D java.lang.ClassCastException E Klasse nicht gefunden ende