enum.values ​​() - là một thứ tự của các xác định enum được trả về


105

Tôi có một enum SOME_ENUM:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Sẽ SOME_ENUM.values()luôn trả về các enum theo thứ tự khai báo enum EN_ONE, EN_TWO, EN_THREE:? Đó là một quy tắc hay nó không được đảm bảo sẽ không bị thay đổi trong các bản phát hành JDK tiếp theo?


1
Tôi lặp lại enum của mình để điền vào một danh sách, mà hơn là ở vị trí khác trong đoạn mã tôi đã đọc là lặp qua enum này.
Skarab

11
@MitchWheat Vì lý do tương tự mà bạn sẽ dựa vào thứ tự bảo toàn Danh sách: bởi vì JDK là một công cụ cung cấp cho bạn những đảm bảo nhất định và việc dựa vào những đảm bảo này sẽ giúp bạn viết mã ngắn gọn hơn và tốt hơn. Phải thừa nhận câu hỏi "Có đảm bảo không bị thay đổi không?" là không thể trả lời, bạn chắc chắn không thể dựa vào đó, không có gì có thể đảm bảo điều đó.
Fletch

Câu trả lời:


144

Đặc tả ngôn ngữ Java sử dụng ngôn ngữ rõ ràng này:

@ quay lại một mảng chứa các hằng của kiểu enum này, theo thứ tự chúng được khai báo [Nguồn]

Vì vậy, có, chúng sẽ được trả lại theo thứ tự khai báo. Cần lưu ý rằng thứ tự có thể thay đổi theo thời gian nếu ai đó thay đổi lớp, vì vậy hãy hết sức cẩn thận về cách bạn sử dụng điều này.


1
Nếu ai đó thêm một giá trị vào giữa trong phiên bản mã mới hơn, điều này có thể khiến bạn khó chịu, vì nó sẽ thay đổi giá trị thứ tự của các phần tử khác (xem phương thức Enum.ordinal ()). Tốt nhất là không dựa vào vị trí thứ tự như một cơ chế tuần tự hóa (tức là không lưu trữ nó trong db) vì lý do này.
Matt,

1
Liên kết đến nguồn cho thông số kỹ thuật đó?
Dan Grahn


16

Có, nó được đảm bảo để trả lại chúng theo thứ tự đó.

Tuy nhiên, bạn nên tránh dựa vào đó và vào ordinal()giá trị, vì nó có thể thay đổi sau khi chèn các mục mới, chẳng hạn.


+1 cho lời khuyên hiền triết. Về chủ đề ordinal (), Java hiệu quả đề xuất thêm một trường thành viên vào kiểu enum.
Ide

9

Nó được xác định theo thứ tự mà các giá trị của bạn được khai báo. Tuy nhiên, không có gì đảm bảo rằng bạn (hoặc người khác) sẽ không sắp xếp lại / chèn / xóa các giá trị trong tương lai . Vì vậy, bạn không nên dựa vào đơn đặt hàng.

Java hiệu quả thứ 2. Ấn bản dành Mục 31 của mình cho một chủ đề có liên quan chặt chẽ: Sử dụng các trường mẫu thay vì thứ tự :

Không bao giờ lấy một giá trị liên kết với một enum từ thứ tự của nó; thay vào đó lưu trữ nó trong một trường cá thể.


3
"không đảm bảo rằng ai đó sẽ không sắp xếp lại các giá trị trong tương lai" - nhưng đó chính xác là lý do tại sao tôi muốn dựa vào thứ tự :-)! Tôi muốn có thể sắp xếp lại các mặt hàng trong tương lai và do đó thay đổi hành vi của chương trình của tôi. Bloch đã đúng khi không dựa vào thứ tự và nếu ví dụ của người hỏi thực sự liên quan đến các enum như EN_TWO thì anh ta đang dựa vào thứ tự và không nên làm điều này. Nhưng để dựa vào thứ tự là hoàn toàn tốt. Trên thực tế, vì thứ tự được đảm bảo, để tạo một trường dành riêng cho thứ tự sẽ là viết mã thừa, những điều mà các cuốn sách như Java hiệu quả yêu cầu bạn không nên làm.
Fletch

@Fletch, xin lỗi, tôi không thực sự theo dõi bạn. Đối với tôi, điều này có vẻ như bạn đang cố gắng sử dụng enumcho một số mục đích mà nó không được dành cho.
Péter Török

giả sử bạn có enum "Planet" nổi tiếng. Trong giao diện người dùng của mình, bạn muốn liệt kê các hành tinh theo thứ tự khoảng cách của chúng với mặt trời. Làm thế nào bạn có thể làm tốt nhất điều này? Tôi sẽ sắp xếp các hằng số hành tinh theo đúng thứ tự bên trong lớp enum và sau đó chỉ cần liệt kê enum trong giao diện người dùng. Vì thứ tự là đáng tin cậy, điều này sẽ hoạt động. Đó là loại điều tôi đang nói đến. Nếu một ngày Trái đất di chuyển gần mặt trời hơn sao Hỏa, tất nhiên trong khoảnh khắc như vậy, điều đầu tiên trong tâm trí bạn ấm áp sẽ là duy trì mã của bạn! Vì vậy, bạn đi đến lớp Planet của bạn và chuyển EARTH đến trước MARS.
Fletch

@Fletch, Trái đất đã gần với Mặt trời hơn sao Hỏa ;-) nhưng tôi hiểu ý bạn. Tuy nhiên, trong trường hợp này, thứ tự của các hành tinh thực sự là một hàm của khoảng cách trung bình của chúng từ Mặt trời, không phải là một thứ tự đơn giản, do đó IMHO tốt hơn nên lưu trữ nó như một trường riêng biệt cho mỗi hành tinh. Sau đó, bạn có thể có một bộ so sánh tầm thường để so sánh các hành tinh dựa trên khoảng cách trung bình của chúng từ Mặt trời và sắp xếp thứ tự chúng bằng bộ so sánh này. Đây là IMHO một giải pháp sạch và tuyệt vời. Trong khi nghỉ giải pháp của bạn càng sớm càng ví dụ như một đồng nghiệp mới quyết định rằng các hành tinh nên rõ ràng được liệt kê theo thứ tự chữ cái ;-)
Péter Török

1
Hahaha ermm vâng dù sao tất cả đều là một âm mưu, không có sao Hỏa. Ban đầu tôi định sử dụng Sao Thổ nhưng không thể nhớ nó ở gần hành tinh nào, nhưng kế hoạch Sao Hỏa dường như đã phản tác dụng :-). Dù sao ... trong trường hợp này, một trình so sánh sẽ tốt nhưng có nhược điểm là yêu cầu nhiều mã hơn, rõ ràng. Tôi nghĩ rằng nếu bạn đang dựa vào thứ tự mã nguồn, ghi lại điều này trong các bình luận của lớp sẽ là một điều tốt. Đồng nghiệp của bạn thậm chí có thể đọc nó.
Fletch

7

Các câu trả lời khác là tốt, nhưng không bình luận về điều này:

"Đó là một quy tắc hay nó không được đảm bảo sẽ không bị thay đổi trong các bản phát hành Jdk tiếp theo?"

Tôi không tin rằng có sự đảm bảo về các JDK trong tương lai, vì vậy bạn thậm chí không nên lo lắng về chúng. Sẽ không có cách nào để thực thi chúng, các khách hàng tiềm năng JDK trong tương lai có thể quyết định gia hạn các bảo đảm như vậy. Nó giống như hệ thống nghị viện Westminster: "Không một Nghị viện nào có thể ràng buộc một quốc hội tương lai."

Điều đó nói lên rằng, lịch sử của JDK cho thấy sự nhất quán tuyệt vời. Chúng không thực hiện nhiều thay đổi đột phá, vì vậy bạn có thể khá tin tưởng rằng hành vi được chỉ định hiện tại (không chỉ được quan sát) sẽ được giữ nguyên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.