2015-07-31 8 views
7

Recentemente ho incontrato il seguente pezzo di codice:Qual è il livello di accesso di variabili in enumerazioni di default

enum Animals { 
    DOG("woof"), CAT("meow"), FISH("burble"); 
    String sound; 

    Animals(String s) { 
     sound = s; 
    } 
} 

class TestEnum { 
    static Animals a; 
    public static void main(String[] args) { 
     System.out.println(a.DOG.sound + " " + a.FISH.sound);//Expected compilation failure 
    } 
} 

mi aspetterei il codice a fallire per compilare a causa di questa parte a.DOG.sound. Ma con mia sorpresa, no. Ho cercato dappertutto incluso lo official documentation per scoprire il livello di accesso ma non ho trovato nulla. È pubblico o predefinito?

+0

Si applicano le normali regole di accesso per l'accessibilità. –

+0

È meglio spiegato su http://stackoverflow.com/questions/30046344/enum-types-as-explained-in-effective-java-by-joshua-bloch/30046481#30046481 –

+0

Buona domanda. In questo caso 'String sound' non ha un modificatore di accesso, che gli dà la visibilità predefinita.Ciò significa che è visibile a tutte le altre classi nello stesso pacchetto. Dai un'occhiata a [questo grafico] (http://stackoverflow.com/a/33627846/276052), in particolare la riga 'int i'. – aioobe

risposta

5

Il livello di accesso implicito di un campo dichiarato manualmente in un enum è pacchetto privato, esattamente uguale a quello delle classi normali. Pertanto il campo sound sarà accessibile se e solo se Animals e TestEnum si trovano nello stesso pacchetto.


ho cercato di trovare un preventivo solida per questo nel JLS ma le regole enum sono purtroppo sparsi in tutto il luogo, specificato come eccezioni alle regole per le classi normali, e le regole devono quindi essere assemblati da pezzi. JLS §6.6.1 Determining Accessibility dice:

Un utente (classe, interfaccia, un campo o metodo) di un tipo di riferimento, o un costruttore di un tipo di classe, è accessibile solo se il tipo è accessibile e l'organo o di costruzione viene dichiarata consentire l'accesso:

  • Se il membro o il costruttore è dichiarato public, l'accesso è consentito.

    Tutti i membri di interfacce prive di modificatori di accesso sono implicitamente public.

  • In caso contrario, se il membro o il costruttore è dichiarato protected, l'accesso è consentito solo quando una delle seguenti condizioni:

    • accesso al membro o il costruttore si verifica all'interno del pacchetto che contiene la classe in cui viene dichiarato il membro o il costruttore protected.

    • L'accesso è corretto come descritto in §6.6.2.

  • Altrimenti, se l'elemento o costruttore è dichiarato con accesso pacchetto, l'accesso è consentito solo quando si verifica l'accesso all'interno del pacchetto in cui viene dichiarato il tipo.

    Un membro della classe o un costruttore dichiarato senza un modificatore di accesso ha implicitamente l'accesso al pacchetto.

  • In caso contrario, il membro o il costruttore è dichiarato privato, e l'accesso è consentito se e solo se si verifica all'interno del corpo della classe di livello superiore (§7.6) che racchiude la dichiarazione del membro o costruttore.

Ciò significa che tipi di classe (class e enum) ottenere la regola che i membri hanno implicitamente accesso pacchetto, mentre i tipi di interfaccia (interface e @interface) ottengono la regola che i membri sono implicitamente pubblico.

Non è immediatamente ovvio da quanto sopra che "membro di classe" include enumerazioni nella sua definizione di "classe", ma lo fa. A causa della loro ampia sovrapposizione, i gruppi JLS enumerano con le classi in molti punti (ei tipi di annotazione vengono anche raggruppati con le interfacce). JLS §8.9 Enum Types dice "Una dichiarazione enum specifica un nuovo tipo di enum, un tipo speciale di tipo di classe"; e JLS §8.2 Class Members chiarisce che il termine "membri della classe" indica i membri di un "tipo di classe".

Tuttavia, enumerazioni ottengono due norme specifiche in materia di membro di accessibilità che non sono inclusi nella sezione citata sopra:

  1. I costanti enum stessi (nel tuo esempio sono DOG, CAT, e FISH) potrebbero non avere alcun modificatore di accesso esplicito (JLS §8.9.1) e sono sempre campi public static final del tipo enum (JLS §8.9.3).

  2. Enum costruttori devono essere private (per evitare che le persone che creano costanti in più) e sono private implicitamente (JLS §8.9.2).

A parte queste due eccezioni, le regole di accesso delle classi normali si applicano alle enumerazioni. Se l'enumerazione Animals viene effettuata con public, questa e tutte le sue costanti sono accessibili al di fuori del pacchetto, ma il campo sound è pacchetto-privato e non è accessibile al di fuori del pacchetto, a meno che non lo dichiari esplicitamente public.

+0

Penso che questa risposta meriti di essere accettata. Grazie per "scavo" –

6

Se è possibile importare enum è possibile accedere enum costanti

Se enum è accessibile (in particolare dichiarato public) al di fuori del package è elementi sono anche accessibili e, se non il modificatore specificato che solo saranno accessibili all'interno package. Per impostazione predefinita le costanti enum sono accessibili se enum è accessibile significa che sono public static final per impostazione predefinita.

mi aspetterei che il codice a fallire per compilare a causa di questo a.DOG.sound parte. Ma con mia sorpresa, no.

Sarà uguale a qualsiasi altra variabile può comportarsi in qualsiasi classe se nessun modificatore predefinito sarà accessibile solo all'interno del pacchetto.

+1

Cancellata la mia risposta a tuo favore. "enum" essere pubblico è un punto importante e molti lo hanno perso. +1 – Shahzeb

Problemi correlati