Aufgrund meines Verständnisses der Java-Sprache können statische Variablen in static initialization block
initialisiert werden.
Wenn ich jedoch versuche, dies in der Praxis zu implementieren (static
-Variablen, die auch final
sind), erhalte ich den folgenden Fehler:
Ja natürlich: static final
-Variablen können in einem statischen Block initialisiert werden aber .... Sie haben implizite GOTOs in diesem Beispiel (try/catch
ist im Wesentlichen ein 'GOTO-Catch, wenn etwas Schlimmes passiert' ).
Wenn eine Ausnahme ausgelöst wird, werden Ihre Variablen final
nicht initialisiert.
Beachten Sie, dass die Verwendung statischer Konstrukte gegen das objektorientierte Dogma verstößt. Dies kann das Testen erschweren und das Debuggen erschweren.
Sie können dies tun, aber Sie müssen den statischen Block beenden, indem Sie eine Ausnahme auslösen. Sie können die abgefangene Ausnahme erneut auslösen oder eine neue auslösen. Im Allgemeinen muss diese Ausnahme eine RuntimeException
sein. Sie sollten wirklich keine generische Exception
erfassen, sondern spezifischere Ausnahmen, die möglicherweise innerhalb Ihres try
-Blocks ausgelöst werden. Wenn ein statischer Initialisierer eine Ausnahme auslöst, wird die Klasse während dieses bestimmten Laufs unbrauchbar, da die JVM nur einmal versucht, Ihre Klasse zu initialisieren. Nachfolgende Versuche, diese Klasse zu verwenden, führen zu einer anderen Ausnahme, z. B. NoClassDefFoundError
.
Um zu funktionieren, sollte Ihr Initialisierer so etwas lesen:
static {
try {
...
} catch (Exception e) {
e.PrintStackTrace();
throw new InitializationFailedException("Could not init class.", e);
}
}
Angenommen, InitializationFailedException
ist eine benutzerdefinierte RuntimeException
, Sie können jedoch eine vorhandene verwenden.
public class MyClass
{
private static final SomeClass myVar;
static
{
Object obj = null; // You could use SomeClass, but I like Object so you can reuse it
try
{
obj = new SomeClass(...);
}
catch(WhateverException err)
{
// Possibly nested try-catches here if the first exception is recoverable...
// Print an error, log the error, do something with the error
throw new ExceptionInInitializerError(err);
}
finally
{
myVar = (SomeClass) obj;
}
}
}
Angenommen, no ist dort, wo der Upstream in der Lage ist, entweder einen ExceptionInInitializationError oder einen allgemeinen Exception abzufangen, dann sollte das Programm niemals versuchen, myVar zu verwenden. Wenn diese jedoch abgefangen werden und das Programm nicht beendet wird, müssen Sie dafür sorgen, dass myVar null ist (oder mit NullPointerExceptions
zufrieden ist).
Ich bin mir nicht sicher, ob es einen guten Weg gibt, damit umzugehen.
Können Sie die Deklaration in den finally-Block setzen?
try {
//load file
} catch(IOException e) {
// horay
} finally {
Host=config.get......
}