When reading this question, I open my editor to try some code samples to verify and understand it. The following is my code:
public enum EnumImpl {
B {
public void method() {
System.out.println(s); //(1)non-static variable s cannot be referenced from a static context
}
public static int b; //(2)Illegal static declaration in inner class
};
private int s;
}
But compiling the upper code makes me more confused.
B
actually belong to a static class. So in method
, it is a static context. A nested enum type is implicitly static.
The following is the byte code of anonymous synthetic class of B:
final class enum_type.EnumImpl$1 extends enum_type.EnumImpl {
enum_type.EnumImpl$1(java.lang.String, int);
Code:
0: aload_0
1: aload_1
2: iload_2
3: aconst_null
4: invokespecial #1 // Method enum_type/EnumImpl."<init>":(Ljava/lang/String;ILenum_type/EnumImpl$1;)V
7: return
public void method();
Code:
0: return
}
So the class of B is static or not?
@Lew Bloch seems saying it is like the following (the behavior matches with above enum example, but if this is true, the answer of the linked question is wrong in some senses).
abstract class Cmp {
private int s;
static {
class Bclass extends Cmp {
public void method() {
// System.out.println(s);
}
// private static int b;
}
}
}
As enums are inherently static , there is no need and makes no difference when using static-keyword in enums . If an enum is a member of a class, it is implicitly static.
An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden). An enum cannot be used to create objects, and it cannot extend other classes (but it can implement interfaces).
Every enum constant is always implicitly public static final. Since it is static, we can access it by using the enum Name. Since it is final, we can't create child enums. We can declare the main() method inside the enum.
Enums are implicitly public static final . You can refer to a. DOG because you may access static members through instance references, even when null: static resolution uses the reference type, not the instance.
Your declaration of method()
is in the wrong place. You declare it in the constant body. But it doesn't override anything. It belongs in the enum body, not the instance body.
The instance subtype is declared in the static initializer for the enum constant. Since the context is static it does not have access to the enum instance variables.
Your enum declaration is not static, it is top-level, and top-level classes cannot be static.
Constant bodies define an implicit nested anonymous subclass of the enum, and do not constitute nested enums as meant by the JLS. Each constant is of a different anonymous subtype of the enum you're declaring, which subtype is not static. However, the subtype is declared in a static context, so that's why the code can't reach the instance variable.
EDIT: Useful references from the JLS
https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.9.1 "The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type. The class body is governed by the usual rules of anonymous classes; in particular it cannot contain any constructors. Instance methods declared in these class bodies may be invoked outside the enclosing enum type only if they override accessible methods in the enclosing enum type (§8.4.8)."
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.9.5 "An anonymous class declaration is automatically derived from a class instance creation expression by the Java compiler. An anonymous class is never abstract (§8.1.1.1). An anonymous class is always implicitly final (§8.1.1.2). An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1)."
The error message "non-static variable s cannot be referenced from a static context" is puzzling because the issue isn't that s
is static but that it isn't accessible in method
. If you remove private
from private int s;
, then the error message goes away.
For the method
declaration to be useful, one also needs to add public void method() {}
or public abstract void method();
outside the declaration of B
.
If you do both, the code
enum EnumImpl {
B {
public void method() {
System.out.println(s);
}
};
public abstract void method();
int s;
}
will compile, and you can call EnumImpl.B.method()
.
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