2015-06-25 17 views
12

Di seguito è riportato il codice che definisce il tipo di enum.In java, a cosa viene compilato questo tipo di enum?

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; 
    } 
} 

che viene internamente compilato,

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; 
    } 
} 

è la mia comprensione corretta?

risposta

7

Funzionalmente, sì. Letteralmente no (non è possibile sottoclassi esplicitamente Enum per una cosa). enum(s) hanno un toString. E il tuo enum non è un codice valido (non è possibile chiamare super()) e getValue richiede un tipo di reso.

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

'classe Company' non può sottoclasse esplicitamente' classe java.Lang.Enum'? Non ti ho capito. Come metodi come 'ordinal()'/'values ​​()' sono visibili per oggetti di tipo 'class Company' senza sottoclassi? – overexchange

+0

@overexchange Fa sottoclasse 'java.lang.Enum' puoi confermarlo guardando il bytecode, tuttavia non puoi sottoclasse' java.lang.Enum' ** te **; questo semplicemente non verrà compilato come ho spiegato. Questa estensione viene aggiunta dal compilatore stesso. –

+0

Puoi creare una classe che estenda 'Enum', se usi un compilatore più vecchio ... – Holger

3

Se si rimuove chiamata a super che è illegale e this.name come parametro al super è anche illegale, compilarlo e corse javap in classe, questo viene emesso:

$ /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 {}; 
} 

Ecco bytecode per statica , parte di esso

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

Strano. Per "Azienda c1 = Company.EBAY;", dov'è la creazione dell'oggetto? – overexchange

+0

@overexchange in 'static {}', se vuoi che il codice byte possa postarlo ma non è sicuro che abbia senso. –

+0

Ma static {} verrà eseguito una volta quando la classe viene caricata e inizializzata.Quindi quel blocco crea oggetti per ogni membro? – overexchange

4

Quasi, il secondo frammento non rappresentare bene quello generato internamente dal compilatore (bytecode), tuttavia, non è esattamente lo stesso.

Un'enumerazione compilata conterrà il flag ACC_ENUM che indica che questa classe o la sua superclasse sono dichiarate come un tipo enumerato e saranno trattate come tali dalla JVM.

La tua seconda frammento non sarebbe (supponendo che sarebbe compilare) includere questo flag nel bytecode:


ENUM

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

CLASSE

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

Come per il resto della tua logica (supponendo ancora che si possa compilare) è giusto. Internamente, un'enumerazione verrà rappresentata come classe final che si estende java.lang.Enum. Tuttavia, si noti che non è possibile estendere direttamente lo java.lang.Enum poiché questo viene eseguito dal compilatore durante la creazione di un'enumerazione e comporterebbe un errore di compilazione se si tenta di farlo da soli.

Problemi correlati