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

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.

Related

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

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.

declare java class as private trigger compilation error

According to java tutorial https://docs.oracle.com/javase/tutorial/java/javaOO/classdecl.html
You can also add modifiers like public or private at the very
beginning—so you can see that the opening line of a class declaration
can become quite complicated. The modifiers public and private, which
determine what other classes can access MyClass, are discussed later
in this lesson. The lesson on interfaces and inheritance will explain
how and why you would use the extends and implements keywords in a
class declaration. For the moment you do not need to worry about these
extra complications.
In general, class declarations can include these components, in order:
Modifiers such as public, private, and a number of others that you will encounter later.
The class name, with the initial letter capitalized by convention.
The name of the class's parent (superclass), if any, preceded by the keyword extends. A class can only extend (subclass) one parent.
A comma-separated list of interfaces implemented by the class, if any, preceded by the keyword implements. A class can implement more
than one interface.
The class body, surrounded by braces, {}.
But the compiler complain with a message Modifier 'private' not allowed here when declare a class (top level class) with private modifier.
this is my code
private class MyPrivateClass {
}
and the error message in compilation
1: error: modifier private not allowed here
From section 8.1.1 of the Java Language Specification (JLS):
The access modifiers protected and private pertain only to member classes within a directly enclosing class or enum declaration.
In other words, a private class is only allowed if it is enclosed within another class.

Accessing own private fields of subclass object

Just found this construction does not compile:
class A {
private int data;
public static int process(B b) {
return b.data;// error here: 'data has private access in A'
}
}
class B extends A {}
Of course this problem can be solved easily manually (cast b to A, make field protected, etc.). But the question is, why java does not allow such construction? I thought that compiler must know that B is a subclass of A, so methods of A must have access to A's private fields.
The only possible problem I can think of is if B has its own 'data' field, compiler must not know which field we want to access, but that's what inheritance is for, right?
Well, the compiler doesn't allow it because the language specification doesn't allow it. JLS section 8.3 (field declarations) specifies (emphasis mine):
A class inherits from its direct superclass and direct superinterfaces all the non-private fields of the superclass and superinterfaces that are both accessible to code in the class and not hidden by a declaration in the class.
A private field of a superclass might be accessible to a subclass - for example, if both classes are members of the same class. Nevertheless, a private field is never inherited by a subclass.
So looking up the field as a member of the subclass (6.5.6.2) must fail - the compiler is being slightly helpful in explaining why it's failed rather than just saying the member doesn't exist, but I believe that in a pure sense, the look up should just say "Type B doesn't have a member called data" rather than complaining that it's inaccessible.
As for why the language was designed that way - I'm not sure. The equivalent code in C# is fine, and it makes perfect sense to me. For example, in the C# 5 specification, section 3.4:
When a type inherits from a base class, all members of the base class, except instance constructors, destructors and static constructors, become members of the derived type. The declared accessibility of a base class member does not control whether the member is inherited—inheritance extends to any member that isn't an instance constructor, static constructor, or destructor. However, an inherited member may not be accessible in a derived type, either because of its declared accessibility (§3.5.1) or because it is hidden by a declaration in the type itself (§3.7.1.2).

The use of visibility modifiers in Java

class Orange{
Orange(){
}
}
What is the difference between the usage of the modifier - in this case, package-private - in front of the class and in front of the constructor? I think the modifier in front of the constructor means it is allowed to instantiate an instance of the class Orange. But what about the modifier in front of the class?
To start with there are 4 access levels created by 3 access modifiers.
public - accessible everywhere
protected - accessible in the same package and in the children
default - accessible only in the same package
private - accessible only in the same class.
You are correct about - Modifiers at the level of constructors are directly related to the instantiation of the class.
Modifiers at the level of Class decide the accessibility of the Class.
First, to assuage any fears, the code you've provided is perfectly valid Java syntax.
In effect, you've created a class that can only be instantiated/used by other classes in the default package. It would also work if you defined it in a package (e.g. package foo;) since only the classes in package foo could see this class).
Now, to the crux of the question.
There are different ways to control access to fields and members. and they each do different things.
private visibility is the least visible. Only the defining class can access the field.
No modifier, or package private is the second least visible. The defining class and all classes within the package may access the field, but subclasses and the rest of the world cannot.
protected is the second most visible. Only other classes are prohibited from accessing the field.
public is the most visible. Everything can access the field.
Modifiers at the level of the class get interesting. This comes from the Java Language Specification, §8.1.1:
The access modifier public (§6.6) pertains only to top level classes
(§7.6) and to member classes (§8.5), not to local classes (§14.3) or
anonymous classes (§15.9.5).
The access modifiers protected and private (§6.6) pertain only to
member classes within a directly enclosing class or enum declaration
(§8.5).
The modifier static pertains only to member classes (§8.5.1), not to
top level or local or anonymous classes.
It is a compile-time error if the same modifier appears more than once
in a class declaration.
If two or more (distinct) class modifiers appear in a class
declaration, then it is customary, though not required, that they
appear in the order consistent with that shown above in the production
for ClassModifier.
In general, a class declaration appears something like this:
ClassDeclaration:
NormalClassDeclaration
EnumDeclaration
NormalClassDeclaration:
ClassModifiers(opt) class Identifier TypeParameters(opt)
Super(opt) Interfaces(opt) ClassBody
Anything with (opt) is considered optional.
So, what does this pare down to?
The JLS mandates that a class does not need a [class] modifier.
The JLS mandates that, if a [class] modifier is present, then it follows one of these rules:
If the modifier is public, then it is only applicable to top level classes and member classes.
If the modifier is protected or private, then it is only applicable to member classes within a directly enclosing class or enumeration.
The static modifier may appear, but is only applicable to member classes.
Constructors have a similar rule set.
ConstructorDeclaration:
ConstructorModifiers(opt) ConstructorDeclarator
Throws(opt) ConstructorBody
ConstructorDeclarator:
TypeParameters(opt) SimpleTypeName ( FormalParameterList(opt) )
Again, this breaks down to:
The JLS mandates that a constructor does not need a [constructor] modifier.
The JLS mandates that a constructor modifier cannot contain abstract, static, final, native, strictfp, or synchronized.
The JLS mandates, if no access modifier is specified for the constructor of a normal class, the constructor has default access (§8.8.3, emphasis mine).
You can only declare a public or default class (in case of top level classes only) in Java and these modifiers decide the accessiblity of the class.
I also suggest you to see "Why can't a class or an interface receive private or protected access modifiers?"
Now as for as constructor concerns, a constructor will have aaccess-control of type default when no access-modifier is defined explicitly. So this constructor will have a Package Level Access. Only those class which are defined within that package as that of the class with this default constructor will be able to access it. See "Aren't Java constructors public by default?"
If the constructor is made private, then only the code within that class can access this.
For a better understanding of modifiers, you need to see "Access Modifiers In Java"
Modifier of class defines who can access the class. For example public class can be accessed by classes from any package, if no modifier is written the class can be accessed by classes from the same package only.
Modifier of constructor, method and field has the same meaning. However private and protected have more sense. Private can be accessed from the current class only. Protected from its subclasses as far as from just classes from the same package.
Concerning to your question about constructor. Class can have several constructors. Some of them can be private, some other public. You are right that there is no sense to make constructor public if class is package protected: no-one outside package can call this class anyway.
This is exactly like writing public constructors for abstract classes. Since abstract class cannot be instantiated itself its constructors should be protected or private although compiler does not care about this.
BTW using default package is not commonly used and not recommended technique.
The use and types of class level modifiers:
http://javapapers.com/core-java/access-modifiers-in-java-explain/
The use and types of constructor level modifiers:
http://www.careercup.com/question?id=296844#commentThread302715
Class modifiers work similarly to method modifiers. Public, private, final, abstract, etc. work.
Public allows the class and its methods to be accessed by classes from any package.
No modifier only allows classes to be access from it's defined package.
Private would prevent all access (no point to this if using with a top-level class).
Abstract classes allow you to create child classes derived from the parent (abstract) class. For example, you can make an Abstract Shape class and have a Rectangle class extend shape, inheriting all its methods, variables, and forcing it to define any abstract methods.
Access Modifiers:
Public - {Can access anywhere in the project}
Private - {Can access only inside the class}
Protected - {Can access within the package and sub classes}
Default - {can access within the package}
Non-Access Modifiers:
Static - {for creating class variable and method}
Final - {for creating finalized variable and method}
Abstract - {for creating abstract method and class}
Synchronized - {for threads}
Some brief discussion on the above modifiers in this link. Refer it for the better understanding.
I find the best visibility level in Java to be the default visibility i.e. package visibility, because it enables unit test classes to access all the methods, if the test is placed in the same package as the main class.
Also package visibility is shorter to write since you can omit the visibility declaration, so there is less boiler plate.
The second best visibility level is protected, since in some cases you can create your test classes as sub-classes of your main class. However, as stated before, package visibility works better in most cases, if you use packages properly.
Third, typically if you run Sonar and do code review and static analysis on large projects, I have found out that typically 80% of the methods are public, and 20% are private/protected. Thus, the main idea of using private or protected methods is to protect the data/properties from being accessed by bypassing the accessors. Most of the methods will be typically public anyways.
The most useless visibility level (but unfortunately commonly used) is private as it's impossible to test (without using Reflection and modifying the visibility to something else). Also, private prohibits code re-use in sub-classes, which is the main idea of using object oriented paradigm in the first place, and thus should be avoided. For the same reasons keyword final should be avoided in most cases.
Thus, I find your example to be the best practice how to define the visibility levels, except that your constructor is not public :). However, you are missing the package declaration and unit tests.

What is the default access specifier in Java?

I just started reading a Java book and wondered; which access specifier is the default one, if none is specified?
The default visibility is known as “package-private” (though you can't use this explicitly), which means the field will be accessible from inside the same package to which the class belongs.
As mdma pointed out, it isn't true for interface members though, for which the default is "public".
See Java's Access Specifiers
The default specifier depends upon context.
For classes, and interface declarations, the default is package private. This falls between protected and private, allowing only classes in the same package access. (protected is like this, but also allowing access to subclasses outside of the package.)
class MyClass // package private
{
int field; // package private field
void calc() { // package private method
}
}
For interface members (fields and methods), the default access is public. But note that the interface declaration itself defaults to package private.
interface MyInterface // package private
{
int field1; // static final public
void method1(); // public abstract
}
If we then have the declaration
public interface MyInterface2 extends MyInterface
{
}
Classes using MyInterface2 can then see field1 and method1 from the super interface, because they are public, even though they cannot see the declaration of MyInterface itself.
If no access specifier is given, it's package-level access (there is no explicit specifier for this) for classes and class members. Interface methods are implicitly public.
The default visibility (no keyword) is package which means that it will be available to every class that is located in the same package.
Interesting side note is that protected doesn't limit visibility to the subclasses but also to the other classes in the same package
It depends on what the thing is.
Top-level types (that is, classes, enums, interfaces, and annotation types not declared inside another type) are package-private by default. (JLS §6.6.1)
In classes, all members (that means fields, methods, and nested type declarations) and constructors are package-private by default. (JLS §6.6.1)
When a class has no explicitly declared constructor, the compiler inserts a default zero-argument constructor which has the same access specifier as the class. (JLS §8.8.9) The default constructor is commonly misstated as always being public, but in rare cases that's not equivalent.
In enums, constructors are private by default. Indeed, enum contructors must be private, and it is an error to specify them as public or protected. Enum constants are always public, and do not permit any access specifier. Other members of enums are package-private by default. (JLS §8.9)
In interfaces and annotation types, all members (again, that means fields, methods, and nested type declarations) are public by default. Indeed, members of interfaces and annotation types must be public, and it is an error to specify them as private or protected. (JLS §9.3 to 9.5)
Local classes are named classes declared inside a method, constructor, or initializer block. They are scoped to the {..} block in which they are declared and do not permit any access specifier. (JLS §14.3) Using reflection, you can instantiate local classes from elsewhere, and they are package-private, although I'm not sure if that detail is in the JLS.
Anonymous classes are custom classes created with new which specify a class body directly in the expression. (JLS §15.9.5) Their syntax does not permit any access specifier. Using reflection, you can instantiate anonymous classes from elsewhere, and both they and their generated constructors are are package-private, although I'm not sure if that detail is in the JLS.
Instance and static initializer blocks do not have access specifiers at the language level (JLS §8.6 & 8.7), but static initializer blocks are implemented as a method named <clinit> (JVMS §2.9), so the method must, internally, have some access specifier. I examined classes compiled by javac and by Eclipse's compiler using a hex editor and found that both generate the method as package-private. However, you can't call <clinit>() within the language because the < and > characters are invalid in a method name, and the reflection methods are hardwired to deny its existence, so effectively its access specifier is no access. The method can only be called by the VM, during class initialization. Instance initializer blocks are not compiled as separate methods; their code is copied into each constructor, so they can't be accessed individually, even by reflection.
default is a keyword that is used as an access modifier for methods and variables.
Using this access modifier will make your class, variable, method or constructor acessible from own class or package, it will be also is set if no access modifier is present.
Access Levels
Modifier Class Package Subclass EveryWhere
public Y Y Y Y
protected Y Y Y N
default Y Y N N
private Y N N N
if you use a default in a interface you will be able to implement a method there like this exemple
public interface Computer {
default void Start() {
throw new UnsupportedOperationException("Error");
}
}
However it will only works from the 8 Java version
Official Documentation
Access Modifiers in Java
See here for more details. The default is none of private/public/protected, but a completely different access specification. It's not widely used, and I prefer to be much more specific in my access definitions.
the default access specifier is package.Classes can access the members of other classes in the same package.but outside the package it appears as private
Here is a quote about package level visibility from an interview with James Gosling, the creator of Java:
Bill Venners: Java has four access levels. The default is package. I
have always wondered if making package access default was convenient
because the three keywords that people from C++ already knew about
were private, protected, and public. Or if you had some particular
reason that you felt package access should be the default.
James Gosling: A package is generally a set of things that are kind of
written together. So generically I could have done one of two things.
One was force you always to put in a keyword that gives you the
domain. Or I could have had a default value. And then the question is,
what makes a sensible default? And I tend to go for what is the least
dangerous thing.
So public would have been a really bad thing to make the default.
Private would probably have been a bad thing to make a default, if
only because people actually don't write private methods that often.
And same thing with protected. And in looking at a bunch of code that
I had, I decided that the most common thing that was reasonably safe
was in the package. And C++ didn't have a keyword for that, because
they didn't have a notion of packages.
But I liked it rather than the friends notion, because with friends
you kind of have to enumerate who all of your friends are, and so if
you add a new class to a package, then you generally end up having to
go to all of the classes in that package and update their friends,
which I had always found to be a complete pain in the butt.
But the friends list itself causes sort of a versioning problem. And
so there was this notion of a friendly class. And the nice thing that
I was making that the default -- I'll solve the problem so what should
the keyword be?
For a while there actually was a friendly keyword. But because all the
others start with "P," it was "phriendly" with a "PH." But that was
only in there for maybe a day.
http://www.artima.com/intv/gosling2P.html
Update Java 8 usage of default keyword:
As many others have noted The default visibility (no keyword)
the field will be accessible from inside the same package to which the
class belongs.
Not to be confused with the new Java 8 feature (Default Methods) that allows an interface to provide an implementation when its labeled with the default keyword.
See: Access modifiers
There is an access modifier called "default" in JAVA, which allows direct instance creation of that entity only within that package.
Here is a useful link:
Java Access Modifiers/Specifiers
First of all let me say one thing there is no such term as "Access specifier" in java. We should call everything as "Modifiers". As we know that final, static, synchronised, volatile.... are called as modifiers, even Public, private, protected, default, abstract should also be called as modifiers . Default is such a modifiers where physical existence is not there but no modifiers is placed then it should be treated as default modifiers.
To justify this take one example:
public class Simple{  
    public static void main(String args[]){  
     System.out.println("Hello Java");  
    }  
}  
Output will be: Hello Java
Now change public to private and see what compiler error you get:
It says "Modifier private is not allowed here"
What conclusion is someone can be wrong or some tutorial can be wrong but compiler cannot be wrong.
So we can say there is no term access specifier in java everything is modifiers.

Categories