What's is the difference between a static and non-static annotation? - java

Java's inner classes can be static or non-static. Non-static inner classes are tied to an instance of the enclosing class.
Annotations are a type of Java interface, and like any other class, they can be defined inside a class. Similarly, they can be declared static or non-static. What is the difference between these two choices, is there any difference between how they're used by consuming code, and is there any scenario where it'd make sense to use one or the other?
Example:
public class AnnotationContainer {
public static #interface StaticAnnotation {}
public #interface NonstaticAnnotation {}
}

No difference at all. Nested interfaces are always static.
This is described in JLS Sec 8.5.1 (for classes):
A member interface is implicitly static (§9.1.1). It is permitted for the declaration of a member interface to redundantly specify the static modifier.
and JLS Sec 9.5 (for interfaces):
A member type declaration in an interface is implicitly public and static. It is permitted to redundantly specify either or both of these modifiers.

To expand a bit on Andy's correct answer that they are exactly the same because they are a special kind of interface declaration and "member interfaces" are implicitly static anyway:
JLS 10 9.6. Annotation Types:
An annotation type declaration specifies a new annotation type, a special kind of interface type. To distinguish an annotation type declaration from a normal interface declaration, the keyword interface is preceded by an at-sign (#).
JLS 10 8.5.1. Static Member Type Declarations :
A member interface is implicitly static (§9.1.1). It is permitted for the declaration of a member interface to redundantly specify the static modifier.
and JLS 10 9.1.1. Interface Modifiers
The modifier static pertains only to member interfaces (§8.5.1, §9.5), not to top level interfaces (§7.6).
Side note: interestingly, these Chapters do not use the term "nested interface" defined at the top of Chapter 9, but it seems to be a synonym for "member interface":
JLS 10 Chapter 9. Interfaces:
A nested interface is any interface whose declaration occurs within the body of another class or interface.

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.

Enums defined in a class is a static nested class?

For an enumeration defined in a class, like
class OuterClass {
public enum Method {
GET,
PUT,
POST,
DELETE;
}
}
Is the enumeration a static nested class (https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html)? It seems to be the case judging from the syntax used to refer to it. Or is it a non-static nested class (an inner class)?
The JLS says
An enum declaration specifies a new enum type, a special kind of class type.
So it looks like the word from Oracle is that enums are classes.
If you declare an enum inside another class, then yes, it's an inner class. And enums are always static, so yes, it's fair to call an enum a static inner class (or nested class) when it's declared in another class.
As per §8.9 of the JLS:
An enum declaration specifies a new enum type, a special kind of class type.
[...]
A nested enum type is implicitly static. It is permitted for the declaration of a nested enum type to redundantly specify the static modifier. [...]
The generated bytecode for the enum declaration is as follows:
// compiled from: OuterClass.java
public final static enum INNERCLASS ...
So yes, enum is a static nested class in this case - confirmation in the JLS.

What are the implicit specifier/modifiers of interface methods in Java 8?

I understand that Interface methods are implicitly public. Java Docs Tutorial says
All abstract, default, and static methods in an interface are
implicitly public, so you can omit the public modifier.
Out of abstract, static and default, which modifiers are implicitly declared in Java 8.
I thought abstract was not implicitly declared anymore as Java 8 introduced default method in interfaces, but I still get a warning in Intellij IDEA.
Modifier 'abstract' is redundant for interface methods.
public interface TestInterface {
abstract int print(); // abstract redundant ?.
int print2(); //legal.but public or public abstract ?.
}
The language spec - specifically Section 9.4, states that abstract and public are implicit.
Every method declaration in the body of an interface is implicitly public (§6.6). It is permitted, but discouraged as a matter of style, to redundantly specify the public modifier for a method declaration in an interface.
An interface method lacking a default modifier or a static modifier is implicitly abstract, so its body is represented by a semicolon, not a block. It is permitted, but discouraged as a matter of style, to redundantly specify the abstract modifier for such a method declaration.
This is why IntelliJ warns you about it; by the JLS, you're doing something completely redundant.
As a bonus, fields in interfaces are implicitly public static final:
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.
In Java 7, as well in Java 8, all fields defined in an interface are ALWAYS public, static, and final. Methods are public and abstract.
Because your print() method does not have a body, it means that is an abstract method. With other words does not need to be declared explicitly abstract, that's why Intellij IDEA says is redundant.
Methods without static or default are not implicitly abstract, even if it has a body. A non-abstract method with a body that is not default or static, cannot exist in an interface.
Access modifiers
In Java 8, we have as per Java Docs Tutorials,
All abstract, default, and static methods in an interface are
implicitly public, so you can omit the public modifier.
Thus the only allowed access modifier in an Interface as of Java 8 is public. (Java 9 introduces private interface methods)
public interface TestInterface {
int print();//compiles and no IDE warning
public int print1();//public redundant
}
Optional Specifiers
abstract - methods in an interface that are not declared as default or static are implicitly abstract, so the abstract modifier is optional. But the method implementation must not be provided in such case.
static- static needs to be explicitly specified and implementation provided.
final - A final methods can't be overridden and is not allowed for an interface method.
default - method can be explicitly declared default if the default implementation is provided.
All fields in Interfaces are public, static and final.

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

Categories