Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Enums in Java

Tags:

What are java enums? How do they work? Where could I used them and how?
Can I do without using enums in an app or are they so powerful that Its better to use them than ignore them?

like image 1000
Kevin Boyd Avatar asked Sep 14 '09 05:09

Kevin Boyd


People also ask

What is the point of Java enums?

The main objective of enum is to define our own data types(Enumerated Data Types). Declaration of enum in Java: Enum declaration can be done outside a Class or inside a Class but not inside a Method.

Why is enum 4 bytes?

The size is four bytes because the enum is stored as an int . With only 12 values, you really only need 4 bits, but 32 bit machines process 32 bit quantities more efficiently than smaller quantities.

Do Java enums start at 0 or 1?

enum starts always with 0.

Can you use == on enums?

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant.


2 Answers

Enums in Java 5+ are basically classes that have a predefined set of instances. They are intended as a replacement for, say, a collection of integer constants. They are preferably to constants as they can enforce type safety.

So instead of:

public class Suit {
  public final static int SPADES = 1;
  public final static int CLUBS = 2
  public final static int HEARTS = 3;
  public final static int DIAMONDS = 4;
}

you have:

public enum Suit {
  SPADES, CLUBS, HEARTS, DIAMONDS
}

The advantages are:

  1. Type safety. You can declare a function argument, return type, class member or local variable to be a particular Enum type and the compiler will enforce type safety;
  2. Enums are basically classes. They can implement interfaces, have behaviour and so on.

The type safety is an issue because in the first example, these are valid statements:

int i = Suit.DIAMONDS * Suit.CLUBS;

or you can pass in 11 to a function expecting a suit. You can't do that with a typesafe enum.

You can use a class for Suit to provide type safety and this was the solution before Java 5. Josh Bloch (in Effective Java, which is a must read for Java programmers imho) promoted the typesafe enum pattern that became the Java 5+ enum. It has a fair amount of boilerplate on it and some corner cases that people didn't tend to cater for, such as serialization not calling a constructor and to ensure you only got one instance you had to override the readResolve() method.

For example:

public enum CardColour {
  RED, BLACK
}

public enum Suit {
  SPADES(CardColour.BLACK),
  CLUBS(CardColour.BLACK),
  HEARTS(CardColour.RED),
  DIAMONDS(CardColour.RED);

  private final CardColour colour;

  Suit(CardColour colour) { this.colour = colour; }

  public CardColour getColour() { return colour; }
}

Edit: Sun has an introduction to typesafe enums.

As for interfaces, they really complement enums rather than being an alternative. Like you could say that Suit is an interface and you'd have this:

public interface Suit {
  CardColour getColour();
}

The problem is that you could go and define 300 different suits and you could also define Spades several times. Another advantage of enums is (classloading corner cases notwithstanding) is that there is only one instance of each enum value. Typically this is referred to as having a canonical value, meaning this equality holds true:

a.equals(b) == b.equals(a) == (a == b)

for all a, b that are instances of a particular Enum. This means that instead of writing:

if (card.getSuit().equals(Suit.SPADES)) { ... }

you can write:

if (card.getSuit() == Suit.SPADES) { ... }

which is quicker and typically easier to read. Plus IDEs will typically give you feedback if you're comparing enums of different types saying they can't possibly be equal, which can be a useful and early form of error-checking.

like image 61
cletus Avatar answered Oct 14 '22 03:10

cletus


Think of Enum as follows

public class MyEnum {

    // Object instantiated at declaration
    public static final MyEnum ONE = new MyEnum();
    public static final MyEnum TWO = new MyEnum();
    public static final MyEnum THREE = new MyEnum();

    // Notice a private constructor 
    // There is no way outside MyEnum class call it
    private MyEnum() { ... }


}

So a MyEnum as a enum would be

public enum MyEnum {
    ONE,
    TWO,
    THREE;
}

Both are similar

regards,

like image 31
Arthur Ronald Avatar answered Oct 14 '22 03:10

Arthur Ronald