2013-06-18 14 views
7
public enum Operations { 

    SINGLE, 
    MULTIPLE; 

    private Type operation; 

    public void setOperation(Type operation) { 
     this.operation = operation; 
    } 

    public Type getOperation() { 
     return operation; 
    } 

    public static void main(String[] args) { 
     Operations oper1 = Operations.SINGLE; 
     oper1.setOperation(Type.GET); 

     Operations oper2 = Operations.SINGLE; 
     oper2.setOperation(Type.POST); 
     System.out.println(oper1.getOperation()); 
     System.out.println(oper2.getOperation()); 
    } 
} 

enum Type { 
    POST, 
    GET; 
} 

W powyższym kodzie wartość operacji zmienia się dla obu operacji. Jak mogę mieć dwa wystąpienia Operations.SINGLE z innym typem operacji?Czy zmienne java enum są statyczne?

+1

Twoje pytanie będzie łatwiejsze do zrozumienia, jeśli powiesz nam, co zostało wydrukowane na standardowe wyjście. (Zakładam, że wypisze 'POST' dwa razy?) –

+0

SINGLE jest równoznaczne z publicznymi statycznymi operacjami końcowymi SINGLE = new Operations (" SINGLE ", 0) – Blackbelt

Odpowiedz

12

Tak, instancje są domyślnie static i final. Oznacza to, że kod jest nierozsądny. Wyobraź sobie dwa wątki zarówno wywołujące SINGLE.setOperation(Type); nie będziesz mieć zaufania do tego, do czego dzwonisz.

Od Java Language Specification, Section 8.9 z:

typów Enum (§8.9) nie może być uznane za abstrakcyjne; spowoduje to błąd podczas kompilacji.

Typ wyliczeniowy jest domyślnie ostateczny, chyba że zawiera co najmniej jedną stałą wyliczeniową, która ma treść klasy.

Błędem podczas kompilacji jest jawne zadeklarowanie typu wyliczeniowego jako ostatecznego.

Zagnieżdżone typy wyliczeniowe są niejawnie statyczne. Dopuszczalne jest jawne zadeklarowanie zagnieżdżonego typu wyliczeniowego jako statycznego.

A w następnym odcinku:

Korpus typu enum może zawierać stałe enum. Stała wyliczeniowa definiuje instancję typu wyliczeniowego.

Ponieważ występuje tylko jedna instancja każdej stałej wyliczeniowej, dopuszczalne jest użycie operatora == zamiast metody równości przy porównywaniu dwóch odniesień do obiektów, jeśli wiadomo, że co najmniej jeden z nich odnosi się do stałej wyliczeniowej .

0

Tak, wszystkie elementy enum to static final constant. Jednak jak wspomniano w innej odpowiedzi przez darijan, w twoim programie jest błąd logiczny.

0

wystąpił błąd w czwartym wierszu main metody

oper1.setOperation(Type.POST); 

powinny być

oper2.setOperation(Type.POST); 
+0

to literówka w kodzie – Optional

10

przypadki Enum są "statyczne" (to znaczy zachowywać się jak zmiennych statycznych), ale nie są immutable.

Wszystkie wątki widzą ten sam obiekt, do którego odnosi się nazwa wyliczeniowa - są podobne do singletonów, z żelazną gwarancją JVM, że istnieje tylko jedno wystąpienie wyliczenia. Zmiana pola wyliczenia zmienia go dla wszystkich.

Dobrą praktyką jest tworzenie pól w polach final i przekształcanie ich w niezmienne.

11

Jak mogę mieć dwa wystąpienia Operations.SINGLE z innym typem operacji?

Podstawową ideą enum jest to, że istnieje jedna i tylko jedna instancja każdego z jej członków. To pozwala bezpiecznie porównywać je pod kątem równości, bez obawy, że istnieje inny SINGLE lub MULTIPLE utworzony w innym miejscu.

Jeśli potrzebujesz wielu wystąpień SINGLE, ustaw go jako class, a nie jako enum. Fakt, że dokonałeś zmiany wartości enum, zmienia się pośrednio w tym samym kierunku: użycie enum jest złym wyborem w twojej sytuacji.

2

Jestem o półtorej roku za późno. Ale widzę, że na pytanie nie udzielono odpowiedzi.

rozwiązaniem byłoby przy użyciu klasy zamiast wyliczenia, która ma te dwa teksty stałe jak dziedzinach:

class Operation { 
    Quantity quantity; 
    Type type; 
    Operation(Quantity quantity, Type type) { 
     this.quantity = quantity; 
     this.type = type; 
    } 
} 

Można oczywiście użyć enum zamiast klasy. Potem trzeba wyliczyć wszystkie kombinacje:

enum Operation { 
    SINGLE_GET(Quantity.SINGLE, Type.GET) 
    SINGLE_POST(Quantity.SINGLE, Type.POST) 
    MULTIPLE_GET(Quantity.MULTIPLE, Type.GET) 
    // ... more options 
    // contents same as in class Operation, constructor private by default 
} 

Oba podejścia są ważne, czasami naprawdę chcesz wyliczyć wszystkie kombinacje, przez większość czasu, jednak należy pewnie trzymać z podejściem class.

Dla zwięzłości, nie zdefiniowałem nazwisk Quantity i Type, są to po prostu proste wyliczenia.