Enumerators can have as many constructors as needed. The constructors are always private and cannot be invoked even by reflection. The constructors are used in values definitions and only there. What is done with the parameters is defined by the developer. They can be used as normal constructor parameters.

In languages like C/C++/C# enums can have integer values assigned.

enum EnumName { VALUE1 = 10, VALUE2 = 20, VALUE3 = 30 };

In fact these enums are treated there as constants and can be cast into int value. In Java you cannot cast an enum to a primitive nor to any other class. But you can simulate assigning a value to it by using a proper constructor. Constructor can accept any kind of parameters and these can be stored in enum’s fields. Enumerators CANNOT have generic types.

Enums can be used as a perfect singletons :) Because Java Virtual Machine will do most of the job for us:

first invoke of Singleton.INSTANCE will cause an instance to be initialized

there will NEVER be another instance of this enum

it can be used as a normal class

To turn a class into a singleton many more steps must be taken. The constructor need to be declared private. It will need to be initialized only once in a method that will return an instance of a singleton (a need to write a static access method). And in Java there should be a way to prevent developers from creating another instance using reflection.
So the following enum is a MUCH better way to create a singleton, isn’t it? ;)

Basic operations on enumerators.
Enum behaves like a normal instance of a class; they can be printed ...
VALUE1
VALUE2
... they can be compared using equals...
false
false
true
... but they can also be compared safely using == operator among themselves (which should NOT be used for normal classes).
false
true
They can be used in a switch statement.
Enum: VALUE1
They can be put into table, list or any other container.
[VALUE1, VALUE2, VALUE3, VALUE2]
[VALUE1, VALUE2]

Sample usage – Enum references

This method shows a way of getting the enum reference.

private static void gettingEnumsReferences() throws Exception {
System.out.println("Getting an enum reference.");
//enums are instantiated when they are loaded by classloader and further instantiation is pointless
//this means that there are only as many instances of the enum as the amount of its declared values
System.out.println("In the application we only reference enumerators.");
SimpleEnum simpleEnum1 = SimpleEnum.VALUE1;
SimpleEnum simpleEnum2 = SimpleEnum.VALUE2;
SimpleEnum simpleEnum3 = SimpleEnum.VALUE3;
System.out.println("Enums CANNOT be created using the new operator ...");
//SimpleEnum error = new SimpleEnum(); <------ THIS WILL CAUSE COMPILATION ERROR
System.out.println("... and using reflection will be of no use either.");
try {
SimpleEnum.class.newInstance();
} catch(InstantiationException e) {
System.out.println("ERROR: Although the compiler will allow the operation from try block, it will always FAIL: " + e.getLocalizedMessage());
}
System.out.println("Enum can be retreivied by name (but this is NOT instantiation).");
SimpleEnum simpleEnum = SimpleEnum.valueOf("VALUE1");
System.out.println(simpleEnum);
System.out.println("But providing invalid name will cause an error.");
try {
SimpleEnum.valueOf("vALUE1");//take notice that this is case-sensitive !!!!!!
} catch(IllegalArgumentException e) {
System.out.println("ERROR: When invoking valueOf it is important to remember about the case-sensitivness.");
}
System.out.println("All available enums can be simply enlisted.");
SimpleEnum[] enums = SimpleEnum.values();
for(SimpleEnum e : enums) {
System.out.println(e);
}
System.out.println("Enum can be retrieved using an enum class name and the proper value name.");
SimpleEnum e = Enum.valueOf(SimpleEnum.class, "VALUE1");
System.out.println(e);
}

The output of this method is as follows:

Getting an enum reference.
In the application we only reference enumerators.
Enums CANNOT be created using the new operator ...
... and using reflection will be of no use either.
ERROR: Although the compiler will allow the operation from try block, it will always FAIL: com.itcuties.java.enums.data.SimpleEnum
Enum can be retrieved by name (but this is NOT instantiation).
VALUE1
But providing invalid name will cause an error.
ERROR: When invoking valueOf it is important to remember about the case-sensitiveness.
All available enums can be simply enlisted.
VALUE1
VALUE2
VALUE3
Enum can be retrieved using an enum class name and the proper value name.
VALUE1

Sample usage – Behaving like classes

This method shows that an enum can be used like any other class instance. You can invoke methods and alter fields.

private static void enumsBehavingLikeClasses() throws Exception {
System.out.println("Enumerators can behave like normal classes.");
ComplexEnum complexEnum = ComplexEnum.VALUE;
System.out.println("A custom method can be called.");
complexEnum.customMethod();
System.out.println("Custom toString will be called when printing the enum.");
System.out.println(complexEnum);
System.out.println("Fields can be accessed (the access scope is of course defined by the access modifier).");
System.out.println(complexEnum.customPublicField);
System.out.println("The fields can be altered just like in a normal class.");
complexEnum.customPublicField = 89;
System.out.println(complexEnum.customPublicField);
}

The output is:

Enumerators can behave like normal classes.
A custom method can be called.
This is a custom enum method!
Custom toString will be called when printing the enum.
Overriden toString: VALUE(9)
Fields can be accessed (the access scope is of course defined by the access modifier).
0
The fields can be altered just like in a normal class.
89