An enum
in java has a default constructor when it's is not defined and it's private.
Default access modifier has different meanings in different scopes. For example inside a class default access modifier for methods and fields is package private
.
Where as in an interface default access modifier means public
. In fact there can be no other modifier on an interface field so it's implicitly public.
On a top level class it's package private (where only 2 access modifiers are allowed public
and default package private)
So the answer to your question is it is so because compiler decides so. Compiler writer had to uphold the language specification contract.
You're right in thinking that it's a normal class after everything. Every object blueprint type in java is a class which can be represented by java.lang.Class
. These restrictions for interfaces, enums, abstract classes, anonymous classes, method local classes are validated by compiler only.
If you can somehow escape the compiler and generate your own byte code for enums or other way around if you can modify the byte code of generated enum
class so that it's private constructor becomes public may be you would be able to call it's constructor outside the enum's private scope. You can also try experimenting with reflection to do the same. In fact by generating byte code manually JVM languages like Groovy, Jython, JRuby, Clojure are able to provide functionalities that are not in Java itself. They're bypassing java compiler.
Purpose for having constructor in enum
s is to be able to set fields of constants in one call. All constants inside an enum
are instances of the enum
class, so they also consist the fields declared in it.
enum Test
{
T1(1), // equivalent to public static final Test T1 = new Test(1);
T2(2); // equivalent to public static final Test T2 = new Test(2);
int id;
Test(int id)
{
this.id = id;
}
}
And finally bellow is the output of decompiled code for above enum
by using java -p Test.class
final class Test extends java.lang.Enum<Test>
{
public static final Test T1;
public static final Test T2;
int id;
private static final Test[] $VALUES;
public static Test[] values();
public static Test valueOf(java.lang.String);
private Test(int);
static {};
}
It should give a better understanding of what happens when the class compiles.