Sadv1r
Sadv1r

Reputation: 173

Constant variable might already have been assigned

I really need help. Don't know how to fix this. I wanna load some constants from properties file. I think, that Catch with FileNotFoundException can be thrown only on the properties.load(). But IDE says that

VK_MIN_ID = VK_MIN_ID_DEFAULT;
VK_MAX_ID = VK_MAX_ID_DEFAULT;
MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;

this variables might already have been assigned. Where? Full code:

private static final int VK_MIN_ID;
private static final int VK_MIN_ID_DEFAULT = 1;
private static final int VK_MAX_ID;
private static final int VK_MAX_ID_DEFAULT = 999_999_999;
private static final int MAX_USERS_TO_PARSE_AT_ONCE;
private static final int MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT = 500;

static {
    FileInputStream fileInputStream;
    Properties properties = new Properties();

    try {
        fileInputStream = new FileInputStream("src/main/resources/vk.properties");
        properties.load(fileInputStream);

        if (properties.containsKey("vk.min.id")) {
            VK_MIN_ID = Integer.parseInt(properties.getProperty("vk.min.id"));
        } else {
            VK_MIN_ID = VK_MIN_ID_DEFAULT;
        }
        if (properties.containsKey("vk.max.id")) {
            VK_MAX_ID = Integer.parseInt(properties.getProperty("vk.max.id"));
        } else {
            VK_MAX_ID = VK_MAX_ID_DEFAULT;
        }
        if (properties.containsKey("max.users.to.parse.at.once")) {
            MAX_USERS_TO_PARSE_AT_ONCE = Integer.parseInt(properties.getProperty("max.users.to.parse.at.once"));
        } else {
            MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
        }
    } catch (FileNotFoundException e) {
        logger.warn("Файл свойств отсуствует! Устанавливаем настройки по умолчанию...");
        VK_MIN_ID = VK_MIN_ID_DEFAULT;
        VK_MAX_ID = VK_MAX_ID_DEFAULT;
        MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
    } catch (IOException e) {
        logger.error("Ошибка чтения файла свойств! Работа будет прекращена", e);
    }
}

Big thanks.

Upvotes: 2

Views: 174

Answers (3)

sstan
sstan

Reputation: 36523

Instead of having a try-catch, and having values set in the catch block, you can replace all that with a simple if-else, and that will work without having to remove the final. Something like this:

File f = new File("src/main/resources/vk.properties");
if (f.exists()) {
    // set values here from FileInputStream
    // ...
} else {
    // set alternate values here if the file is not found.
    VK_MIN_ID = VK_MIN_ID_DEFAULT;
    VK_MAX_ID = VK_MAX_ID_DEFAULT;
    MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
}

EDIT

The reason why you can't assign the constants from the catch block, is because, even though you know that the exception will be caught before the values are set for the first time, the compiler doesn't know that for a fact. It has to assume that the exception can be thrown anywhere in the try block. And so, from the perspective of the compiler, it is possible for the final variables to have been set before the exception is caught, so it gives you the error.

Upvotes: 2

rgettman
rgettman

Reputation: 178333

The Java compiler doesn't see what we can see -- that the assignment to MAX_USERS_TO_PARSE_AT_ONCE is at the end of the try block, so that either it gets assigned there or in the catch block. It sees a possibility that it gets assigned in the try block, an exception is thrown, and it gets assigned again in the catch block.

Use a temporary variable to work around this.

int temp;
try {
    // other code
    if (properties.containsKey("max.users.to.parse.at.once")) {
        temp = Integer.parseInt(properties.getProperty("max.users.to.parse.at.once"));
    } else {
        temp = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
    }
} catch (FileNotFoundException e) {
    // other code.
    temp = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
} catch (IOException e) {
    // You'll need to assign something to temp here too.
}

After the last catch block, then assign temp to your final variable, once.

MAX_USERS_TO_PARSE_AT_ONCE = temp;

This way you can keep MAX_USERS_TO_PARSE_AT_ONCE final.

Upvotes: 3

Jack
Jack

Reputation: 133639

The problem is this:

    VK_MIN_ID = VK_MIN_ID_DEFAULT;
    VK_MAX_ID = VK_MAX_ID_DEFAULT;
    MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;

VK_MIN_ID, VK_MAX_ID and MAX_USERS_TO_PARSE_AT_ONCE are declared as final, this means that once assigned you can't change their value. Remove final keyword.

Upvotes: 1

Related Questions