Подтвердить что ты не робот

Java. Можно ли инициализировать окончательные переменные в статическом блоке инициализации?

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

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

/img/1b2862e9d0ae2e745a1beed2fa31b58a.jpg

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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, выходящим повсюду).

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

Ответ 4

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

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