2015-06-25 22 views
12

Dưới đây là mã xác định loại enum.Trong java, loại enum như thế nào biên dịch?

enum Company{ 
    EBAY(30), PAYPAL(10), GOOGLE(15), YAHOO(20), ATT(25); 
    private int value; 

    private Company(int value){ 
     super(this.name()); 
     this.value = value; 
    } 

    public int getValue(){ 
     return value; 
    } 
} 

đó được nội biên soạn để,

final class Company extends Enum<Company>{ 
    public final static Company EBAY = new Company(30); 
    public final static Company PAYPAL = new Company(10); 
    public final static Company GOOGLE = new Company(15); 
    public final static Company YAHOO = new Company(20); 
    public final static Company ATT = new Company(25); 

    private int value; 

    private Company(int value){ 
     super(this.name(),Enum.valueOf(Company.class, this.name())); 
     this.value = value; 
    } 

    public int getValue(){ 
     return value; 
    } 
} 

là hiểu biết của tôi có đúng không?

Trả lời

7

Chức năng, có. Theo nghĩa đen không (bạn không thể phân loại một cách rõ ràng Enum cho một điều). enum(s)toString. Và enum của bạn không phải là mã hợp lệ (bạn không thể gọi super()) và getValue cần loại trả lại.

enum Company{ 
    EBAY(30), PAYPAL(10), GOOGLE(15), YAHOO(20), ATT(25); 
    private int value; 

    private Company(int value){ 
     this.value = value; 
    } 

    public int getValue(){ 
     return value; 
    } 
} 
+1

'lớp Công ty' không thể phân lớp rõ ràng' lớp java.Lang.Enum'? Tôi không hiểu bạn. Các phương thức như 'ordinal()'/'values ​​()' có thể nhìn thấy như thế nào đối với các đối tượng kiểu 'class Company' mà không có subclassing? – overexchange

+0

@overexchange Nó không phân lớp 'java.lang.Enum' bạn có thể xác nhận nó bằng cách xem bytecode, tuy nhiên bạn không thể phân lớp' java.lang.Enum' ** mình **; điều này đơn giản sẽ không biên dịch như tôi đã giải thích. Mở rộng này được thêm vào bởi trình biên dịch. –

+0

Bạn có thể tạo một lớp mở rộng 'Enum', nếu bạn sử dụng trình biên dịch cũ hơn… – Holger

3

Nếu bạn loại bỏ lời kêu gọi super đó là bất hợp pháp và this.name như tham số để siêu cũng là bất hợp pháp, biên dịch nó và chạy javap trên lớp, đây là kết quả:

$ /usr/lib/jvm/java-7-oracle/bin/javap -p Company.class 
Compiled from "Company.java" 
final class Company extends java.lang.Enum<Company> { 
    public static final Company EBAY; 
    public static final Company PAYPAL; 
    public static final Company GOOGLE; 
    public static final Company YAHOO; 
    public static final Company ATT; 
    private int value; 
    private static final Company[] $VALUES; 
    public static Company[] values(); 
    public static Company valueOf(java.lang.String); 
    private Company(int); 
    public int getValue(); 
    static {}; 
} 

Đây là bytecode cho tĩnh , một phần của nó

static {}; 
    flags: ACC_STATIC 
    LineNumberTable: 
    line 2: 0 
    line 1: 75 
    Code: 
    stack=5, locals=0, args_size=0 
     0: new   #4     // class Company 
     3: dup   
     4: ldc   #8     // String EBAY 
     6: iconst_0  
     7: bipush  30 
     9: invokespecial #9     // Method "<init>":(Ljava/lang/String;II)V 
     12: putstatic  #10     // Field EBAY:LCompany; 
+0

Lạ. Đối với "Công ty c1 = Công ty.EBAY;", tạo đối tượng ở đâu? – overexchange

+0

@overexchange trong 'static {}', nếu bạn muốn mã byte có thể đăng nó nhưng không chắc chắn nó có ý nghĩa. –

+0

Nhưng tĩnh {} sẽ thực hiện một lần khi lớp được nạp và khởi tạo.Vậy khối đó có tạo các đối tượng cho mỗi thành viên không? – overexchange

4

Hầu hết, đoạn thứ hai của bạn đại diện cho nội dung được tạo bởi trình biên dịch (bytecode) tuy nhiên, nó không chính xác giống nhau.

Một liệt kê được biên dịch sẽ chứa cờ ACC_ENUM cho biết rằng lớp này hoặc siêu lớp của nó được khai báo là loại được liệt kê và sẽ được JVM xử lý như vậy.

đoạn thứ hai của bạn sẽ không (giả như nó sẽ biên dịch) bao gồm cờ này trong bytecode:


ENUM

final class Company extends java.lang.Enum<Company> 
     minor version: 0 
     major version: 52 
     flags: ACC_FINAL, ACC_SUPER, ACC_ENUM 

CLASS

final class Company 
    minor version: 0 
    major version: 52 
    flags: ACC_FINAL, ACC_SUPER 

Đối với phần còn lại của logic của bạn (vẫn giả sử nó sẽ biên dịch) nó là đúng. Trong nội bộ, một liệt kê sẽ được thể hiện dưới dạng lớp final kéo dài java.lang.Enum. Tuy nhiên, lưu ý rằng bạn không thể trực tiếp mở rộng java.lang.Enum mình vì công cụ này được thực hiện bởi trình biên dịch khi tạo một liệt kê và sẽ dẫn đến lỗi biên dịch nếu bạn cố gắng tự làm.

Các vấn đề liên quan