6

I am trying to initialize a static final variable. However, this variable is initialized in a method which can throw exception, therefor, I need to have inside a try catch block.

Even if I know that variable will be either initialized on try or on catch block, java compiler produces an error

The final field a may already have been assigned

This is my code:

public class TestClass {

  private static final String a;

  static {
    try {
      a = fn(); // ERROR
    } catch (Exception e) {
      a = null;
    }
  }

  private static String fn() throws Exception {
    throw new Exception("Forced exception to illustrate");
  }

}

I tried another approach, declaring it as null directly, but it shows a similar error (In this case, it seems totally logic for me)

The final field TestClass.a cannot be assigned

public class TestClass {

  private static final String a = null;

  static {
    try {
      a = fn(); // ERROR
    } catch (Exception e) {
    }
  }

  private static String fn() throws Exception {
    throw new Exception("Forced exception to illustrate");
  }

}

Is there an elegant solution for this?

Mayday
  • 4,680
  • 5
  • 24
  • 58
  • 2
    Try with passing by a temporary variable `b` in your `try...catch`, test the result and following it, assign `a` value – Kaddath Apr 23 '18 at 09:23

4 Answers4

11

You can assign the value to a local variable first, and then assign it to the final variable after the try-catch block:

private static final String a;

static {

    String value = null;
    try {
        value = fn();
    } catch (Exception e) {
    }
    a = value;

}

This ensures a single assignment to the final variable.

Eran
  • 387,369
  • 54
  • 702
  • 768
1

Final variables can only be set once.

You cannot (and do not need to) set a to null in the catch block.

Make the following change:

public class TestClass {


      private static final String a = setupField();

      private static String setupField() {
        String s = "";
        try {
            s = fn();
        } catch (Exception e) {
          // Log the exception, etc.
        }
        return s;
      }

      private static String fn() throws Exception {
        return "Desired value here";
      }
Austin Schaefer
  • 695
  • 5
  • 19
  • 1
    This will produce a different error - `The blank final field a may not have been initialized` - since now `a` is not guaranteed to be initialized by the static initializer block. – Eran Apr 23 '18 at 09:29
  • 1
    Well, now you have two assignments to a final variable (first error) and a method that should return a String but has no return statement (second error). – Eran Apr 23 '18 at 09:42
0

private static final String a = null;

properties that are final are only initialise once. Either in the Constructor or the way you did it here. You cannot give 'a' a new value after you have given it the value null. If you dont have a final you can set the value via the fn function

Marcus Lanvers
  • 383
  • 5
  • 20
0

It's because final variable can only be assigned only once and it can't be reassigned again.

Nothing to do with try/catch

Shubhendu Pramanik
  • 2,711
  • 2
  • 13
  • 23
  • "`final` variable can only be assigned only once at the time of declaration". That's not true, haven't you heard of blank finals? – Kayaman Apr 23 '18 at 09:29
  • there is a link with `try...catch` in the way that code in the `try` is effectively "tried", so that `a` was assigned already when reaching the `catch` if there is an error, contrary to what the OP expected. – Kaddath Apr 23 '18 at 09:34