Khushal Singh
Khushal Singh

Reputation: 59

Declare static variables in inner non-static class

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

Upvotes: 5

Views: 336

Answers (1)

Kaan
Kaan

Reputation: 5754

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"

Upvotes: 4

Related Questions