I don't understand why the following code errors in Java:
public abstract class TestClass
{
private final int data;
protected TestClass(int data) { this.data = data; }
public final class InnerClass extends TestClass
{
private InnerClass(int data) { super(data); }
public static final TestClass CONSTANT = new InnerClass(5);
}
}
The error is on the public static final TestClass CONSTANT = new InnerClass(5);
part.
The errors are:
I:\Documents\NetBeansProjects\TestingGround\src\testingground\TestClass.java:22: error: non-static variable this cannot be referenced from a static context public static final TestClass CONSTANT = new InnerClass(5); ^ I:\Documents\NetBeansProjects\TestingGround\src\testingground\TestClass.java:22: error: Illegal static declaration in inner class TestClass.InnerClass public static final TestClass CONSTANT = new InnerClass(5); ^ modifier 'static' is only allowed in constant variable declarations 2 errors
If I try to achieve the same in C#, it works fine.
public abstract class TestClass
{
private readonly int data;
protected TestClass(int data) { this.data = data; }
public sealed class InnerClass : TestClass
{
private InnerClass(int data) : base(data) { }
public static readonly TestClass CONSTANT = new InnerClass(5);
}
}
Why does Java not allow this?
To create an inner class (as opposed to a nested static class) you need an instance of the enclosing class - you don't have one in this case. Note that there's no direct equivalent of inner classes in C# - a nested class in C# is more like a nested static class in Java, and the meaning of static
in a class declaration in C# is entirely different to the meaning of static
in a class declaration in Java.
Option 1
If you really want it to be an inner class, you can write:
public static final TestClass CONSTANT = new SomeConcreteTestClass().new InnerClass(5);
(Where SomeConcreteTestClass
is a concrete class extending TestClass
)
or, horribly:
public static final TestClass CONSTANT = ((TestClass) null).new InnerClass(5);
Note that you'd need to move the declaration out of InnerClass
though, as inner classes can't declare static variables other than compile-time constant expressions:
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 (§4.12.4).
So you'd end up with:
public abstract class TestClass
{
private final int data;
protected TestClass(int data) { this.data = data; }
public final class InnerClass extends TestClass
{
private InnerClass(int data) { super(data); }
}
public static final TestClass CONSTANT = ((TestClass) null).new InnerClass(5);
}
Option 2
Just make InnerClass
static:
public static final class InnerClass extends TestClass
The addition of static
there is the only change required. That's now much more like a C# nested class (although generics behave differently, as always...) Ideally at that point you'd rename the class, as it's not an inner class...
Java language does not allow an inner class to declare a member that is explicitly or implicitly static, unless the member is a constant variable, see JLS 8.1.3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With