Week 98 — What is an enum?

Question of the Week #98
What is an enum?
7 Replies
0x150
0x1502mo ago
The Object class provides an equals(Object) method that can be used to test for equality. To do that, one can override that method and write code for equality checks. If two objects are considered equal, firstObject.equals(secondObject) should return true, else it should return false. When overriding equals, one should make sure that a.equals(b) gives the same result as b.equals(a) (assuming that neither a nor b are null) and always also override hashCode and make sure that the hashCode() result is the same for all objects a and b where a.equals(b) is true.
public final class SomeClass{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}
}
public final class SomeClass{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}
}
SomeClass instance = new SomeClass("Hi", 1337);
System.out.println(instance.equals(new SomeClass("Hi", 1337)));//true
System.out.println(instance.equals(new SomeClass("Hi", 1338)));//false
System.out.println(instance.equals(new SomeClass("Ho", 1337)));//false
SomeClass instance = new SomeClass("Hi", 1337);
System.out.println(instance.equals(new SomeClass("Hi", 1337)));//true
System.out.println(instance.equals(new SomeClass("Hi", 1338)));//false
System.out.println(instance.equals(new SomeClass("Ho", 1337)));//false
The methods equals(Object) and hashCode() are used by many classes in the JDK for comparing objects, e.g. HashMap.
0x150
0x1502mo ago
Sometimes, it's also necessary to define some sort of order between objects. This can be done using the Comparable interface. A class can mark itself to be comparable to another class by implementing that interface and overriding the compareTo method. If firstObject and secondObject are equal (by the equals(Object) method), firstObject.compareTo(secondObject) as well as secondObject.compareTo(firstObject) should return 0. If firstObject is considered to be greater than secondObject, then firstObject.compareTo(secondObject) should return a value greater than 0 and secondObject.compareTo(firstObject) should return a value smaller than 0.
public final class SomeClass implements Comparable<SomeClass>{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}

@Override
public int compareTo(SomeClass other){
Objects.requireNonNull(other);
int someStringResult = someString.compareTo(other.someString);
if(someStringResult != 0){
return someStringResult;
}
return Integer.compare(someInt, other.someInt);
}
}
public final class SomeClass implements Comparable<SomeClass>{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}

@Override
public int compareTo(SomeClass other){
Objects.requireNonNull(other);
int someStringResult = someString.compareTo(other.someString);
if(someStringResult != 0){
return someStringResult;
}
return Integer.compare(someInt, other.someInt);
}
}
📖 Sample answer from dan1st
0x150
0x1502mo ago
Enums are classes where all instances of the class are known at compile-time. An enum can be declared using the enum keyword with a list of all enum constants (list of the objects of the enum):
public enum SomeEnum {
FIRST, SECOND, THIRD
}
public enum SomeEnum {
FIRST, SECOND, THIRD
}
After an enum is declared, its instances can be obtained like regular constants and used like other objects:
SomeEnum enumValue = SomeEnum.SECOND;
System.out.println(enumValue);//SECOND
System.out.println(enumValue == SomeEnum.FIRST);//false
System.out.println(enumValue == SomeEnum.SECOND);//true
SomeEnum enumValue = SomeEnum.SECOND;
System.out.println(enumValue);//SECOND
System.out.println(enumValue == SomeEnum.FIRST);//false
System.out.println(enumValue == SomeEnum.SECOND);//true
All enums have an ordinal() method that can be used to get the index of the enum value in the declaration:
System.out.println(SomeEnum.FIRST.ordinal());//0
System.out.println(SomeEnum.SECOND.ordinal());//1
System.out.println(SomeEnum.THIRD.ordinal());//2
System.out.println(SomeEnum.FIRST.ordinal());//0
System.out.println(SomeEnum.SECOND.ordinal());//1
System.out.println(SomeEnum.THIRD.ordinal());//2
Similarly, the static method called values (which is present in every enum) returns an array of all values of that enum in the order of declaration. The value returned by ordinal() is the the index of that enum value in the array:
System.out.println(Arrays.toString(SomeEnum.values()));//[FIRST, SECOND, THIRD]
System.out.println(SomeEnum.values()[SomeEnum.THIRD.ordinal()]);//THIRD
System.out.println(Arrays.toString(SomeEnum.values()));//[FIRST, SECOND, THIRD]
System.out.println(SomeEnum.values()[SomeEnum.THIRD.ordinal()]);//THIRD
Apart from that, there is an implicit static method named valueOf in each enum class that can be used to get an enum value by name:
SomeEnum enumByName = SomeEnum.valueOf("FIRST");
System.out.println(enumByName == SomeEnum.FIRST);//true
SomeEnum enumByName = SomeEnum.valueOf("FIRST");
System.out.println(enumByName == SomeEnum.FIRST);//true
Enums always extend java.lang.Enum and cannot have any subclasses.
0x150
0x1502mo ago
Just like classes, enums can have fields and constructors but the constructors cannot be called except using the enum constants but a constructor must be called in the enum declaration:
public enum Weekday {
MONDAY("MON"), TUESDAY("TUE"), WEDNESDAY("WED"), THURSDAY("THU"), FRIDAY("FRI"),
SATURDAY("SAT"), SUNDAY("SUN");

private final String abbreviation;
private final boolean workday;

private Weekday(String abbreviation, boolean workday){
this.abbreviation = abbreviation;
this.workday = workday;
}

private Weekday(String abbreviation) {
this(abbreviation, true);
}

public boolean isWorkday(){
return workday;
}
public String getAbbreviation(){
return abbreviation;
}
}
public enum Weekday {
MONDAY("MON"), TUESDAY("TUE"), WEDNESDAY("WED"), THURSDAY("THU"), FRIDAY("FRI"),
SATURDAY("SAT"), SUNDAY("SUN");

private final String abbreviation;
private final boolean workday;

private Weekday(String abbreviation, boolean workday){
this.abbreviation = abbreviation;
this.workday = workday;
}

private Weekday(String abbreviation) {
this(abbreviation, true);
}

public boolean isWorkday(){
return workday;
}
public String getAbbreviation(){
return abbreviation;
}
}
Weekday endOfWorkWeek = Weekday.FRIDAY;
System.out.println(endOfWorkWeek.getAbbreviation() + " is workday: "+endOfWorkWeek.isWorkday());//FRI is workday: true

Weekday startOfWeekend = Weekday.SATURDAY;
System.out.println(startOfWeekend.getAbbreviation() + " is workday: "+startOfWeekend.isWorkday());//SAT is workday: false
Weekday endOfWorkWeek = Weekday.FRIDAY;
System.out.println(endOfWorkWeek.getAbbreviation() + " is workday: "+endOfWorkWeek.isWorkday());//FRI is workday: true

Weekday startOfWeekend = Weekday.SATURDAY;
System.out.println(startOfWeekend.getAbbreviation() + " is workday: "+startOfWeekend.isWorkday());//SAT is workday: false
📖 Sample answer from dan1st
0x150
0x1502mo ago
An Enum is a Type of document, like a class or an interface. In this document you can write a number of values that can be use in the code. A code example can be: public enum numbers { ONE, TWO, THREE } And then you can call de enum numbers in youre code and be sure that the only numbers you can use are ONE, TWO and THREE thanks to this enum.... A practical example could be putting the extensions of files that your code accepts...
Submission from arielb0591
0x150
0x1502mo ago
An enum is a special kind of Java class with a fixed set of values. They are similar in function to a regular class with a private constructor and a fixed number of public static final instances. However, enums have some advantages. As an example, compare the following enum....
public enum DaysOfTheWeek {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
public enum DaysOfTheWeek {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
.... with the following regular class....
public class DaysOfTheWeek {
public static final DaysOfTheWeek SUNDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek MONDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek TUESDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek WEDNESDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek THURSDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek FRIDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek SATURDAY = nwe DaysOfTheWeek();

private DaysOfTheWeek() {
}
}
public class DaysOfTheWeek {
public static final DaysOfTheWeek SUNDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek MONDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek TUESDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek WEDNESDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek THURSDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek FRIDAY = new DaysOfTheWeek();
public static final DaysOfTheWeek SATURDAY = nwe DaysOfTheWeek();

private DaysOfTheWeek() {
}
}
First, the enum is more compact, requiring less code to achieve a similar result. The enum's constants must be the first declarations in the class. The last one can be terminated with a semicolon, and then additional members -- including constructors, fields, and methods -- can be added to the enum, just like with any class. The only restriction is that constructors must be private; if the private access modifier is omitted, it will still be implied. Second, enum classes implicitly extend an Enum base class, which provides methods for retrieving the enum value's name and ordinal. The Enum class also implements Comparable and Serializable, so all values of an enum can be compared, sorted, and serialized. Enum also exposes a static method to lookup any enum value by class and name. In addition to that, the compiler will generate a similar static method on each enum. To illustrate that last point, these two method calls are equivalent:
Enum.valueOf(MyEnum.class, "VALUE_1");
MyEnum.valueOf("VALUE_1"); // This method generated by the compiler for MyEnum
Enum.valueOf(MyEnum.class, "VALUE_1");
MyEnum.valueOf("VALUE_1"); // This method generated by the compiler for MyEnum
Finally, the JVM will ensure that no additional instances of the class exist beyond the declared values. In the "regular" DaysOfTheWeek class above, serialization can be used to circumvent the visibility restrictions on the constructor, which would result in instances that are not one of the 7 static final values. However, in the enum class, the JVM treats enum deserialization specially to ensure that the existing instances are returned.
Note that the JVM/JDK also blocks most reflective mechanisms from creating new enum instances. Be warned, though, that there are a couple of arcane mechanisms (notably, the soon-to-be-retired Unsafe class) that can actually break the normal guarantees around enum instances. These should never be used.
0x150
0x1502mo ago
Because of these guarantees, enum instances can be safely compared with == instead of .equals(). They can also be used in switch statements, just like integer values. As of Java 14, they can also be used in switch expressions. Because the number of values is fixed and known at compile time, the cases can be exhaustive, meaning a default block is not required.
⭐ Submission from dangerously_casual

Did you find this page helpful?