5

Why does this line:

static final Integer intValue = 1;

give a compiler error, while this line declared in the same way:

static final String strValue = "aaa";

does not.

The full code:

public class InnerClass {
    class NestedClass {
        static final String strValue = "aaa";
        static final Integer intValue = 1;
    }
}

Compile time error:

The field intValue cannot be declared static in a non-static inner type, unless initialized with a constant expression

6
  • Please edit the post and add the compiler error. Commented Apr 15, 2022 at 16:54
  • 1
    Done, added error @Turing85 Commented Apr 15, 2022 at 16:55
  • 1
    Interestingly it doesn't give an error when it is a primitive int Commented Apr 15, 2022 at 17:19
  • 1
    It probably has to do with the fact that Integer is a class and although you can assign the int literal 1 to an instance of an Integer at runtime, it would still result in a wrapper object allocated on the heap, so it's not a constant expression. Changing to int should make it work. String literals are interned and they get a constant chunk of memory so those are constant expressions. Commented Apr 15, 2022 at 17:20
  • 1
    Please, mention the JDK version where you see a compilation error. The same code fails using JDK 11 but successfully compiles when JDK 17 is used. Commented Apr 16, 2022 at 4:28

1 Answer 1

4

It is implied that you're using an older version of Java (such as 11), as this is not reproducible with either 17 (openjdk version "17.0.2" 2022-01-18) or 18 (openjdk version "18" 2022-03-22). For this answer, I'm using Java 11 ("11.0.14" 2022-01-18 LTS) as the error you describe is reproducible using that version.

Here's a compilation attempt using Java 11:

% cat Test.java 
public class Test {
    class NestedClass {
        static final Integer intValue = 1;
    }
}

% javac -version
javac 11.0.14

% javac Test.java
Test.java:3: error: Illegal static declaration in inner class Test.NestedClass
        static final Integer intValue = 1;
                             ^
  modifier 'static' is only allowed in constant variable declarations
1 error

Why did that fail? The Java Language Spec (again, for Java 11) states that you cannot define an inner class with a static member, unless that member is a constant:

"It is a compile-time error if an inner class declares a member that is explicitly or implicitly static, unless the member is a constant variable"

Why did it work with a String - static final String strValue = "aaa"? Because a String is a constant:

"A String object has a constant (unchanging) value"

What else besides String is a constant? A final primitive:

"A constant variable is a final variable of primitive type or type String that is initialized with a constant expression"

So what happens if you change the type from Integer to int - does that work? Yes, it works fine:

class InnerClass {
    class NestedClass {
        static final int intValue = 1; // no problems in Java 11 using primitive
    }
}

Or you could try a later Java version, such as 17:

% javac -version
javac 17.0.2
% javac Test.java
%

I did not look further into why later versions allow static final Integer, even though later versions of JLS (such as version 18) still contain the same wording which suggests Integer should not work (even though it clearly does).

"A constant variable is a final variable of primitive type or type String that is initialized with a constant expression"

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.