web-dev-qa-db-fra.com

Java - Les variables finales peuvent-elles être initialisées dans un bloc d'initialisation statique?

D'après ma compréhension du langage Java, les variables statiques peuvent être initialisées dans static initialization block.

Cependant, lorsque j'essaie d'implémenter cela dans la pratique (les variables static qui sont aussi final), j'obtiens l'erreur indiquée dans la capture d'écran ci-dessous:

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

43
Yatendra Goel

Oui, bien sûr: les variables static final peuvent être initialisées dans un bloc statique mais .... vous avez des GOTO implicites dans cet exemple (try/catch est essentiellement un 'Capture GOTO si quelque chose de mauvais arrive' ).

Si une exception est levée, vos variables final ne seront pas initialisées.

Notez que l'utilisation de constructions statiques va à l'encontre du dogme orienté objet. Cela peut compliquer vos tests et rendre le débogage plus difficile.

36
SyntaxT3rr0r

Vous pouvez le faire, mais vous devez quitter le bloc statique en lançant une exception. Vous pouvez rediffuser l'exception qui a été interceptée ou une nouvelle. Généralement, cette exception doit être une RuntimeException. Vous ne devriez vraiment pas attraper une Exception générique, mais des exceptions plus spécifiques qui pourraient être levées depuis votre bloc try. Enfin, si un initialiseur statique lève une exception, il rendra la classe inutilisable pendant cette exécution spécifique, car la machine virtuelle Java ne tentera d'initialiser votre classe qu'une seule fois. Toute tentative ultérieure d'utilisation de cette classe entraînera une autre exception, telle que NoClassDefFoundError.

Donc, pour que ça fonctionne, votre initialiseur devrait lire quelque chose comme ceci:

static {
    try {
        ...
    } catch (Exception e) {
        e.PrintStackTrace();
        throw new InitializationFailedException("Could not init class.", e);
    }
}

En supposant que InitializationFailedException est une RuntimeException personnalisée, mais vous pouvez en utiliser une existante.

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;
        }
    }
}

En supposant qu'aucun endroit en amont ne soit en mesure d'attraper un ExceptionInInitializationError ou un Exception général, le programme ne doit jamais essayer d'utiliser myVar . Si toutefois ceux-ci sont interceptés et que le programme ne se termine pas, vous devez alors coder pour surveiller et gérer myVar étant null (ou contentez-vous de NullPointerExceptions sortir partout).

Je ne suis pas sûr qu'il existe un bon moyen de gérer cela.

9
Matt Vang

Pouvez-vous mettre la déclaration dans le bloc finally?

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