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...
See more on this question at Stackoverflow