Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the access level of variables in enums by default [duplicate]

Tags:

java

enums

Recently I've come across the following piece of code:

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

I would expect the code to fail to compile because of this a.DOG.sound part. But to my surprise it doesn't. I've searched all around including the official documentation to find out the access level but found nothing. Is it public or default?

like image 517
Mikayil Abdullayev Avatar asked Jul 31 '15 05:07

Mikayil Abdullayev


People also ask

Are enums public by default?

Enum constructors must be private (to prevent people creating extra constants) and are private implicitly (JLS §8.9.

What is the default value of enum in Java?

The default for one who holds a reference to an enum without setting a value would be null (either automatically in case of a class field, or set by the user explicitly).

Can you use == for enums?

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant.

What is ordinal in enum?

ordinal() tells about the ordinal number(it is the position in its enum declaration, where the initial constant is assigned an ordinal of zero) for the particular enum.


2 Answers

The implicit access level of a manually declared field in an enum is package-private, exactly the same as it in normal classes. Thus your sound field will be accessible if and only if Animals and TestEnum are in the same package.


I tried to find a solid quote for this in the JLS but the enum rules are unfortunately scattered all over the place, specified as exceptions to the rules for normal classes, and the rules thus have to be assembled from pieces. JLS §6.6.1 Determining Accessibility says:

A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:

  • If the member or constructor is declared public, then access is permitted.

    All members of interfaces lacking access modifiers are implicitly public.

  • Otherwise, if the member or constructor is declared protected, then access is permitted only when one of the following is true:

    • Access to the member or constructor occurs from within the package containing the class in which the protected member or constructor is declared.

    • Access is correct as described in §6.6.2.

  • Otherwise, if the member or constructor is declared with package access, then access is permitted only when the access occurs from within the package in which the type is declared.

    A class member or constructor declared without an access modifier implicitly has package access.

  • Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

This means that class types (class and enum) get the rule that members implicitly have package access, while interface types (interface and @interface) get the rule that members are implicitly public.

It is not immediately obvious from the above that "class member" includes enums in its definition of "class", but it does. Because of their broad overlap, the JLS groups enums with classes in many places (and annotation types get likewise grouped with interfaces). JLS §8.9 Enum Types says "An enum declaration specifies a new enum type, a special kind of class type"; and JLS §8.2 Class Members makes clear that the term "class members" means members of a "class type".

However, enums do get two special rules with regard to member accessibility that are not included in the quoted section above:

  1. The enum constants themselves (in your example they are DOG, CAT, and FISH) may not have any explicit access modifiers (JLS §8.9.1), and are always public static final fields of the enum type (JLS §8.9.3).

  2. Enum constructors must be private (to prevent people creating extra constants) and are private implicitly (JLS §8.9.2).

Apart from those two exceptions, the access rules of normal classes apply to enums. If your Animals enum is made public, it and all its constants are accessible outside the package, but the sound field is package-private, and is not accessible outside the package unless you declare it public explicitly.

like image 148
Boann Avatar answered Oct 22 '22 19:10

Boann


If you can import enum you can access enum constants

If enum is accessible (specifically declared public) outside the package it's elements are also accessible and if no modifier specified it will only be accessible inside package. By default enum constants are accessible if enum is accessible means those are public static final by default.

I would expect the code to fail to compile because of this a.DOG.sound part. But to my surprise it doesn't.

It will be same as any other variable can behave in any class if no default modifier it will be accessible inside package only.

like image 34
akash Avatar answered Oct 22 '22 18:10

akash