Why are enums in java public and static implicitly by nature? [duplicate] - java

This question already has answers here:
Are instances of enums static by default?
(2 answers)
Closed 7 months ago.
I have been recently studying java enums and couldn't understand why they are implicitly public and static by nature. final I understand because they are constants but why the other tags?

If you would look at Java documentation, it is clearly mentioned that:
Programmers can not invoke constructors of enum.
which basically means that we can not create any object of enum using the keyword new. Now if enums weren't static, then how would we access them without any instance/object?
enum Color { RED, GREEN, BLUE; } // enum declaration
Color.RED //accessing enum constant
If you have noticed only have to access enum constants is through enum name (similar to how we access static members of any class).
So to be able to access enum constants without any object we need them to be static.
And enums are by default public so that we can freely access them anywhere however this is not a necessity we can use private or protected modifiers as well.

I have been recently studying Java enums and couldn't understand why they are implicitly public and static by nature.
final I understand because they are constants but why the other tags?
It is complicated, but I think you have some of the facts incorrect there.
According to the Java 17 Language Specification (JLS 8.9)
"It is a compile-time error if an enum declaration has the modifier abstract, final, sealed, or non-sealed."
See below.
"A NESTED enum class is implicitly static. That is, every member enum class and local enum class is static."
And non-nested classes are implicitly static too.
"It is a compile-time error if ... an enum declaration has MORE THAN ONE OF the access modifiers public, protected, and private (§6.6)."
But that is the same as any other class. This doesn't say that it is implicitly public.
"An enum class is either implicitly final OR implicitly sealed ..."
There is something rather subtle going on here. If an enum constant has a class body, then it actually defines an anonymous subclass of the enum class. In this case, the enum class is not final in the sense of "having no subclasses"
So:
Enum classes are NOT implicitly public. They can be private, for example.
Enum classes MAY BE implicitly final in the "has no subclasses" sense. But you were using final in the "constantness" sense. The binding between an enum constant name and the corresponding value cannot change; i.e. it is implicitly final in that sense.
However, the enum values can have mutable fields, so they are not necessarily constant in the sense that 42 is a constant. Just like you can change the array content with the following "constant":
final int[] CONST = new int[]{1, 2, 3};
Enum classes ARE implicitly static in contexts where another class could be non-static.
Why are they implicitly static? Well if they weren't, what would it mean? An implicitly static enum is effectively a set of singleton values. But it it wasn't, then each time you created an instance of the class that enclosed the enum class, you would be creating a new set of enum values. They are no longer singleton. This would be most unexpected ... and I am finding it hard to see how it would be useful.

Related

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

This question already has answers here:
What is the difference between public, protected, package-private and private in Java?
(30 answers)
Closed 7 years ago.
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?
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:
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).
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.
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.

Is "public static final" redundant for a constant in a Java interface?

This code:
interface Config {
int MAX_CONN = 20;
}
compiled and worked as I expected. It looks like this is the same as:
interface Config {
public static final int MAX_CONN = 20;
}
Is "public static final" redundant for a constant in a Java interface? Is this true for Java 1.1, 1.2, 1.3, 1.4,..., 1.8 or did it change in a Java release?
Variables declared in Interface are implicitly public static final. This is what JLS 9.3 says :
Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.
Read through the JLS to get an idea why this was done.
Look at this SO answer:
Interface variables are static because Java interfaces cannot be instantiated in their own right; the value of the variable must be assigned in a static context in which no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
Interface : System requirement service.
In interface, variable are by default assign by public,static,final access modifier. Because :
public : It happen some-times that interface might placed in some other package. So it need to access the variable from anywhere in project.
static : As such incomplete class can not create object. So in project we need to access the variable without object so we can access with the help of
interface_filename.variable_name
final : Suppose one interface implements by many class and all classes try to access and update the interface variable. So it leads to inconsistent of changing data and affect every other class. So it need to declare access modifier with final.
Interface variables are implicitly static and final because Java interfaces cannot be instantiated on their own.
Interfaces are declared using the interface keyword, and may only contain method signature and constant declarations (variable declarations that are declared to be both static and final). An interface may never contain method definitions.
http://en.wikipedia.org/wiki/Interface_(Java)
Interface variables are static because Java interfaces cannot be instantiated in their own right. Value of the variable must be assigned in a static context - no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
Interface variables are always static and final.
If the interface has to be refactored to a class, it may be more practical to keep the redundant public static final, though. (This sounds odd, because each IDE flags those as redundant information).
EDIT To be fair: One would not do this without changing lots of other places (as interfaces are using implements, while inheriting from classes use extends)
EDIT#2 In fact, constant interface(s) can be considered to be an anti-pattern, please see on wikipedia - Constant Interface

static final methods in enum

So I have looked around google and SO , I cannot find a example or explanation of : What is the purpose of static final methods in enum?
What I understand :
Methods declare static can be accessed like function/procedural languages.
final means you can't override it. Can't change the reference. As assylias pointed out in comments static can't be overridden either.
enums can't be subclassed, explained here.
So what's the point of static final methods in enums if it will never be overridden since there won't be a subclass?
By making a static method final, you prevent it from being hidden (only instance methods can be overriden) by a subclass.
Since enum can't be subclassed, making a static method final is superfluous but not forbidden.
Note: technically, each enum constant that has a class body implicitly defines an anonymous class that extends the enum. But since inner classes may not declare static methods, the static final method could not be hidden in such a constant's class body.
It's easy to see why static methods make sense, so I guess the question is about the final modifier.
final serves no purpose here, except maybe make the code a bit easier to read, but not by much.
It's similar to the way interface methods are often written as public void foo();, even though interface members are always public anyway.
In Java Enum types are used to represent fixed set of constants and making it static final helps its initialisation only once, single copy to be shared across all instances, accessing the variable with the class name and with final its more like a read-only
When you declare instances of an enum you can override the enum's methods, essentially enum instances are implemented as (or thought of) as subclasses. static methods can't be overridden in any case but the implication in the OP and other answers that final is superfluous for an enum is false.

Does enum means static class?

I have a confusion here.
If I cannot declare a class as static, how does enum works?
It looks like a static class, because it gets instantiated itself and can be called anywhere.
Looks like I can use enum almost like other static fields.
Is it safe to use enum?
enum types are automatically static. You can't have a non-static enum, so the static is implied.
JLS 8.9:
Nested enum types are implicitly static. It is permissible to explicitly declare a nested enum type to be static.
Each enum which you are declaring inside an enum type is static member of your enum type.And the type of your enum variables is the type of your enum,in short they are self typed.

Why can't a Java enum be final?

public interface Proposal {
public static final enum STATUS {
NEW ,
START ,
CONTINUE ,
SENTTOCLIENT
};
}
Java does not allow an enum to be final inside an interface, but by default every data member inside an interface is public static final. Can anybody clarify this?
Java does not allow you to create a class that extends an enum type. Therefore, enums themselves are always final, so using the final keyword is superfluous.
Of course, in a sense, enums are not final because you can define an anonymous subclass for each field inside of the enum descriptor. But it wouldn't make much sense to use the final keyword to prevent those types of descriptions, because people would have to create these subclasses within the same .java file, and anybody with rights to do that could just as easily remove the final keyword. There's no risk of someone extending your enum in some other package.
An enum can't be final, because the compiler will generate subclasses for each enum entry that the programmer has explicitly defined an implementation for.
Moreover, an enum where no instances have their own class body is implicitly final, by JLS section 8.9.
Two things:
enums are final subclasses of java.lang.Enum
if an enum is a member of a class, it is implicitly static
No point in declaring enum final. Final for classes means that they can not be inherited. However, enums can not be inherited by default (that is they are final).
The final thing is valid only for variables. However you should think of the enums more like data types than variables.

Categories