Advanced Java Services | Assertions |
Mit der Version 1.4 hat Java Assertions eingeführt. Seitdem ist assert ein Schlüsselwort und darf nicht mehr als Bezeichner verwendet werden. Mit einem assert Statement macht man eine (hoffentlich wohlbegründete) Annahme an einer bestimmte Stelle im Code. Nehman wir an, wir haben eine Methode, der eine Zahl übergeben wird und die daraus mit einem bestimmten Algorithmus eine weitere Zahl generiert und zurückgibt. Der Algorithmus sollte eigentlich immer eine positive Zahl ergeben, eigentlich...
private static int assertionDemo(int x) { int y = ... // do something with x and y // resulting in y > 0 return y; }
Assertions schaffen hier einen Mechanismus um in einem späteren Programmablauf diese Annahme zu testen. Statt mit if/else zu arbeiten oder mit Exceptions kann man in solchen Fällen auch Assertions verwenden. Diese kann man dann zur Laufzeit durch eine Paramterangabe an die Virtual Machine einschalten. Normalerweise sind sie ausgeschaltet. Das sieht in unserem Falle folgendermaßen aus.
private static int form1(int x)
{
int y = ...
// do something with x and y
// resulting in y > 0
assert(y > 0);
return y;
}
Bevor wir y zurückgeben fügen wir das Assertstatement ein. Es wird vom Compiler einfach übergangen. Beim Aufruf können wir dann die Assertions einschalten. Falls unsere Annahme nicht stimmt wird ein AssertionError geworfen.
In der obigen Form des Assertstatements gibt die JVM lediglich das Auftreten des Fehlers bekannt verbunden mit Zeilennummern.
Exception in thread "main" java.lang.AssertionError at Main.form2(Main.java:51) at Main.main(Main.java:33)
Wenn man mehr Information will, dann kann man das Assertstatement um eine Meldung erweitern, die im Fehlerfalle mit ausgegeben wird.
private static int form2(int x)
{
int y = ...
// do something with x and y
assert( y > 0) : "Error : y = " + y;
return y;
}
Der Ausdruck nach dem Doppelpunkt muß immer einen Wert haben. Das kann ein primitiver Wert sein oder auch ein durch ein Object erzeugter Wert sein. Im letzeren Fall wird bei der Fehlermeldung immer die toString()-Methode aufgerufen. fast immer verwendet man Strings an dieser Stelle.
Das Ausschalten wird nur im Zusammenhang mit komplexen Situationen gebraucht. So kann man etwa Assertions zunächst global einschalten, aber dann für bestimmte Pakete ausschalten. Generell steht -ea für Einschalten und -da für Ausschalten. Man kann die Abkürzungen auch Ausschreiben, also -enableassertions und -disableassertions. Man übergibt den Parameter an den Javainterpreter java.
java -ea
bzw.
java -da
siehe Assertions Ein- und Ausschalten.
-ea und -da sind globale Schalter. Man kann auch differenzierter Arbeiten und Assertions für Klassen und/oder Pakete ein- oder Ausschalten. Dazu macht man nach dem Schalter einen Doppelpunkt und gibt dahinter das Paket oder die Klasse an. Einige Beispiele hierzu listet die folgende Tabelle.
Kommandozeilenparameter | Bedeutung |
---|---|
-ea | schaltet Assertions global ein |
-ea -dsa | schaltet Assertions global ein, aber deaktiviert sie für Systemklassen |
-ea:myPackage.MyClass | schaltet Assertions für die Klasse MyClass ein |
-ea:myPackage... | schaltet Assertions für das Paket myPackage und für alle Unterpakete (...) ein. |
-ea -da:myPackage... | schaltet Assertions global ein, schaltet sie ab für das Paket myPackage und alle Unterpakete (...) davon. |
Assertions sind schon der Beginn der Testphase und sind nicht als regulärer Code zu betrachten. Das unterscheidet sie von Exceptions. Die Situation
public int lieberNicht(int x) { assert( x > 0) : "Error : x = " + x; //... return y; }
Über eine public-Methode hat man keine Kontrolle mehr, jeder kann sie verwenden und stößt dann evtl. auf diese Assertion. Hier ist ein if oder eine normale Exception angebracht. In der Regel verwendet man Assertions nur in privaten Methoden. Eine Ausnahme kann etwa der default-Zweig in einem switch-Statement sein, der "eigentlich" nie auftreten sollte...