немедленно.

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

Я никогда не пользоваласьenumи я программирую на Java уже более двух лет. И, видимо, они сильно изменились. Теперь они даже полностью поддерживают ООП внутри себя.

Теперь, почему и для чего мне использовать enum в повседневном программировании?
 Andrew Mao25 февр. 2013 г., 22:56
До сих пор нет объяснения синглтон-шаблона enum и почему он безопасен для потоков.
 mbomb00723 дек. 2014 г., 23:02
@bvdb Этот вопрос был задан первым.
 Mat B.19 февр. 2013 г., 23:38
Просто привлекая внимание к вопросу. Я обнаружил, что многие разработчики НЕ используют перечисления там, где они должны, и эта награда - лишь небольшое усилие, чтобы изменить привычки немногих. Падение в видении, но видение сделано из капель, поэтому каждый маленький кусочек имеет значение.
 Hovercraft Full Of Eels17 янв. 2011 г., 02:13
Классический (канонический?) Пример - колода карт. Вы можете использовать перечисление для представления мастей - трефы, бубны, червы, пики и ранг или значение - туз, дуче, три, четыре, ... валет, дама и король, а затем создать класс карты. здесь есть поле «Костюм» и «Ранг».

Ответы на вопрос(23)

Вы можете использовать Enum для представления небольшого фиксированного набора констант или режима внутреннего класса, увеличивая читабельность. Кроме того, Enums может обеспечить определенную жесткость при использовании в параметрах метода. Они предлагают интересную возможность передачи информации конструктору, как вПример планет на сайте Oracle и, как вы обнаружили, также позволяют простой способ создания одноэлементного шаблона.

например:Locale.setDefault(Locale.US) читает лучше чемLocale.setDefault(1) и принудительно использует фиксированный набор значений, отображаемый в IDE при добавлении. разделитель вместо всех целых чисел.

 James P.11 авг. 2018 г., 01:38
@arnt Я тоже исправил грамматику в этом вопросе. Благодарю.

enums так же, как другие классы сConstant поля иprivate constructor.

Например,

public enum Weekday
{
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
} 

Компилятор компилирует это следующим образом;

class Weekday extends Enum
{
  public static final Weekday MONDAY  = new Weekday( "MONDAY",   0 );
  public static final Weekday TUESDAY = new Weekday( "TUESDAY ", 1 );
  public static final Weekday WEDNESDAY= new Weekday( "WEDNESDAY", 2 );
  public static final Weekday THURSDAY= new Weekday( "THURSDAY", 3 );
  public static final Weekday FRIDAY= new Weekday( "FRIDAY", 4 );
  public static final Weekday SATURDAY= new Weekday( "SATURDAY", 5 );
  public static final Weekday SUNDAY= new Weekday( "SUNDAY", 6 );

  private Weekday( String s, int i )
  {
    super( s, i );
  }

  // other methods...
}

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

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

В противном случае вы можете использовать строки, как вы всегда это делали (возможно, вы определили некоторые «соглашения» для своего приложения), и вы будете очень гибкими ... но вы не получите 100% -ную защиту от опечаток в ваших строках, и вы сможете их реализовать только во время выполнения.

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

enums coffeesize{BIG , HUGE , OVERWHELMING }; 
//This semicolon is optional.

Это ограничиваетcoffeesize чтобы либо:BIG , HUGE , или жеOVERWHELMING как переменная.

у Enum есть частный конструктор, доступный только через публичное перечисление:

enum RGB {
    RED("Red"), GREEN("Green"), BLUE("Blue");

    public static final String PREFIX = "color ";

    public String getRGBString() {
        return PREFIX + color;
    }

    String color;

    RGB(String color) {
        this.color = color;
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        String c = RGB.RED.getRGBString();
        System.out.print("Hello " + c);
    }
}

1) Использование в качестве констант вSwitch-case заявление. Переключатель case не позволит вам использовать объекты String для case. Перечисления пригодятся. Больше:http://www.javabeat.net/2009/02/how-to-use-enum-in-switch/

2) РеализацияSingleton Design Pattern - Enum снова, приходит на помощь. Использование здесь:Каков наилучший подход для использования Enum в качестве синглтона в Java?

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

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

Теперь, если вы создаете enum как операцию:

public enum operation {
    create("1")
    delete("2")
    edit("3")
    read("4")

    // You may have is methods here
    public boolean isCreate() {
        return this.equals(create);
    }
    // More methods like the above can be written

}

Теперь вы можете объявить что-то вроде:

private operation currentOperation;

// And assign the value for it 
currentOperation = operation.create

Таким образом, вы можете использовать его по-разному. Всегда хорошо иметь enum для конкретных вещей, так как управление базой данных в приведенном выше примере можно контролировать, проверяяcurrentOperation, Возможно, можно сказать, что это может быть достигнуто с помощью переменных и целочисленных значений. Но я считаю, что Enum - более безопасный и программистский путь.

Другое дело: я думаю, что каждый программист любитлогическийне так ли? Потому что он может хранить только два значения, два конкретных значения. Таким образом, можно думать, что Enum имеет такой же тип средств, где пользователь будет определять, сколько и какой тип значения он будет хранить, просто немного по-другому. :)

я часто нахожу перечисления полезными для реализации шаблона стратегии, следуя некоторым основным рекомендациям ООП:

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

Простейшим примером будет наборComparator реализации:

enum StringComparator implements Comparator<String> {
    NATURAL {
        @Override
        public int compare(String s1, String s2) {
            return s1.compareTo(s2);
        }
    },
    REVERSE {
        @Override
        public int compare(String s1, String s2) {
            return NATURAL.compare(s2, s1);
        }
    },
    LENGTH {
        @Override
        public int compare(String s1, String s2) {
            return new Integer(s1.length()).compareTo(s2.length());
        }
    };
}

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

Я видел, как это успешно применялось для моделирования концепции гранулярности времени (ежедневно, еженедельно и т. Д.), Где вся логика была заключена в перечисление (выбор правильной гранулярности для данного временного диапазона, специфическое поведение, связанное с каждой гранулярностью как константа). методы и т. д.). И все же,Granularity как видно из уровня обслуживания был просто интерфейс.

 Holger14 сент. 2018 г., 12:03
Вы также можете добавитьCASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }, Еще одно преимущество, которое не упомянуто, заключается в том, что вы получаете надежную поддержку сериализации; постоянная форма содержит только имя класса и имя константы, независимо от деталей реализации ваших компараторов.

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

enum ProtocolType {
    TCP_IP (1, "Transmission Control Protocol"), 
    IP (2, "Internet Protocol"), 
    UDP (3, "User Datagram Protocol");

    public int code;
    public String name;

    private ProtocolType(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public static ProtocolType fromInt(int code) {
    switch(code) {
    case 1:
        return TCP_IP;
    case 2:
        return IP;
    case 3:
        return UDP;
    }

    // we had some exception handling for this
    // as the contract for these was between 2 independent applications
    // liable to change between versions (mostly adding new stuff)
    // but keeping it simple here.
    return null;
    }
}

Создайтеenum объект из полученных значений (например, 1,2), используяProtocolType.fromInt(2) Пишите в журналы используяmyEnumObj.name

Надеюсь это поможет.

enum означаетперечислениеЭто упоминание (несколько вещей) по одному.

перечисление тип данных, который содержит фиксированный набор констант

ИЛИ ЖЕ

enum это какclassс фиксированным набором экземпляров, известных во время компиляции.

Например:

public class EnumExample {
    interface SeasonInt {
        String seasonDuration();
    }

    private enum Season implements SeasonInt {
        // except the enum constants remaining code looks same as class
        // enum constants are implicitly public static final we have used all caps to specify them like Constants in Java
        WINTER(88, "DEC - FEB"), SPRING(92, "MAR - JUN"), SUMMER(91, "JUN - AUG"), FALL(90, "SEP - NOV");

        private int days;
        private String months;

        Season(int days, String months) { // note: constructor is by default private 
            this.days = days;
            this.months = months;
        }

        @Override
        public String seasonDuration() {
            return this+" -> "+this.days + "days,   " + this.months+" months";
        }

    }
    public static void main(String[] args) {
        System.out.println(Season.SPRING.seasonDuration());
        for (Season season : Season.values()){
            System.out.println(season.seasonDuration());
        }

    }
}

Преимущества enum:

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

заБольше

это языковая функция, поэтому вы обычно получаете:

Поддержка компилятора (сразу смотрите проблемы с типом)Поддержка инструментов в IDE (автозаполнение в случае переключения ...)

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

Думайте о перечислениях как о типах, заменяющих четко определенный набор int-констант (которые Java «унаследовала» от C / C ++).

КнигаЭффективное Java, 2-е издание имеет целую главу о них и более подробно. Также смэтот пост переполнения стека.

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

public enum Items {
    MESSAGES, CHATS, CITY_ONLINE, FRIENDS, PROFILE, SETTINGS, PEOPLE_SEARCH, CREATE_CHAT
}

@Override
public boolean onCreateOptionsMenu(Menu menuPrm) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menuPrm);
    View itemChooserLcl;
    for (int i = 0; i < menuPrm.size(); i++) {
        MenuItem itemLcl  = menuPrm.getItem(i);
            itemChooserLcl = itemLcl.getActionView();
            if (itemChooserLcl != null) {
                 //here Im marking each View' tag by enume values:
                itemChooserLcl.setTag(Items.values()[i]);
                itemChooserLcl.setOnClickListener(drawerMenuListener);
            }
        }
    return true;
}
private View.OnClickListener drawerMenuListener=new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Items tagLcl= (Items) v.getTag();
        switch (tagLcl){
            case MESSAGES: ;
            break;
            case CHATS : ;
            break;
            case CITY_ONLINE : ;
            break;
            case FRIENDS : ;
            break;
            case  PROFILE: ;
            break;
            case  SETTINGS: ;
            break;
            case  PEOPLE_SEARCH: ;
            break;
            case  CREATE_CHAT: ;
            break;
        }
    }
};

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

Например, торговая система, которая использует Enum для рынков / бирж. Существует множество рынков, и почти наверняка будет много подсистем, которым необходим доступ к этому списку рынков. Каждый раз, когда вы хотите, чтобы новый рынок был добавлен в вашу систему, или если вы хотите удалить рынок, возможно, что все под солнцем придется перестраивать и выпускать.

Лучшим примером будет что-то вроде типа категории продукта. Допустим, ваше программное обеспечение управляет запасами для универмага. Существует множество категорий товаров и множество причин, по которым этот список категорий может измениться. Менеджеры могут захотеть снабдить новой линейкой продуктов, избавиться от других линий продуктов и, возможно, время от времени реорганизовывать категории. Если вам нужно перестроить и заново развернуть все свои системы просто потому, что пользователи хотят добавить категорию продукта, то вы взяли что-то, что должно быть простым и быстрым (добавление категории), и сделали это очень трудным и медленным.

В итоге, перечисления хороши, если данные, которые вы представляете, очень статичны во времени и имеют ограниченное количество зависимостей. Но если данные сильно меняются и имеют много зависимостей, вам нужно что-то динамическое, что не проверяется во время компиляции (например, таблица базы данных).

Object класс и абстрактный классEnum, Таким образом, вы можете использовать его методы для отражения, многопоточности, сериализации, сопоставления и т. Д. Если вы просто объявите статическую константу вместо Enum, вы не сможете. Кроме того, значение Enum может быть передано и на уровень DAO.

Вот пример программы для демонстрации.

public enum State {

    Start("1"),
    Wait("1"),
    Notify("2"),
    NotifyAll("3"),
    Run("4"),
    SystemInatilize("5"),
    VendorInatilize("6"),
    test,
    FrameworkInatilize("7");

    public static State getState(String value) {
        return State.Wait;
    }

    private String value;
    State test;

    private State(String value) {
        this.value = value;
    }

    private State() {
    }

    public String getValue() {
        return value;
    }

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public boolean isNotify() {
        return this.equals(Notify);
    }
}

public class EnumTest {

    State test;

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public State getCurrentState() {
        return test;
    }

    public static void main(String[] args) {
        System.out.println(State.test);
        System.out.println(State.FrameworkInatilize);
        EnumTest test=new EnumTest();
        test.setCurrentState(State.Notify);
        test. stateSwitch();
    }

    public void stateSwitch() {
        switch (getCurrentState()) {
        case Notify:
            System.out.println("Notify");
            System.out.println(test.isNotify());
            break;
        default:
            break;
        }
    }
}

документы -

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

Типичным примером является замена класса набором частных статических конечных констант int (в пределах разумного числа констант) типом enum. По сути, если вы думаете, что знаете все возможные значения «что-то» во время компиляции, вы можете представить это как тип enum. Перечисления обеспечивают читаемость и гибкость над классом с константами.

Несколько других преимуществ, которые я могу придумать для типов enum. Они всегда являются одним экземпляром определенного класса enum (отсюда и концепция использования enum по мере появления синглтона). Другое преимущество заключается в том, что вы можете использовать перечисления в качестве типа в выражении switch-case. Также вы можете использоватьнанизывать() на перечислении, чтобы напечатать их как читаемые строки.

 James P.22 мая 2012 г., 17:08
@marcog Если немного подумать, можно было бы суммировать дни недели и дни каждого месяца в компактном перечислении.
 Basil Bourque10 апр. 2016 г., 09:38
Говоря о днях недели ...DayOfWeek enum теперь предопределен, встроен в Java 8 и позже как частьjava.time рамки (иобратно портированы на Java 6 & 7 а такжена Android).
 CoolBeans17 янв. 2011 г., 02:13
@marcog - LOL - хорошая мысль. Я добавил отказ от ответственности!
 marcog17 янв. 2011 г., 02:10
Вы бы использовали enum для всех 366 дней в году? Это фиксированный набор (366) констант (дни не меняются). Так что это говорит о том, что вы должны. : - / Я бы ограничил размер фиксированного набора.

ения, избегая многократногоif-else при условии, что реализованы некоторые методы.

public enum Mapping {

    ONE("1"),
    TWO("2");

    private String label;

    private Mapping(String label){
        this.label = label;
    }

    public static Mapping by(String label) {

        for(Mapping m: values() {
            if(m.label.equals(label)) return m;
        }

        return null;
    }

}

Так что методby(String label) позволяет получить значение Enumerated не перечисленным. Кроме того, можно изобрести отображение между 2 перечислениями. Можно также попробовать «1 ко многим» или «многие ко многим» в дополнение к «одно к одному» по умолчанию отношение

В конце,enum это класс Java Таким образом, вы можете иметьmain метод внутри него, который может быть полезен при необходимости выполнения некоторых операций отображенияargs немедленно.

ал о них с тех пор, как они были введены в версии 1.5 или версии тигра, как это было отозвано в тот же день. Они никогда не решали «проблему» для меня. Для тех, кто использует это (и я вижу, что многие из них делают), я уверен, что это определенно служитнесколько цель. Просто мои 2 фунта.

имеющий фиксированный набор констант, которые вы определяете сами.

 Duncan Jones24 февр. 2013 г., 15:30
Вы не объяснили, почему использовать перечисление.
 Steve25 февр. 2013 г., 10:22
Да. Вы используете его для хранения фиксированного набора констант, которые вы определяете сами. Конкретное применение этого зависит от вас. Нет такой вещи, как говорить, когда, почему или как что-то использовать. Это зависит от потребностей разработчика. Все, что вам нужно понять, это что это такое и как это работает.
Что такое перечислениеenum - это ключевое слово, определенное для перечисления нового типа данных. Типизированные перечисления должны использоваться свободно. В частности, они представляют собой надежную альтернативу простым константам String или int, используемым в гораздо более старых API для представления наборов связанных элементов.Зачем использовать enumперечисления неявно являются окончательными подклассами java.lang.Enumесли перечисление является членом класса, оно неявно статичноnew никогда не может использоваться с перечислением, даже внутри самого перечисленияname и valueOf просто используют текст констант enum, тогда как toString может быть переопределен для предоставления любого содержимого, если это необходимодля констант перечисления равно и == равно одному и тому же и может использоваться взаимозаменяемоконстанты enum неявно являются публичными static finalЗаписьПеречисления не могут расширять любой класс.Перечисление не может быть суперклассом.порядок появления констант enum называется их «естественным порядком» и определяет порядок, используемый другими элементами: CompareTo, порядок итераций значений, EnumSet, EnumSet.range.Перечисление может иметь конструкторы, статические блоки и блоки экземпляров, переменные и методы, но не может иметь абстрактных методов.
 tinker_fairy25 февр. 2013 г., 05:24
@DuncanJones разве термины final, static не дают цель использования перечислений?
 Duncan Jones24 февр. 2013 г., 15:26
Вы не объясняете, почему использовать перечисления. Вы просто перечислите несколько свойств перечислений под несвязанными заголовками.

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

Почему бы не использоватьString, или жеint, вместоEnum, для постоянных?

Компилятор не позволитопечатокни одно из значений из фиксированного набора, так как перечислениятипы сами. Последствия:Вам не придется писатьПредварительное условие (или руководствоif) чтобы убедиться, что ваш аргумент находится в допустимом диапазоне.инвариант типа приходит бесплатно.Перечисления могут иметь поведение, как и любой другой класс.Вам, вероятно, понадобится такое же количество памяти, чтобы использоватьStringв любом случае (это зависит от сложностиEnum).

Более того, каждый изEnumЭкземпляры это класс, для которого вы можете определить его индивидуальное поведение.

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

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

по которой у нас есть языки,

Программисты эффективно иправильно Экспресс алгоритмы в форме, которую могут использовать компьютеры.Сопровождающие, чтобы понять алгоритмы, написанные другими иправильно вносить изменения.

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

public class Color {
    private Color() {} // Prevent others from making colors.
    public static final Color RED = new Color();
    public static final Color AMBER = new Color();
    public static final Color GREEN = new Color();
}

Теперь вы можете написать:

Color trafficLightColor = Color.RED;

Приведенный выше шаблон имеет тот же эффект, что и

public enum Color { RED, AMBER, GREEN };

Оба предоставляют одинаковый уровень проверки справки от компилятора. Boilerplate просто больше печатать. Но сохранение большого набора текста делает программиста болееэффективное (см. 1), так что это полезная функция.

Это стоит по крайней мере еще по одной причине:

Смена операторов

Одна вещь, которуюstatic final перечисление выше моделирования делаетне дать тебе приятноswitch случаев. Для типов enum переключатель Java использует тип своей переменной, чтобы вывести область действия перечислений, поэтому дляenum Color выше вам просто нужно сказать:

Color color = ... ;
switch (color) {
    case RED:
        ...
        break;
}

Обратите внимание, что это не такColor.RED в случаях. Если вы не используете enum, единственный способ использовать именованные количества сswitch это что-то вроде:

public Class Color {
    public static final int RED = 0;
    public static final int AMBER = 1;
    public static final int GREEN = 2;
}

Но теперь переменная для хранения цвета должна иметь типint, Хорошая проверка компилятором перечисления иstatic final симуляция исчезла Не счастлив.

Компромиссом является использование скалярного члена в симуляции:

public class Color {
    public static final int RED_TAG = 1;
    public static final int AMBER_TAG = 2;
    public static final int GREEN_TAG = 3;

    public final int tag;

    private Color(int tag) { this.tag = tag; } 
    public static final Color RED = new Color(RED_TAG);
    public static final Color AMBER = new Color(AMBER_TAG);
    public static final Color GREEN = new Color(GREEN_TAG);
}

В настоящее время:

Color color = ... ;
switch (color.tag) {
    case Color.RED_TAG:
        ...
        break;
}

Но обратите внимание, еще более шаблонный!

Использование enum в качестве синглтона

Из приведенного выше шаблона видно, почему перечисление предоставляет способ реализации синглтона. Вместо того чтобы писать:

public class SingletonClass {
    public static final void INSTANCE = new SingletonClass();
    private SingletonClass() {}

    // all the methods and instance data for the class here
}

а затем доступ к нему с

SingletonClass.INSTANCE

мы можем просто сказать

public enum SingletonClass {
    INSTANCE;

    // all the methods and instance data for the class here
}

что дает нам то же самое. Мы можем сойти с рук, потому что Java перечислениянаходятся реализовано как полные классы с небольшим количеством синтаксического сахара, посыпанного сверху. Это опять-таки менее шаблонно, но не очевидно, если идиома вам не знакома. Мне также не нравится тот факт, что вы получаете различные функции enum, хотя они не имеют особого смысла для синглтона:ord а такжеvaluesи т. д. (Там на самом деле сложная симуляция, гдеColor extends Integer это будет работать с переключателем, но это настолько сложно, что это еще более ясно показывает, почемуenum это лучшая идея.)

Поток безопасности

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

public class SingletonClass {
    private static SingletonClass INSTANCE;
    private SingletonClass() {}
    public SingletonClass getInstance() {
        if (INSTANCE == null) INSTANCE = new SingletonClass();
        return INSTANCE;
    }

    // all the methods and instance data for the class here
}

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

Однакоstatic final Код выше не имеет этой проблемы. Он создает экземпляр с нетерпением во время загрузки класса. Загрузка классов синхронизирована.

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

 Basil Bourque31 авг. 2014 г., 20:53
Последний абзац действительно прояснил мне ситуацию с синглтоном. Спасибо! Любой читатель, который скользит, должен перечитать это.
 Holger13 сент. 2018 г., 15:15
static final поля инициализируются ввремя инициализации класса, не время загрузки. Это точно так же, как сenum постоянная инициализация (на самом деле они идентичны под капотом). Вот почему пытаться реализовать «умный» ленивый код инициализации для синглетонов всегда было бессмысленно, даже в первой версии Java.
 Deepankar Singh15 авг. 2016 г., 19:18
Я читал это,stackoverflow.com/questions/16771373/... , Теперь я запутался с вашим последним пунктом. Каким образом enum не предоставляет функцию инициализации lay?

что ни один из других ответов не охватил, что делает перечисления особенно сильными, это способность иметьметоды шаблона, Методы могут быть частью базового перечисления и переопределяться каждым типом. И с поведением, связанным с перечислением, это часто устраняет необходимость в конструкциях if-else или операторах переключения, как этосообщение в блоге демонстрирует - гдеenum.method() делает то, что изначально будет выполнено внутри условного. В этом же примере показано использование статического импорта с перечислениями, а также создание более чистого кода, подобного DSL.

Некоторые другие интересные качества включают в себя тот факт, что перечисления обеспечивают реализацию дляequals(), toString() а такжеhashCode() и реализоватьSerializable а такжеComparable.

Для полного изложения всего, что может предложить перечисление, я настоятельно рекомендую Брюса ЭкеляМышление в Java 4-е издание который посвящает всю главу этой теме. Особенно показательны примеры игр типа «камень, бумага, ножницы» (т. Е. RoShamBo) в качестве перечислений.

Решение Вопроса

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

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

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

Как пример, что лучше?

/** Counts number of foobangs.
 * @param type Type of foobangs to count. Can be 1=green foobangs,
 * 2=wrinkled foobangs, 3=sweet foobangs, 0=all types.
 * @return number of foobangs of type
 */
public int countFoobangs(int type)

против

/** Types of foobangs. */
public enum FB_TYPE {
 GREEN, WRINKLED, SWEET, 
 /** special type for all types combined */
 ALL;
}

/** Counts number of foobangs.
 * @param type Type of foobangs to count
 * @return number of foobangs of type
 */
public int countFoobangs(FB_TYPE type)

Вызов метода как:

int sweetFoobangCount = countFoobangs(3);

затем становится:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

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

int sweetFoobangCount = countFoobangs(99);

больше не возможно.

 Dediqated04 июн. 2013 г., 12:19
Эти ответы мне очень нравятся в SO, потому что кто-то приложил к этому реальные усилия, хорошую работу, я понимаю, перечисления сейчас!
 sleske27 апр. 2015 г., 10:58
@committedandroider: Нет, это правильно. Тип enum - это особый вид класса, а значения - это особые экземпляры. Чтобы процитировать спецификацию языка Java:«Тип enum не имеет экземпляров, отличных от тех, которые определены его константами enum. Это ошибка времени компиляции, чтобы попытаться явно создать экземпляр типа enum (§15.9.1)». (ПСБ,глава 8.9).
 RobAu25 февр. 2013 г., 21:46
Если вы используете перечисления и хотите разрешить комбинацию значений, используйте EnumSet. Это идет со всеми видами аккуратных помощников, таких как public static final EnumSet <FB_TYPE> ALL = EnumSet.allOf (FB_TYPE.class);
 Elist24 дек. 2014 г., 00:11
Я не думаю, что это правдаyou should *always* use enums when a variable can only take one out of a small set of possible values, Использование постоянных значений в качестве «двоичного флага» (с логическимoring) может быть полезным для приложений реального времени, когда у вас мало памяти.
 theRoot19 февр. 2015 г., 16:51
@Elist с использованием enums повышает удобочитаемость ваших кодов. Если вы используете константы в какое-то время, вы или ваш преемник не знаете, почему они используются ... :)

Ваш ответ на вопрос