I have an OuterClass
and an NestedClass
. Like this.
public class OuterClass
{
public class NestedClass
{
}
}
Whenever I try to call the constructor of NestedClass
in a static context (like as a static field or a static method), I get a compiler error.
Here is an example code.
public class OuterClass
{
public class NestedClass
{
public static final NestedClass someStaticField = new NestedClass();
public static NestedClass someStaticMethod()
{
return new NestedClass();
}
}
}
And here are the compiler errors that I get.
$ javac OuterClass.java
OuterClass.java:7: error: non-static variable this cannot be referenced from a static context
public static final NestedClass someStaticField = new NestedClass();
^
OuterClass.java:12: error: non-static variable this cannot be referenced from a static context
return new NestedClass();
^
2 errors
What do these errors mean, and what should I be writing instead to achieve the desired outcome of being able to call the constructor in a static context?
The problem is that the NestedClass
is not static
- neither implicitly nor explicitly declared as such - so it is an inner class. From Java Language Specification 8.1.3. Inner Classes and Enclosing Instances:
An inner class is a nested class that is not explicitly or implicitly
static
.
To create an instance of such inner class, an instance of the enclosing (outer class) is needed. If not in a static context, this
is implicitly used when creating such an instance. In a static context, there is no this
and we must provide the instance of the enclosing class. This is accomplish by using a qualified class instance creation expression like:
outer.new InnerClass()
as described in JLS 15.9. Class Instance Creation Expressions:
A qualified class instance creation expression enables the creation of instances of inner member classes and their anonymous subclasses.
More details can be found in JLS 15.9.2. Determining Enclosing Instances.
Applying that to the code of the question, we could do:
public class OuterClass
{
public class NestedClass // actually an Inner Class
{
public static final NestedClass someStaticField = new OuterClass().new NestedClass();
public static NestedClass someStaticMethod()
{
var outer = new OuterClass();
return outer.new NestedClass();
}
}
}
A second possibility would be to not make the nested class an inner class by declaring it as static
and avoiding the need for an enclosing instance:
public class OuterClass
{
// static added to following declaration
public static class NestedClass
{
public static final NestedClass someStaticField = new NestedClass();
public static NestedClass someStaticMethod()
{
return new NestedClass();
}
}
}
Which solution to use should be based on the specific use case and data model, not just because the compiler accepts it!
Note: static
members of inner classes are allowed since Java 16 (JEP 359), so we can have record classes, which are static
, declared in inner classes.