2009-09-14 36 views
10

Java enums là gì? Họ làm việc như thế nào? Tôi có thể sử dụng chúng ở đâu và như thế nào?
Tôi có thể làm mà không sử dụng enums trong một ứng dụng hay chúng mạnh đến mức sử dụng chúng tốt hơn là bỏ qua chúng?Hiểu về Enums trong Java

Trả lời

40

Enums trong Java 5+ là các lớp cơ bản có tập hợp các phiên bản được xác định trước. Chúng được dùng để thay thế cho một tập hợp các hằng số nguyên. Chúng được ưu tiên là hằng số vì chúng có thể thực thi an toàn kiểu.

Vì vậy, thay vì:

public class Suit { 
    public final static int SPADES = 1; 
    public final static int CLUBS = 2 
    public final static int HEARTS = 3; 
    public final static int DIAMONDS = 4; 
} 

bạn có:

public enum Suit { 
    SPADES, CLUBS, HEARTS, DIAMONDS 
} 

Những lợi thế là:

  1. Loại an toàn. Bạn có thể khai báo một đối số hàm, kiểu trả về, thành viên lớp hoặc biến cục bộ là một kiểu Enum cụ thể và trình biên dịch sẽ thực thi kiểu an toàn;
  2. Enums về cơ bản là các lớp học. Họ có thể thực hiện các giao diện, có hành vi và như vậy.

Sự an toàn loại là một vấn đề bởi vì trong ví dụ đầu tiên, đây là những báo cáo hợp lệ:

int i = Suit.DIAMONDS * Suit.CLUBS; 

hoặc bạn có thể vượt qua trong 11 tới một chức năng hy vọng một bộ đồ. Bạn không thể làm điều đó với một enum an toàn.

Bạn có thể sử dụng một lớp cho Suit để cung cấp loại an toàn và đây là giải pháp trước khi Java 5. Josh Bloch (trong Effective Java, mà là một phải đọc cho các lập trình Java IMHO) thúc đẩy mô hình typesafe enum mà đã trở thành Java 5+ enum. Nó có một số tiền hợp lý của boilerplate trên nó và một số trường hợp góc mà mọi người không có xu hướng phục vụ, chẳng hạn như serialization không gọi một constructor và để đảm bảo bạn chỉ có một ví dụ bạn phải ghi đè lên readResolve() phương pháp.

Ví dụ:

public enum CardColour { 
    RED, BLACK 
} 

public enum Suit { 
    SPADES(CardColour.BLACK), 
    CLUBS(CardColour.BLACK), 
    HEARTS(CardColour.RED), 
    DIAMONDS(CardColour.RED); 

    private final CardColour colour; 

    Suit(CardColour colour) { this.colour = colour; } 

    public CardColour getColour() { return colour; } 
} 

Edit: Sun có introduction to typesafe enums.

Đối với giao diện, chúng thực sự bổ sung enums thay vì thay thế. Giống như bạn có thể nói rằng Suit là một giao diện và bạn sẽ có điều này:

public interface Suit { 
    CardColour getColour(); 
} 

Vấn đề là bạn có thể đi và xác định 300 bộ quần áo khác nhau và bạn cũng có thể xác định Spades nhiều lần. Một ưu điểm khác của enums là (việc nạp các trường hợp góc lớp) mặc dù chỉ có một cá thể của mỗi giá trị enum.Thông thường điều này được gọi là có giá trị kinh điển , có nghĩa là bình đẳng này đúng:

a.equals(b) == b.equals(a) == (a == b) 

cho tất cả a, b mà là trường hợp của một Enum cụ thể. Điều này có nghĩa rằng thay vì viết:

if (card.getSuit().equals(Suit.SPADES)) { ... } 

bạn có thể viết:

if (card.getSuit() == Suit.SPADES) { ... } 

đó là nhanh hơn và thường dễ đọc hơn. Thêm IDE thường sẽ cung cấp cho bạn thông tin phản hồi nếu bạn so sánh enums của các loại khác nhau nói rằng họ không thể có thể bằng nhau, mà có thể là một hình thức hữu ích và đầu kiểm tra lỗi.

+1

Hướng dẫn của Sun (http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html) cung cấp một tầm nhìn tốt về tiềm năng của chúng; Tôi muốn đề nghị thêm một tài liệu tham khảo để đọc thêm. –

+0

@cletus ... không thể sử dụng Giao diện cho giống nhau được không? –

+0

@cletus: Tôi không hiểu phần "an toàn loại" của nó. Không phải là một lớp Java cung cấp an toàn loại? –

1

Mặt trời là enum documentation có lẽ là giải thích tốt nhất. Tất nhiên bạn có thể làm mà không có chúng như các lập trình viên Java chắc chắn đã làm cho đến khi Java 1.5 được phát hành. Bạn thường sẽ thực hiện điều tương tự bằng cách sử dụng hằng số trong các phiên bản của Java trước 1.5. Nhưng enums là một tiện lợi tốt đẹp.

+0

Tại sao nó bao gồm trong Java 1.5? Nó có mạnh không? –

1

Nếu tình huống không xuất hiện thì bạn không cần đến chúng.

Chúng cho phép bạn có một bộ được xác định rõ của sự vật, ví dụ nếu bạn muốn để đại diện cho trạng thái vật chất bạn có thể có:

enum MatterState { 
    Solid, 
    Liquid, 
    Gas; 
} 

đâu họ đánh bại phong cách cũ của việc sử dụng đối tượng để đại diện cho bộ theo một số cách, một số trong số đó là:

  • Bạn có thể sử dụng chúng trong câu lệnh chuyển đổi.
  • Ít mã hơn.
  • Được xây dựng trong đến/từ chuỗi.
+0

bạn đánh bại tôi để trả lời bằng cách sử dụng ví dụ chính xác;) – n002213f

+3

quên Plasma: p –

0

Từ cách diễn giải của tôi, enums dễ đọc hơn bất kỳ thứ gì khác. Về cơ bản, chúng được sử dụng để thay thế các giá trị như 1-6 với nhiều tên mô tả hơn, như [Happy, Sad, Angry, etc] Bạn nên sử dụng chúng bất cứ khi nào bạn cần sử dụng một tập nhỏ các biến để mô tả giải pháp mà bạn đang mong đợi.

+2

@ bogerton: thực sự, có những lợi thế về an toàn loại đáng kể khi sử dụng Java enums; xem câu trả lời tuyệt vời của @ cletus. –

11

Hãy suy nghĩ về Enum như sau

public class MyEnum { 

    // Object instantiated at declaration 
    public static final MyEnum ONE = new MyEnum(); 
    public static final MyEnum TWO = new MyEnum(); 
    public static final MyEnum THREE = new MyEnum(); 

    // Notice a private constructor 
    // There is no way outside MyEnum class call it 
    private MyEnum() { ... } 


} 

Vì vậy, một MyEnum như một enum sẽ

public enum MyEnum { 
    ONE, 
    TWO, 
    THREE; 
} 

Cả hai đều tương tự

regards,

1

Để thêm một số thông tin bổ sung cho tìm hiểu thêm, tốt hơn là bắt đầu với khái niệm về biến và giá trị của nó. Vì tôi chắc chắn bạn bây giờ, mỗi biến có một kiểu khai báo (như các kiểu nguyên thủy Java). Mỗi loại có giá trị tương ứng của riêng nó. Ví dụ một biến với kiểu char có thể chấp nhận tất cả các ký tự riêng lẻ làm giá trị của nó. Vì vậy, nó rất hữu ích khi bạn muốn khai báo một biến có thể chấp nhận tất cả các hằng số ký tự. Ví dụ tất cả các hằng số nhân vật được chấp nhận và có ý nghĩa cho biến aCharToStopProgram:

char aCharToStopProgram = getUserInput(); 

Tuy nhiên, những gì về khi bạn có một giá trị giới hạn, tôi có nghĩa là miền giá trị của biến của bạn được giới hạn giá trị đặc biệt. Ví dụ bạn có userChoice giữ giá trị của câu hỏi trắc nghiệm hệ thống. Vì vậy, chỉ 'a', 'b', 'c', 'd' là có ý nghĩa. Bạn không muốn trong một phần khác của mã chương trình của bạn (hoặc bất kỳ lý do nào khác) biến này được gán với các giá trị vô nghĩa như 's'.Bây giờ là sự thật để sử dụng một kiểu nguyên thủy char cho biến của chúng ta có thể chấp nhận bất kỳ hằng số ký tự nào, chẳng hạn như sau.

char userChoice = getUserChoice(); 

Trong trường hợp này Java cung cấp các loại được liệt kê. Nó có nghĩa là thông qua từ khóa enum bạn có thể định nghĩa một lớp mới có trường hợp giới hạn và cố định được gọi là giá trị có tên (bạn không thể tạo đối tượng mới). Ví dụ:

enum MultipleChoiceAnswer { A, B, C, D }; 

hoặc

public enum MultipleChoiceAnswer { 

    A('a'), B('b'), C('c'), D('d'); 

    private char choice; 

    private MultipleChoiceAnswer(char choice) { 
     this.choice = choice; 
    } 

    public String getChoice() { 
     return choice; 
    } 
} 

Như kết quả mà bạn có thể định nghĩa một biến với kiểu riêng của bạn:

MultipleChoiceAnswer userChoice = getUserChoice();//OR MultipleChoiceAnswer.A