- Java Enums
- Example
- Enum inside a Class
- Example
- Enum in a Switch Statement
- Example
- Loop Through an Enum
- Example
- Difference between Enums and Classes
- Why And When To Use Enums?
- Java enum example
- 1. Basic Enum
- 2. Enum + Instance field
- 3. Enum + Method + Some logic
- 4. How to use Enum
- References
- Comments
- Enums
- Java enum for example
Java Enums
An enum is a special «class» that represents a group of constants (unchangeable variables, like final variables).
To create an enum , use the enum keyword (instead of class or interface), and separate the constants with a comma. Note that they should be in uppercase letters:
Example
You can access enum constants with the dot syntax:
Enum is short for «enumerations», which means «specifically listed».
Enum inside a Class
You can also have an enum inside a class:
Example
public class Main < enum Level < LOW, MEDIUM, HIGH >public static void main(String[] args) < Level myVar = Level.MEDIUM; System.out.println(myVar); >>
Enum in a Switch Statement
Enums are often used in switch statements to check for corresponding values:
Example
enum Level < LOW, MEDIUM, HIGH >public class Main < public static void main(String[] args) < Level myVar = Level.MEDIUM; switch(myVar) < case LOW: System.out.println("Low level"); break; case MEDIUM: System.out.println("Medium level"); break; case HIGH: System.out.println("High level"); break; >> >
Loop Through an Enum
The enum type has a values() method, which returns an array of all enum constants. This method is useful when you want to loop through the constants of an enum:
Example
for (Level myVar : Level.values())
Difference between Enums and Classes
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).
Why And When To Use Enums?
Use enums when you have values that you know aren’t going to change, like month days, days, colors, deck of cards, etc.
Java enum example
Some of the Java enum examples, and how to use it, nothing special, just for self-reference.
Note
Consider the Enum type if your program consists of a fixed set of constants, like seasons of the year, operations calculator, user status and etc.
1. Basic Enum
2. Enum + Instance field
public enum WhoisRIR < ARIN("whois.arin.net"), RIPE("whois.ripe.net"), APNIC("whois.apnic.net"), AFRINIC("whois.afrinic.net"), LACNIC("whois.lacnic.net"), JPNIC("whois.nic.ad.jp"), KRNIC("whois.nic.or.kr"), CNNIC("ipwhois.cnnic.cn"), UNKNOWN(""); private String url; WhoisRIR(String url) < this.url = url; >public String url() < return url; >>
3. Enum + Method + Some logic
4. How to use Enum
PENDING ACTIVE INACTIVE DELETED
4.2 To compare the Enum values, use == operator.
This is APNIC : whois.apnic.net
4.2 Convert a String to Enum object.
References
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.
Comments
First of all, thank you for posting these example.It helped me to understand how I can use ‘ENUM’ in an application.
However, doing more practice on Enum , I noticed that – I get Compile time error when I declare constructor before declaring Enum constants.
Could you please justify why did it happen ?
Enums
In 5.0, the Java™ programming language gets linguistic support for enumerated types. In their simplest form, these enums look just like their C, C++, and C# counterparts:
But appearances can be deceiving. Java programming language enums are far more powerful than their counterparts in other languages, which are little more than glorified integers. The new enum declaration defines a full-fledged class (dubbed an enum type). In addition to solving all the problems mentioned above, it allows you to add arbitrary methods and fields to an enum type, to implement arbitrary interfaces, and more. Enum types provide high-quality implementations of all the Object methods. They are Comparable and Serializable, and the serial form is designed to withstand arbitrary changes in the enum type.
Here is an example of a playing card class built atop a couple of simple enum types. The Card class is immutable, and only one instance of each Card is created, so it need not override equals or hashCode :
import java.util.*; public class Card < public enum Rank public enum Suit private final Rank rank; private final Suit suit; private Card(Rank rank, Suit suit) < this.rank = rank; this.suit = suit; >public Rank rank() < return rank; >public Suit suit() < return suit; >public String toString() < return rank + " of " + suit; >private static final List protoDeck = new ArrayList(); // Initialize prototype deck static < for (Suit suit : Suit.values()) for (Rank rank : Rank.values()) protoDeck.add(new Card(rank, suit)); >public static ArrayList newDeck() < return new ArrayList(protoDeck); // Return copy of prototype deck > >
The toString method for Card takes advantage of the toString methods for Rank and Suit . Note that the Card class is short (about 25 lines of code). If the typesafe enums ( Rank and Suit ) had been built by hand, each of them would have been significantly longer than the entire Card class.
The (private) constructor of Card takes two parameters, a Rank and a Suit . If you accidentally invoke the constructor with the parameters reversed, the compiler will politely inform you of your error. Contrast this to the int enum pattern, in which the program would fail at run time.
Note that each enum type has a static values method that returns an array containing all of the values of the enum type in the order they are declared. This method is commonly used in combination with the for-each loop to iterate over the values of an enumerated type.
The following example is a simple program called Deal that exercises Card . It reads two numbers from the command line, representing the number of hands to deal and the number of cards per hand. Then it creates a new deck of cards, shuffles it, and deals and prints the requested hands.
import java.util.*; public class Deal < public static void main(String args[]) < int numHands = Integer.parseInt(args[0]); int cardsPerHand = Integer.parseInt(args[1]); Listdeck = Card.newDeck(); Collections.shuffle(deck); for (int i=0; i < numHands; i++) System.out.println(deal(deck, cardsPerHand)); >public static ArrayList deal(List deck, int n) < int deckSize = deck.size(); ListhandView = deck.subList(deckSize-n, deckSize); ArrayList hand = new ArrayList(handView); handView.clear(); return hand; > > $ java Deal 4 5 [FOUR of HEARTS, NINE of DIAMONDS, QUEEN of SPADES, ACE of SPADES, NINE of SPADES] [DEUCE of HEARTS, EIGHT of SPADES, JACK of DIAMONDS, TEN of CLUBS, SEVEN of SPADES] [FIVE of HEARTS, FOUR of DIAMONDS, SIX of DIAMONDS, NINE of CLUBS, JACK of CLUBS] [SEVEN of HEARTS, SIX of CLUBS, DEUCE of DIAMONDS, THREE of SPADES, EIGHT of CLUBS]
Suppose you want to add data and behavior to an enum. For example consider the planets of the solar system. Each planet knows its mass and radius, and can calculate its surface gravity and the weight of an object on the planet. Here is how it looks:
public enum Planet < MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7), PLUTO (1.27e+22, 1.137e6); private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius) < this.mass = mass; this.radius = radius; >public double mass() < return mass; >public double radius() < return radius; >// universal gravitational constant (m3 kg-1 s-2) public static final double G = 6.67300E-11; public double surfaceGravity() < return G * mass / (radius * radius); >public double surfaceWeight(double otherMass) < return otherMass * surfaceGravity(); >>
The enum type Planet contains a constructor, and each enum constant is declared with parameters to be passed to the constructor when it is created.
Here is a sample program that takes your weight on earth (in any unit) and calculates and prints your weight on all of the planets (in the same unit):
public static void main(String[] args) < double earthWeight = Double.parseDouble(args[0]); double mass = earthWeight/EARTH.surfaceGravity(); for (Planet p : Planet.values()) System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass)); >$ java Planet 175 Your weight on MERCURY is 66.107583 Your weight on VENUS is 158.374842 Your weight on EARTH is 175.000000 Your weight on MARS is 66.279007 Your weight on JUPITER is 442.847567 Your weight on SATURN is 186.552719 Your weight on URANUS is 158.397260 Your weight on NEPTUNE is 199.207413 Your weight on PLUTO is 11.703031
The idea of adding behavior to enum constants can be taken one step further. You can give each enum constant a different behavior for some method. One way to do this by switching on the enumeration constant. Here is an example with an enum whose constants represent the four basic arithmetic operations, and whose eval method performs the operation:
public enum Operation < PLUS, MINUS, TIMES, DIVIDE; // Do arithmetic op represented by this constant double eval(double x, double y)< switch(this) < case PLUS: return x + y; case MINUS: return x - y; case TIMES: return x * y; case DIVIDE: return x / y; >throw new AssertionError("Unknown op: " + this); > >
This works fine, but it will not compile without the throw statement, which is not terribly pretty. Worse, you must remember to add a new case to the switch statement each time you add a new constant to Operation. If you forget, the eval method with fail, executing the aforementioned throw statement
There is another way give each enum constant a different behavior for some method that avoids these problems. You can declare the method abstract in the enum type and override it with a concrete method in each constant. Such methods are known as constant-specific methods. Here is the previous example redone using this technique:
public enum Operation < PLUS < double eval(double x, double y) < return x + y; >>, MINUS < double eval(double x, double y) < return x - y; >>, TIMES < double eval(double x, double y) < return x * y; >>, DIVIDE < double eval(double x, double y) < return x / y; >>; // Do arithmetic op represented by this constant abstract double eval(double x, double y); >
Here is a sample program that exercises the Operation class. It takes two operands from the command line, iterates over all the operations, and for each operation, performs the operation and prints the resulting equation:
public static void main(String args[]) < double x = Double.parseDouble(args[0]); double y = Double.parseDouble(args[1]); for (Operation op : Operation.values()) System.out.printf("%f %s %f = %f%n", x, op, y, op.eval(x, y)); >$ java Operation 4 2 4.000000 PLUS 2.000000 = 6.000000 4.000000 MINUS 2.000000 = 2.000000 4.000000 TIMES 2.000000 = 8.000000 4.000000 DIVIDE 2.000000 = 2.000000
Constant-specific methods are reasonably sophisticated, and many programmers will never need to use them, but it is nice to know that they are there if you need them.
Two classes have been added to java.util in support of enums: special-purpose Set and Map implementations called EnumSet and EnumMap . EnumSet is a high-performance Set implementation for enums. All of the members of an enum set must be of the same enum type. Internally, it is represented by a bit-vector, typically a single long . Enum sets support iteration over ranges of enum types. For example given the following enum declaration:
for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY)) System.out.println(d);
EnumSet.of(Style.BOLD, Style.ITALIC)
Similarly, EnumMap is a high-performance Map implementation for use with enum keys, internally implemented as an array. Enum maps combine the richness and safety of the Map interface with speed approaching that of an array. If you want to map an enum to a value, you should always use an EnumMap in preference to an array.
The Card class, above, contains a static factory that returns a deck, but there is no way to get an individual card from its rank and suit. Merely exposing the constructor would destroy the singleton property (that only a single instance of each card is allowed to exist). Here is how to write a static factory that preserves the singleton property, using a nested EnumMap:
private static Map> table = new EnumMap>(Suit.class); static < for (Suit suit : Suit.values()) < MapsuitTable = new EnumMap(Rank.class); for (Rank rank : Rank.values()) suitTable.put(rank, new Card(rank, suit)); table.put(suit, suitTable); > > public static Card valueOf(Rank rank, Suit suit)
The EnumMap ( table ) maps each suit to an EnumMap that maps each rank to a card. The lookup performed by the valueOf method is internally implemented as two array accesses, but the code is much clearer and safer. In order to preserve the singleton property, it is imperative that the constructor invocation in the prototype deck initialization in Card be replaced by a call to the new static factory:
// Initialize prototype deck static < for (Suit suit : Suit.values()) for (Rank rank : Rank.values()) protoDeck.add(Card.valueOf(rank, suit)); >
It is also imperative that the initialization of table be placed above the initialization of protoDeck, as the latter depends on the former.
So when should you use enums? Any time you need a fixed set of constants. That includes natural enumerated types (like the planets, days of the week, and suits in a card deck) as well as other sets where you know all possible values at compile time, such as choices on a menu, rounding modes, command line flags, and the like. It is not necessary that the set of constants in an enum type stay fixed for all time. The feature was specifically designed to allow for binary compatible evolution of enum types.
Java enum for example
* Информация для продвинутых юзеров. На самом деле возможно ограниченное наследование от Enum. Подробнее здесь: https://kibungo.livejournal.com/19999.html Пример наследования и переопределения общего метода:
public enum MyEnum < VAL1 < public int returnMyVal()< return 20; >>, VAL2; public int returnMyVal() < return 10; >> ------------------------ System.out.println(MyEnum.VAL1.returnMyVal()) // 20 System.out.println(MyEnum.VAL2.returnMyVal()) // 10
«По сравнению с обычными классами, на Enum наложили одно серьезное ограничение — от него невозможно наследоваться.» Что за бред вы пишете?! Все перечисления изначально неявно расширяют класс java.lang.Enum, а поскольку в Java нету множественного наследования, то и расширять enum уже больше ничего не может.
В статье enum в коде с маленькой буквы, в комментариях к коду — Enum с большой Почему не говорится, что это разные вещи? Если у нас несколько enum`ов с перечислениями в приложении и нам нужно передать один из них как аргумент в метод можно сделать просто так someMethod(Enum e) < и здесь написать условие для выбора одного из enum`ов >Т.е. не нужно приводить все enum`ы к единому интерфейсу или абстрактному классу, чтобы выбрать один из enum`ов Как я понял Enum(тот который с большой буквы) — это что-то типа пустого интерфейса для всех enum`ов
@Override public String toString() < return "DayOfWeek';
В коде приведенного примера про школьника есть ошибка: задано поле private ScholarSchedule schedule, но сеттер для него не прописан, а так как оно изначально не инициализировано, получаете NullPointerException. Добавьте сеттер (либо просто сделайте это поле public, что есть костыль) для задания значения:
public void setSchedule(ScholarSchedule schedule)
Ну или, в конце концов, поместите метод main в класс Scholar (видимо так и задумывалось автором примера изначально), тогда он будет иметь доступ к private ScholarSchedule schedule и сможет инициализировать его надлежащим образом.