wake-up-neo.com

Java - Können letzte Variablen im statischen Initialisierungsblock initialisiert werden?

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:

 https://i.stack.imgur.com/5I0am.jpg

43
Yatendra Goel

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.

36
SyntaxT3rr0r

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.

18
Kevin Brock
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.

9
Matt Vang

Können Sie die Deklaration in den finally-Block setzen?

try {
    //load file
} catch(IOException e) {
    // horay
} finally {
    Host=config.get......
}
0
Stephen