Java - Могут ли конечные переменные быть инициализированы в статическом блоке инициализации? - PullRequest
43 голосов
/ 26 февраля 2010

Исходя из моего понимания языка Java, статические переменные могут быть инициализированы в static initialization block.

Однако, когда я пытаюсь реализовать это на практике (static переменные тоже final)Я получаю ошибку, показанную на скриншоте ниже:

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

Ответы [ 4 ]

35 голосов
/ 26 февраля 2010

Да, конечно: static final переменные могут быть инициализированы в статическом блоке , но .... у вас есть неявные GOTO в этом примере (try/catch по сути является 'GOTO catch, если происходит что-то плохое ').

Если выдается исключение, ваши final переменные не будут инициализированы.

Обратите внимание, что использование статических конструкций идет вразрез с объектно-ориентированной догмой. Это может усложнить ваше тестирование и усложнить отладку.

18 голосов
/ 26 февраля 2010

Вы можете сделать это, но вам нужно выйти из статического блока, выдав исключение - вы можете сбросить перехваченное исключение или новое. Обычно это исключение должно быть RuntimeException. Вы действительно не должны ловить универсальные Exception, но более конкретные исключения, которые могут быть выброшены из вашего блока try. Наконец, если статический инициализатор генерирует исключение, то он делает класс непригодным для использования во время этого конкретного запуска, потому что JVM попытается инициализировать ваш класс только один раз. Последующие попытки использовать этот класс приведут к другому исключению, например NoClassDefFoundError.

Итак, для работы ваш инициализатор должен прочитать что-то вроде этого:

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

Предполагая, что InitializationFailedException - это пользовательский RuntimeException, но вы можете использовать существующий.

9 голосов
/ 28 ноября 2011
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;
        }
    }
}

Если предположить, что нет, где восходящий поток находится в состоянии перехватить либо ExceptionInInitializationError , либо общее Исключение , тогда программа не должна пытаться использовать myVar . Однако, если они перехвачены, и программа не заканчивается, вам нужно написать код, чтобы отслеживать и обрабатывать myVar как ноль (или довольствоваться NullPointerExceptions, появляющимся во всем).

Я не уверен, что есть хороший способ справиться с этим.

0 голосов
/ 20 марта 2011

Можете ли вы поместить объявление в блок finally?

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