Поиск…


Вступление

Переменные Java (объявленные с использованием ключевого слова enum ) - это сокращенный синтаксис для значительных количеств констант одного класса.

Синтаксис

  • [public / protected / private] enum Enum_name {// Объявить новое перечисление.
  • ENUM_CONSTANT_1 [, ENUM_CONSTANT_2 ...]; // Объявляем константы перечисления. Это должна быть первая строка внутри перечисления и должна быть разделена запятыми, с точкой с запятой в конце.
  • ENUM_CONSTANT_1 (param) [, ENUM_CONSTANT_2 (param) ...]; // Объявлять константы enum с параметрами. Типы параметров должны соответствовать конструктору.
  • ENUM_CONSTANT_1 {...} [, ENUM_CONSTANT_2 {...} ...]; // Объявлять константы enum с переопределенными методами. Это необходимо сделать, если перечисление содержит абстрактные методы; все такие методы должны быть реализованы.
  • ENUM_CONSTANT.name () // Возвращает строку с именем константы перечисления.
  • ENUM_CONSTANT.ordinal () // Возвращает порядковый номер этой константы перечисления, ее позицию в объявлении перечисления, где исходной константе присваивается порядковый номер нуля.
  • Enum_name.values ​​() // Возвращает новый массив (типа Enum_name []), содержащий каждую константу этого перечисления каждый раз, когда он вызывается.
  • Enum_name.valueOf ("ENUM_CONSTANT") // Обратное к ENUM_CONSTANT.name () - возвращает константу перечисления с заданным именем.
  • Enum.valueOf (Enum_name.class, "ENUM_CONSTANT") // Синоним предыдущей: Обратный ENUM_CONSTANT.name () - возвращает константу перечисления с заданным именем.

замечания

ограничения

Enums всегда расширяют java.lang.Enum , поэтому невозможно, чтобы enum расширил класс. Однако они могут реализовать множество интерфейсов.

Советы и хитрости

Из-за их специализированного представления есть более эффективные карты и наборы, которые можно использовать с перечислениями в качестве их ключей. Они часто будут работать быстрее, чем их неспециализированные коллеги.

Объявление и использование базового перечисления

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

Простые перечисления для перечисления разных сезонов будут объявлены следующим образом:

public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

Хотя константы перечисления необязательно должны быть во всех шапках, это Java-соглашение, что имена констант полностью заглавные, со словами, разделенными символами подчеркивания.


Вы можете объявить Enum в собственном файле:

/**
 * This enum is declared in the Season.java file.
*/
public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

Но вы также можете объявить его в другом классе:

 public class Day {

    private Season season;

    public String getSeason() {
        return season.name();
    }

    public void setSeason(String season) {
        this.season = Season.valueOf(season);
    }

    /**
     * This enum is declared inside the Day.java file and 
     * cannot be accessed outside because it's declared as private.
     */
    private enum Season {
        WINTER,
        SPRING,
        SUMMER,
        FALL
    }

}

Наконец, вы не можете объявить Enum внутри тела метода или конструктора:

public class Day {

    /**
     * Constructor
    */
    public Day() {
        // Illegal. Compilation error
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }
    }

    public void aSimpleMethod() {
        // Legal. You can declare a primitive (or an Object) inside a method. Compile!
        int primitiveInt = 42;

        // Illegal. Compilation error.
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }

        Season season = Season.SPRING;
    }
    
}

Дублирующие константы перечисления не допускаются:

public enum Season {
    WINTER,
    WINTER, //Compile Time Error : Duplicate Constants
    SPRING,
    SUMMER,
    FALL
} 

Каждая константа enum является public , static и final по умолчанию. Поскольку каждая константа static , к ней можно получить доступ напрямую, используя имя перечисления.

Константы Enum могут передаваться как параметры метода:

public static void display(Season s) {
    System.out.println(s.name());  // name() is a built-in method that gets the exact name of the enum constant
}

display(Season.WINTER);  // Prints out "WINTER"

Вы можете получить массив констант перечисления, используя метод values() . Значения гарантированно будут в порядке объявления в возвращаемом массиве:

Season[] seasons = Season.values();

Примечание. Этот метод выделяет новый массив значений каждый раз, когда он вызывается.


Чтобы перебрать константы перечисления:

public static void enumIterate() {
    for (Season s : Season.values()) {
        System.out.println(s.name());
    }
}

Вы можете использовать перечисления в инструкции switch :

public static void enumSwitchExample(Season s) {
    switch(s) {
        case WINTER:
            System.out.println("It's pretty cold");
            break;
        case SPRING:
            System.out.println("It's warming up");
            break;
        case SUMMER:
            System.out.println("It's pretty hot");
            break;
        case FALL:
            System.out.println("It's cooling down");
            break;
    }
}

Вы также можете сравнить константы enum, используя == :

Season.FALL == Season.WINTER    // false
Season.SPRING == Season.SPRING  // true

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

Season.FALL.equals(Season.FALL); // true
Season.FALL.equals(Season.WINTER); // false
Season.FALL.equals("FALL"); // false and no compiler error

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

public enum MutableExample {
    A,
    B;

    private int count = 0;

    public void increment() {
        count++;
    }

    public void print() {
        System.out.println("The count of " + name() + " is " + count);
    }
}

// Usage:
MutableExample.A.print();       // Outputs 0
MutableExample.A.increment();
MutableExample.A.print();       // Outputs 1 -- we've changed a field   
MutableExample.B.print();       // Outputs 0 -- another instance remains unchanged

Однако хорошая практика состоит в том, чтобы сделать экземпляры enum неизменяемыми, т. Е. Когда у них либо нет каких-либо дополнительных полей, либо все такие поля отмечены как final и неизменяемы. Это гарантирует, что на протяжении всего срока службы enum не будет пропускать какую-либо память и что безопасно использовать его экземпляры во всех потоках.


Enums неявно реализуют Serializable и Comparable потому что класс Enum делает:

public abstract class Enum<E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable

Перечисления с конструкторами

У enum не может быть публичного конструктора; однако частные конструкторы приемлемы (конструкторы для перечислений по умолчанию являются закрытыми по пакетам):

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25); // usual names for US coins
    // note that the above parentheses and the constructor arguments match
    private int value;

    Coin(int value) { 
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

int p = Coin.NICKEL.getValue(); // the int value will be 5

Рекомендуется сохранять все поля частными и предоставлять методы getter, так как существует конечное количество экземпляров для перечисления.


Если бы вы вместо этого выполняли Enum как class , это выглядело бы так:

public class Coin<T extends Coin<T>> implements Comparable<T>, Serializable{
    public static final Coin PENNY = new Coin(1);
    public static final Coin NICKEL = new Coin(5);
    public static final Coin DIME = new Coin(10);
    public static final Coin QUARTER = new Coin(25);

    private int value;

    private Coin(int value){
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

int p = Coin.NICKEL.getValue(); // the int value will be 5

Константы континуума технически изменяемы, поэтому может быть добавлен сеттер для изменения внутренней структуры константы перечисления. Однако это считается очень плохой практикой, и его следует избегать.

Лучшая практика заключается в том, чтобы сделать поля Enum неизменяемыми, с final :

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int value;

    Coin(int value){ 
        this.value = value;
    }

    ...

}

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

public enum Coin {
    PENNY(1, true), NICKEL(5, false), DIME(10), QUARTER(25);

    private final int value;
    private final boolean isCopperColored;

    Coin(int value){
        this(value, false);
    }

    Coin(int value, boolean isCopperColored){ 
        this.value = value;
        this.isCopperColored = isCopperColored;
    }

    ...

}

Примечание. Все не примитивные поля перечисления должны реализовывать Serializable потому что класс Enum делает.

Использование методов и статических блоков

Перечисление может содержать метод, как и любой класс. Чтобы увидеть, как это работает, мы объявим перечисление следующим образом:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;
}

Давайте получим метод, возвращающий перечисление в противоположном направлении:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction getOpposite(){
        switch (this){
            case NORTH:
                return SOUTH;               
            case SOUTH:
                return NORTH;                
            case WEST:
                return EAST; 
            case EAST:
                return WEST;  
            default: //This will never happen
                return null;
        }
    }
}

Это может быть дополнительно улучшено за счет использования полей и статических блоков инициализатора:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;
    
    private Direction opposite;
    
    public Direction getOpposite(){
        return opposite;
    }
    
    static {
        NORTH.opposite = SOUTH;
        SOUTH.opposite = NORTH;
        WEST.opposite = EAST;
        EAST.opposite = WEST;
    }
}

В этом примере противоположное направление сохраняется в поле частного экземпляра opposite , которое статически инициализируется при первом использовании Direction . В этом конкретном случае (поскольку NORTH ссылается на SOUTH и наоборот), мы не можем использовать Enums с конструкторами здесь (конструкторы NORTH(SOUTH), SOUTH(NORTH), EAST(WEST), WEST(EAST) были бы более изящными и позволяли бы opposite будут объявлены final , но будут самореферентными и, следовательно, не разрешены).

Осуществляет интерфейс

Это enum , которое также является вызываемой функцией, которая проверяет входные данные String против предварительно скомпилированных шаблонов регулярных выражений.

import java.util.function.Predicate;
import java.util.regex.Pattern;

enum RegEx implements Predicate<String> {
    UPPER("[A-Z]+"), LOWER("[a-z]+"), NUMERIC("[+-]?[0-9]+");

    private final Pattern pattern;

    private RegEx(final String pattern) {
        this.pattern = Pattern.compile(pattern);
    }

    @Override 
    public boolean test(final String input) {
        return this.pattern.matcher(input).matches();
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(RegEx.UPPER.test("ABC"));
        System.out.println(RegEx.LOWER.test("abc"));
        System.out.println(RegEx.NUMERIC.test("+111"));
    }
}

Каждый член перечисления может также реализовать метод:

import java.util.function.Predicate;

enum Acceptor implements Predicate<String> {
    NULL {
        @Override
        public boolean test(String s) { return s == null; }
    },
    EMPTY {
        @Override
        public boolean test(String s) { return s.equals(""); }
    },
    NULL_OR_EMPTY {
        @Override
        public boolean test(String s) { return NULL.test(s) || EMPTY.test(s); }
    };
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Acceptor.NULL.test(null));  // true
        System.out.println(Acceptor.EMPTY.test(""));   // true
        System.out.println(Acceptor.NULL_OR_EMPTY.test(" ")); // false
    }
}

Образец полиморфизма Enum

Когда метод должен принимать «расширяемый» набор значений enum , программист может применять полиморфизм, как в обычном class путем создания интерфейса, который будет использоваться любым, где будут использоваться enum :

public interface ExtensibleEnum {
    String name();
}

Таким образом, любое enum помеченное (реализующим) интерфейс, может использоваться как параметр, позволяющий программисту создавать переменную сумму enum которая будет принята методом. Это может быть полезно, например, в API , где есть (неизменяемый) по умолчанию enum и пользователь этих API , хотят «продлить» на enum с большим количеством значений.

Набор значений enum по умолчанию можно определить следующим образом:

public enum DefaultValues implements ExtensibleEnum {
    VALUE_ONE, VALUE_TWO;
}

Дополнительные значения затем могут быть определены следующим образом:

public enum ExtendedValues implements ExtensibleEnum {
    VALUE_THREE, VALUE_FOUR;
}

Пример, который показывает, как использовать перечисления - обратите внимание, как printEnum() принимает значения из обоих типов enum :

private void printEnum(ExtensibleEnum val) {
    System.out.println(val.name());
}  

printEnum(DefaultValues.VALUE_ONE);    // VALUE_ONE
printEnum(DefaultValues.VALUE_TWO);    // VALUE_TWO
printEnum(ExtendedValues.VALUE_THREE); // VALUE_THREE
printEnum(ExtendedValues.VALUE_FOUR);  // VALUE_FOUR

Примечание. Этот шаблон не мешает вам переопределять значения перечисления, которые уже определены в одном перечислении, в другом перечислении. Тогда эти значения перечисления будут разными. Кроме того, невозможно использовать switch-on-enum, поскольку все, что у нас есть, это интерфейс, а не реальное enum .

Перечисления с абстрактными методами

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

enum Action {
    DODGE {
        public boolean execute(Player player) {
            return player.isAttacking();
        }
    },
    ATTACK {
        public boolean execute(Player player) {
            return player.hasWeapon();
        }
    },
    JUMP {
        public boolean execute(Player player) {
            return player.getCoordinates().equals(new Coordinates(0, 0));
        }
    };

    public abstract boolean execute(Player player);
}

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

Обратите внимание, что этот шаблон является короткой формой того, что обычно достигается с использованием полиморфизма и / или реализации интерфейсов.

Документирование перечислений

Не всегда имя enum достаточно понятно для понимания. Чтобы зарегистрировать enum , используйте стандартный javadoc:

/**
 * United States coins
 */
public enum Coins {
    
    /**
     * One-cent coin, commonly known as a penny, 
     * is a unit of currency equaling one-hundredth 
     * of a United States dollar
     */
    PENNY(1),

    /**
     * A nickel is a five-cent coin equaling 
     * five-hundredth of a United States dollar
     */        
    NICKEL(5),

    /**
     * The dime is a ten-cent coin refers to 
     * one tenth of a United States dollar
     */        
    DIME(10),

    /**
     * The quarter is a US coin worth 25 cents, 
     * one-fourth of a United States dollar
     */        
    QUARTER(25);

    private int value;

    Coins(int value){ 
        this.value = value;
    }

    public int getValue(){
        return value;
    }
}

Получение значений перечисления

Каждый класс перечисления содержит неявный статический метод с именем values() . Этот метод возвращает массив, содержащий все значения этого перечисления. Вы можете использовать этот метод для перебора значений. Однако важно отметить, что этот метод возвращает новый массив каждый раз, когда он вызывается.

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    
    /**
    * Print out all the values in this enum.
    */
    public static void printAllDays() {
        for(Day day : Day.values()) {
            System.out.println(day.name());
        }
    }
}

Если вам нужен Set вы также можете использовать EnumSet.allOf(Day.class) .

Enum как параметр ограниченного типа

При написании класса с дженериками в java можно гарантировать, что параметр type является перечислением. Поскольку все перечисления расширяют класс Enum , может использоваться следующий синтаксис.

public class Holder<T extends Enum<T>> {
    public final T value;

    public Holder(T init) {
        this.value = init;
    }
}

В этом примере тип T должен быть перечислением.

Получить перечисление по имени

Скажем, у нас есть перечисление DayOfWeek :

enum DayOfWeek {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}

Перечисление компилируется со встроенным статическим методом valueOf() который может использоваться для поиска константы по ее имени:

String dayName = DayOfWeek.SUNDAY.name();
assert dayName.equals("SUNDAY");

DayOfWeek day = DayOfWeek.valueOf(dayName);
assert day == DayOfWeek.SUNDAY;

Это также возможно с использованием динамического типа перечисления:

Class<DayOfWeek> enumType = DayOfWeek.class;
DayOfWeek day = Enum.valueOf(enumType, "SUNDAY");
assert day == DayOfWeek.SUNDAY;

Оба эти метода valueOf() будут IllegalArgumentException если указанное перечисление не имеет константы с соответствующим именем.

Библиотека Guava предоставляет вспомогательный метод Enums.getIfPresent() который возвращает Guava Optional для устранения явной обработки исключений:

DayOfWeek defaultDay = DayOfWeek.SUNDAY;
DayOfWeek day = Enums.valueOf(DayOfWeek.class, "INVALID").or(defaultDay);
assert day == DayOfWeek.SUNDAY;

Реализовать шаблон Singleton с перечислением из одного элемента

Константы Enum создаются, когда перечисление ссылается в первый раз. Таким образом, это позволяет реализовать шаблон разработки программного обеспечения Singleton с перечислением из одного элемента.

public enum Attendant {

    INSTANCE;

    private Attendant() {
        // perform some initialization routine
    }

    public void sayHello() {
        System.out.println("Hello!");
    }
}


public class Main {

    public static void main(String... args) {
        Attendant.INSTANCE.sayHello();// instantiated at this point
    }
}

Согласно книге «Эффективная Ява» Джошуа Блоха, одноэлементное перечисление - лучший способ реализовать синглтон. Такой подход имеет следующие преимущества:

  • безопасность потока
  • гарантия единого экземпляра
  • серийная сериализация

И, как показано в разделе, реализующем интерфейс, этот синглтон может также реализовывать один или несколько интерфейсов.

Enum со свойствами (полями)

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

Рассмотрим следующий пример:

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int value;

    Coin(int value){
        this.value = value;
    }

    public boolean isGreaterThan(Coin other){
        return this.value > other.value;
    }

}

Здесь мы определили Enum называемый Coin который представляет его значение. С помощью метода isGreaterThan мы можем сравнить два enum s:

Coin penny = Coin.PENNY;
Coin dime = Coin.DIME;

System.out.println(penny.isGreaterThan(dime)); // prints: false
System.out.println(dime.isGreaterThan(penny)); // prints: true

Преобразование перечисления в строку

Иногда вы хотите преобразовать свой enum в String, есть два способа сделать это.

Предположим, что мы имеем:

public enum Fruit {
    APPLE, ORANGE, STRAWBERRY, BANANA, LEMON, GRAPE_FRUIT;
}

Итак, как мы можем конвертировать что-то вроде Fruit.APPLE в "APPLE" ?


Преобразовать с помощью name()

name() - это внутренний метод в enum который возвращает представление String перечисления, возвращаемая String представляет точно, как было определено значение перечисления.

Например:

System.out.println(Fruit.BANANA.name());      // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.name()); // "GRAPE_FRUIT"

Преобразование с помощью команды toString()

toString() по умолчанию переопределяется, чтобы иметь такое же поведение, как name()

Однако toString() скорее всего переопределяется разработчиками, чтобы сделать печать более удобной для пользователя String

Не используйте toString() если вы хотите проверить свой код, name() для этого гораздо более стабильно. Используйте только toString() когда вы собираетесь выводить значение в журналы или stdout или что-то еще

По умолчанию:

System.out.println(Fruit.BANANA.toString());      // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "GRAPE_FRUIT"

Пример переопределения

System.out.println(Fruit.BANANA.toString());      // "Banana"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "Grape Fruit"

Enum постоянное определенное тело

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

Предположим, что три ученика-пианиста - Джон, Бен и Люк - определены в enum имени PianoClass :

    enum PianoClass {
    JOHN, BEN, LUKE;
        public String getSex() {
            return "Male";
        }
        public String getLevel() {
            return "Beginner";
        }
    }

И в один прекрасный день приезжают двое других учеников - Рита и Том - с сексом (Женщина) и уровнем (Промежуточный), которые не соответствуют предыдущим:

    enum PianoClass2 {
    JOHN, BEN, LUKE, RITA, TOM;
        public String getSex() {
            return "Male"; // issue, Rita is a female
        }
        public String getLevel() {
            return "Beginner"; // issue, Tom is an intermediate student
        }
    }

так что просто добавление новых учеников в объявление констант, как указано ниже, неверно:

PianoClass2 tom = PianoClass2.TOM;
PianoClass2 rita = PianoClass2.RITA;
System.out.println(tom.getLevel()); // prints Beginner -> wrong Tom's not a beginner
System.out.println(rita.getSex()); // prints Male -> wrong Rita's not a male

Можно определить конкретное поведение для каждой из констант, Rita и Tom, которая переопределяет поведение PianoClass2 умолчанию следующим образом:

enum PianoClass3 {
    JOHN, BEN, LUKE,
    RITA {
        @Override
        public String getSex() {
            return "Female";
        }
    },
    TOM {
        @Override
        public String getLevel() {
            return "Intermediate";
        }
    };
    public String getSex() {
        return "Male";
    }
    public String getLevel() {
        return "Beginner";
    }
}

и теперь уровень Тома и секс Риты такие, какими они должны быть:

PianoClass3 tom = PianoClass3.TOM;
PianoClass3 rita = PianoClass3.RITA;
System.out.println(tom.getLevel()); // prints Intermediate
System.out.println(rita.getSex()); // prints Female

Другой способ определить тело, специфичное для контента, - это использовать конструктор, например:

enum Friend {
    MAT("Male"),
    JOHN("Male"),
    JANE("Female");
    
    private String gender;

    Friend(String gender) {
        this.gender = gender;
    }

    public String getGender() {
        return this.gender;
    }
}

и использование:

Friend mat = Friend.MAT;
Friend john = Friend.JOHN;
Friend jane = Friend.JANE;
System.out.println(mat.getGender());     // Male
System.out.println(john.getGender());    // Male
System.out.println(jane.getGender());    // Female

Нумерация нулевого экземпляра

enum Util {
    /* No instances */;

    public static int clamp(int min, int max, int i) {
        return Math.min(Math.max(i, min), max);
    }

    // other utility methods...
}

Так же, как enum может использоваться для одиночных игр (1 класс экземпляров), его можно использовать для служебных классов (0 классов экземпляров). Просто убедитесь, что завершили (пустой) список констант перечисления с помощью ; ,

См. Вопрос Zune enum vs private constructors для предотвращения создания экземпляра для обсуждения pro и con по сравнению с частными конструкторами.

Перечисления со статическими полями

Если у вашего класса enum есть статические поля, имейте в виду, что они создаются после самих значений перечисления. Это означает, что следующий код приведет к NullPointerException :

enum Example {
    ONE(1), TWO(2);

    static Map<String, Integer> integers = new HashMap<>();

    private Example(int value) {
        integers.put(this.name(), value);
    }
}

Возможный способ исправить это:

enum Example {
    ONE(1), TWO(2);

    static Map<String, Integer> integers;

    private Example(int value) {
        putValue(this.name(), value);
    }

    private static void putValue(String name, int value) {
        if (integers == null)
            integers = new HashMap<>();
        integers.put(name, value);
    }
}

Не инициализируйте статическое поле:

enum Example {
    ONE(1), TWO(2);

    // after initialisisation integers is null!!
    static Map<String, Integer> integers = null;

    private Example(int value) {
        putValue(this.name(), value);
    }

    private static void putValue(String name, int value) {
        if (integers == null)
            integers = new HashMap<>();
        integers.put(name, value);
    }
    // !!this may lead to null poiner exception!!
    public int getValue(){
        return (Example.integers.get(this.name()));
    }
}

initialisisation:

  • создавать значения перечисления
    • как побочный эффект putValue (), который инициализирует целые числа
  • статические значения установлены
    • integers = null; // выполняется после перечислений, поэтому содержимое целых чисел теряется

Сравнить и Содержит для значений Enum

Перечисления содержат только константы и могут быть непосредственно сопоставлены с == . Итак, нужна только проверка ссылок, нет необходимости использовать метод .equals . Более того, если .equals используются неправильно, может вызвать .equals NullPointerException то время как это не относится к проверке == .

enum Day {
    GOOD, AVERAGE, WORST;
}

public class Test {

    public static void main(String[] args) {
        Day day = null;

        if (day.equals(Day.GOOD)) {//NullPointerException!
            System.out.println("Good Day!");
        }

        if (day == Day.GOOD) {//Always use == to compare enum
            System.out.println("Good Day!");
        }

    }
}

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

  • EnumSet#range : для получения подмножества перечисления по диапазону, определяемому двумя конечными точками

  • EnumSet#of : набор конкретных перечислений без какого-либо диапазона. Многократное перегружен of методов есть.

  • EnumSet#complementOf : набор перечислений, который является дополнением к значениям перечисления, указанным в параметре метода

    enum Page {
       A1, A2, A3, A4, A5, A6, A7, A8, A9, A10
    }
    
    public class Test {
    
      public static void main(String[] args) {
          EnumSet<Page> range = EnumSet.range(Page.A1, Page.A5);
    
          if (range.contains(Page.A4)) {
              System.out.println("Range contains A4");
          }
    
          EnumSet<Page> of = EnumSet.of(Page.A1, Page.A5, Page.A3);
    
          if (of.contains(Page.A1)) {
              System.out.println("Of contains A1");
          }
      }
    }
    


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow