enum.values ​​() - to kolejność zwracanych wyliczeń deterministycznych


105

Mam wyliczenie SOME_ENUM:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Będzie SOME_ENUM.values()zawsze zwracają stałe teksty w kolejności zgłoszeń ENUM: EN_ONE, EN_TWO, EN_THREE? Czy jest to reguła, czy też nie ma gwarancji, że nie zostanie zmieniona w następnych wersjach JDK?


1
Iteruję po moim wyliczeniu, aby wypełnić listę, którą niż w innym miejscu w kodzie czytam iterując po tym wyliczeniu.
Skarab,

11
@MitchWheat Z tego samego powodu, dla którego można by polegać na kolejności zachowania listy: ponieważ JDK jest narzędziem, które daje pewne gwarancje, a poleganie na nich pomaga pisać bardziej zwięzły i lepszy kod. Trzeba przyznać, że pytanie „Czy gwarantuje się, że nie zostanie zmieniony?” nie można odpowiedzieć, na pewno nie można na tym polegać, nic nie ma takiej gwarancji.
Fletch

Odpowiedzi:


144

Specyfikacja języka Java używa tego jawnego języka:

@return tablica zawierająca stałe tego typu wyliczenia, w kolejności, w jakiej są zadeklarowane [źródło]

Więc tak, zostaną zwrócone w kolejności deklaracji. Warto zauważyć, że kolejność może się zmieniać z czasem, jeśli ktoś zmieni klasę, więc uważaj, jak tego używasz.


1
Jeśli ktoś doda wartość pośrodku w późniejszej wersji kodu, może to cię okiełznać, ponieważ zmieniłoby to wartość porządkową innych elementów (zobacz metodę Enum.ordinal ()). Z tego powodu najlepiej nie polegać na pozycji porządkowej jako mechanizmie serializacji (tj. Nie przechowywać jej w bazie danych).
Matt

1
Link do źródła tej specyfikacji?
Dan Grahn


16

Tak, zwrot w takiej kolejności jest gwarantowany.

Należy jednak unikać polegania na tym i na ordinal()wartości, ponieważ może się ona zmienić na przykład po wstawieniu nowych elementów.


+1 za radę mędrca. Jeśli chodzi o porządkową (), Effective Java sugeruje dodanie pola członkowskiego do typu wyliczenia.
ide,

9

Jest to określane przez kolejność deklarowania wartości. Jednak nie ma gwarancji, że Ty (lub ktoś inny) nie zmieni kolejności / wstawia / usuwa wartości w przyszłości . Więc nie powinieneś polegać na zamówieniu.

Efektywna Java 2nd. Edycja poświęca swój punkt 31 blisko powiązanemu tematowi: Użyj pól instancji zamiast liczb porządkowych :

Nigdy nie wyprowadzaj wartości związanej z wyliczeniem z jego liczby porządkowej; zamiast tego przechowuj go w polu instancji.


3
„nie ma gwarancji, że ktoś nie zmieni kolejności wartości w przyszłości” - ale właśnie dlatego chcę polegać na zamówieniu :-)! Chcę mieć możliwość ponownego zamawiania artykułów w przyszłości i tym samym zmiany zachowania mojego programu. Bloch ma rację, mówiąc, że nie polega na liczbie porządkowej, a jeśli przykład pytającego naprawdę obejmuje wyliczenia, takie jak EN_TWO, to polega na liczbie porządkowej i nie powinien tego robić. Ale poleganie na zamówieniu jest całkowicie w porządku. W rzeczywistości, ponieważ porządek jest gwarantowany, utworzenie pola przeznaczonego specjalnie dla zamówienia oznaczałoby napisanie zbędnego kodu, czego nie można robić w książkach takich jak Efektywna Java.
Fletch

@Fletch, przepraszam, nie całkiem cię śledzę. Dla mnie brzmi to tak, jakbyś próbował użyć go enumw jakimś celu, do którego nie był przeznaczony.
Péter Török

powiedzmy, że masz słynne wyliczenie „Planeta”. W swoim interfejsie użytkownika chcesz wyświetlić planety w kolejności ich odległości od słońca. Jak możesz to najlepiej osiągnąć? Chciałbym uporządkować stałe planety we właściwej kolejności w klasie wyliczenia, a następnie wyliczyć wyliczenie w interfejsie użytkownika. Ponieważ kolejność jest niezawodna, to zadziała. Właśnie o tym mówię. Jeśli pewnego dnia Ziemia zbliży się do Słońca niż Mars, oczywiście w takim momencie pierwszą rzeczą, która przyjdzie Ci do głowy, będzie utrzymanie kodu! Więc idziesz do klasy Planeta i przenosisz ZIEMIĘ przed MARSEM.
Fletch

@Fletch, Ziemia jest już bliżej Słońca niż Marsa ;-), ale rozumiem, co masz na myśli. Jednak w tym przypadku kolejność planet jest w rzeczywistości funkcją ich średniej odległości od Słońca, która nie jest prostą liczbą porządkową, dlatego IMHO powinno być lepiej przechowywane jako oddzielne pole dla każdej planety. Następnie możesz mieć trywialny komparator, który porównuje planety na podstawie ich średniej odległości od Słońca i porządkuje je za pomocą tego komparatora. To jest IMHO czyste i niezawodne rozwiązanie. Zważywszy, że twoje rozwiązanie psuje się, gdy np. Nowy kolega zdecyduje, że planety powinny być oczywiście wymienione w porządku alfabetycznym ;-)
Péter Török

1
Hahaha ermm tak, w każdym razie to wszystko spisek, nie ma Marsa. Początkowo zamierzałem użyć Saturna, ale nie mogłem sobie przypomnieć, które planety znajdują się w pobliżu, ale plan Marsa wydaje się obrócić :-). W każdym razie ... w tym przypadku komparator byłby dobry, ale ma oczywiście tę wadę, że wymaga większej ilości kodu. Myślę, że jeśli polegasz na porządkowaniu kodu źródłowego, udokumentowanie tego w komentarzach do klasy byłoby dobrą rzeczą. Twój kolega może nawet to przeczytać.
Fletch

7

Inne odpowiedzi są dobre, ale nie komentuj tego:

„Czy to reguła, czy nie ma gwarancji, że nie zostanie zmieniona w następnych wersjach Jdk?”

Nie wierzę, że istnieją gwarancje dotyczące przyszłych JDK, więc nie powinieneś się o nie martwić. Nie byłoby sposobu, aby je wyegzekwować, przyszli liderzy JDK mogą po prostu zdecydować się na rezygnację z takich gwarancji. To jak system parlamentu Westminster: „Żaden parlament nie może związać przyszłego parlamentu”.

To powiedziawszy, historia JDK ujawnia doskonałą spójność. Nie wprowadzają wielu istotnych zmian, więc możesz być całkiem pewien, że bieżące określone (a nie tylko obserwowane) zachowanie zostanie zachowane.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.