Java add enum to enum

Java Enum перечисления с примерами

Enums – это специальный тип, используемый для определения коллекций констант. Точнее, тип перечисления – это особый вид класса Java, который может содержать константы, методы и т. д. Были добавлены в Java 5. Это руководство объясняет, как создавать и использовать их.

Пример Enum

Обратите внимание на ключевое слово enum, которое используется вместо класса или интерфейса. Оно сообщает компилятору, что это определение типа является перечислением.

Вы можете сослаться на константы в перечислении выше, как это:

Обратите внимание, что переменная уровня имеет тип Level, который является типом перечисления, определенным в примере выше. Переменная уровня может принимать одну из констант уровня Level в качестве значения (HIGH, MEDIUM или LOW). В этом случае уровень установлен на HIGH.

В заявлениях if

Поскольку перечисления являются константами, вам часто приходится сравнивать переменную, указывающую на константу перечисления, с возможными константами в типе перечисления:

Level level = . //assign some Level constant to it if( level == Level.HIGH) < >else if( level == Level.MEDIUM) < >else if( level == Level.LOW)

Этот код сравнивает переменную уровня с каждой из возможных констант перечисления в перечислении уровня.

Если одно из значений встречается чаще, чем другие, проверка этого значения в первом операторе if приведет к лучшей производительности, так как выполняется меньше сравнений в среднем. Это не большая разница, если только сравнения не выполняются.

В выражениях

Если ваши типы перечислений содержат много констант, и вам нужно проверить переменную по значениям, как показано в предыдущем разделе, использование оператора переключения switch может быть хорошей идеей:

Level level = . //assign some Level constant to it switch(level)

Замените … на код, который нужно выполнить, если переменная уровня соответствует заданному значению константы уровня. Код может быть простой операцией, вызовом метода и т. д.

Итерации

Вы можете получить массив всех возможных значений типа enum, вызвав его метод static values(). Все типы перечислений получают статический метод values() автоматически компилятором. Вот пример итерации всех значений:

for(Level level : Level.values())

Выполнение этого кода распечатало бы все значения:

Обратите внимание, как распечатываются имена самих констант. Это одна из областей, где перечисления отличаются от статических конечных констант.

toString()

Класс enum автоматически получает метод toString() в классе при компиляции. Он возвращает строковое значение имени данного экземпляра перечисления:

String levelText = Level.HIGH.toString();

Значением переменной levelText после выполнения вышеприведенного оператора будет текст HIGH.

Printing

Если вы печатаете перечисление, вот так:

System.out.println(Level.HIGH);

Затем метод toString() будет вызван и значение, которое будет напечатано, является текстовым именем экземпляра enum. Другими словами, в приведенном выше примере текст HIGH был бы напечатан.

valueOf()

Класс enum автоматически получает статический метод valueOf() в классе при компиляции. Его можно использовать для получения экземпляра класса для данного значения String:

Level level = Level.valueOf("HIGH");

Переменная уровня будет указывать на Level.HIGH после выполнения этой строки.

Читайте также:  Радиус

Fields

Вы можете добавить поля в перечисление. Таким образом, каждое значение константы enum получает их. Значения полей должны быть предоставлены конструктору перечисления при определении констант:

Обратите внимание, что перечисление в приведенном выше примере имеет конструктор, который принимает int. Он устанавливает поле int. Когда постоянные значения перечисления определены, значение int передается в конструктор Java.

Конструктор enum должен быть либо закрытым, либо областью действия пакета (по умолчанию). Вы не можете использовать публичные или защищенные.

Методы

Вы также можете добавлять методы:

public enum Level < HIGH(3), //calls constructor with value 3 MEDIUM(2), //calls constructor with value 2 LOW (1) //calls constructor with value 1 ; // semicolon needed when fields / methods follow private final int levelCode; Level(int levelCode) < this.levelCode = levelCode; >public int getLevelCode() < return this.levelCode; >>

Вы вызываете метод через ссылку на одно из значений констант:

Level level = Level.HIGH; System.out.println(level.getLevelCode());

Этот код выведет значение 3, которое является значением поля levelCode для константы перечисления HIGH.

Вы не ограничены простыми методами получения и установки. Можете создавать методы, которые производят вычисления на основе значений полей константы перечисления. Если поля не объявлены как final, вправе изменить значения полей (хотя это может быть не очень хорошей идеей, учитывая, что перечисления должны быть константами).

Abstract методы

Для класса enum также могут быть абстрактные методы. Если у класса есть абстрактный метод, то каждый экземпляр класса должен его реализовывать:

public enum Level < HIGH< @Override public String asLowerCase() < return HIGH.toString().toLowerCase(); >>, MEDIUM < @Override public String asLowerCase() < return MEDIUM.toString().toLowerCase(); >>, LOW < @Override public String asLowerCase() < return LOW.toString().toLowerCase(); >>; public abstract String asLowerCase(); >

Обратите внимание на объявление абстрактного метода внизу класса enum. Каждый экземпляр enum (каждая константа) определяет собственную реализацию этого метода. Его использование полезно, когда нужна отдельная реализация метода для каждого экземпляра перечисления.

Реализация интерфейса

Enum может реализовать интерфейс, если чувствуете, что это имеет смысл в вашей ситуации:

public enum EnumImplementingInterface implements MyInterface < FIRST("First Value"), SECOND("Second Value"); private String description = null; private EnumImplementingInterface(String desc)< this.description = desc; >@Override public String getDescription() < return this.description; >>

Это метод getDescription(), который приходит из интерфейса MyInterface.

Реализация интерфейса с Enum может использоваться для реализации набора различных констант Comparator, которые применяются для сортировки коллекций объектов.

EnumSet

Специальная реализация Java Set под названием EnumSet, которая может хранить перечисления более эффективно, чем стандартные реализации:

EnumSet enumSet = EnumSet.of(Level.HIGH, Level.MEDIUM);

После создания вы можете использовать EnumSet, как и любой другой набор.

EnumMap

Специальная реализация Java Map, которая может использовать экземпляры перечисления в качестве ключей:

EnumMap enumMap = new EnumMap(Level.class); enumMap.put(Level.HIGH , "High level"); enumMap.put(Level.MEDIUM, "Medium level"); enumMap.put(Level.LOW , "Low level"); String levelValue = enumMap.get(Level.HIGH);

Детали

  • Перечисления неявно расширяют класс java.lang.Enum, поэтому типы перечислений не могут расширять другой класс.
  • Если перечисление содержит поля и методы, определение полей и методов должно всегда идти в списке констант в нем. Кроме того, список констант должен заканчиваться точкой с запятой (;).
Читайте также:  Приоритет битовых операций python

Источник

Extend Enums in Java

Extend Enums in Java

This tutorial demonstrates how to extend the enum functionality in Java.

Extend enum in Java

We can consider enum as a kind of compiler magic because, in the byte code, the enum is represented as a class with several static members and is inherited from abstract java.lang.Enum .

It is the reason the enum cannot extend any other class or enum . As we cannot extend enum in Java, it is also impossible for any class to extend an enum . Let’s learn by using the following example code and see what happens.

package delftstack;  enum Cars Audi, BMW, Marcedes>  public class Example extends Cars    public static void main(String. args)    > > 

The code above has an enum named Cars , and class Example is trying to extend it. See output:

/Example.java:5: error: cannot inherit from final Cars public class Example extends Cars   ^ /Example.java:5: error: enum types are not extensible public class Example extends Cars   ^ 2 errors 

As we can see, the class cannot extend the enum . So if it is impossible to extend the enum , can we still extend its functionality?

The functionality can be defined as the implemented methods in the enum . For example, the enum Cars from the above code can declare abstract methods for each member; see the example:

enum Cars   Audi  @Override public void drive()  > >,  BMW  @Override public void drive()  > >,  Mercedes  @Override public void drive()  > >,  ;  public abstract void drive(); > 
  • If the enum belongs to a third-party library or another team, it will not allow to implementation of abstract methods.
  • If it belongs to the module which doesn’t have the dependency required for the drive() method.
  • If the enum is overloaded with other functions and data, it will be unreadable.

There are some solutions provided that can solve these problems and extend the functionality of enum in Java.

Solution 1: Mirror enum in Java

As the name suggests, we need to create another enum with the same data. That new enum will also implement the drive() method, So we have two enums now:

Example Code for enum Cars :

enum Cars   Audi  @Override public void drive()  > >,  BMW  @Override public void drive()  > >,  Mercedes  @Override public void drive()  > >,  ;  public abstract void drive(); > 

Example Code for enum DriveCars :

enum DriveCars   Audi  @Override public void drive()  > >,  BMW  @Override public void drive()  > >,  Mercedes  @Override public void drive()  > >,  ;  public abstract void drive(); > 

The second enum is the mirror of the first one. Now we can use both of these enums by extending the functionality; we need to use built-in enum methods that are name() and valueof() .

See the following example of how to use it:

Cars cars = . DriveCars.valueOf(cars.name()).drive(); 

The above code shows how enum Cars functionality is used in the enum DriveCars . Which means the functionality is extended.

The name() method in the above code is final , which cannot be overridden, and the valueOf method will be generated by the compiler. Both of these methods are a good fit for each other is there is no functional error in the extended operation.

There is one issue with the above code if the enum Cars is changed, the enum DriveCars will not have any idea, and it will cause the failure of the name and valueof trick. To solve this issue, we must let the DriveCars know that its parent mirror is Cars .

For that, we can use a static initializer to compare the DriveCars and Cars , which will throw the exception if both the enums do not match. Here is an example of that from the enumus library:

enum DriveCars   .  static   Mirror.of(Cars.class);  > > 

The utility class will check if both enums match or not. This method will validate the name() and valueOf() trick.

Solution 2: Map enum in Java

If you don’t want to create another enum that holds only one method. In this case, we can use interface instead of the enum ; see the example below:

public interface Driver   void drive(); > 

Now to use this interface Drive with the enum Cars , we can create a mapping between them. Here is the example for the map:

MapCars, Driver> drivers = new EnumMap<>(Cars.class)   put(Audi, new Driver()  @Override public void driver()<>>)  put(BMW, new Driver()  @Override public void driver()<>>)  put(Mercedes, new Driver()  @Override public void driver()<>>) >> 

Now to use them, use this simple piece of code:

The EnumMap used in the code above will guarantee that each enum member will appear only once, but it does not guarantee an entry for each member.

We can check the size of the map is equal to the number of members of enums:

drivers.size() == Cars.values().length 

The enumus library also provides a utility for this case: if the map does not fit the Cars , it will throw the IllegalStateException . Here is the utility:

EnumMapValidator.validateValues(Cars.class, map, "Cars map"); 

Both methods above show how to make enums powerful by extending their functionality. Though it is impossible to directly extend an enum , we can use these tricks to extend their functionalities.

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

Related Article — Java Enum

Источник

Оцените статью