Anonymous inner classes and Final modifier

As far as I understand correctly anonymous classes always final :

This was mentioned specifically in JLS 15.9.5

However, when I run the following code to verify that it shows that the Inner class is not final .

  public class Test{ static class A<T> { } public static void main(String arg[]) { A<Integer> obj = new A() { }; if ((obj.getClass().getModifiers() & Modifier.FINAL) != 0) { System.out.println("It is a final " + obj.getClass().getModifiers()); } else { System.out.println("It is not final " + obj.getClass().getModifiers()); } } } 

The output of the program above:

 It is not final 0 

Please clear my doubts as I cannot understand this behavior.

+7
java
source share
3 answers

Explicit is what is written in the source code. So, if something is declared as a public final class , it means that the class is clearly final.

Implicit - this is something that is not written in the source code, but that in the context of a certain construction or based on language rules, the element behaves as it was declared with the specified modifier.

For example, the enum keyword in the enum SomeEnum { } calls SomeEnum as final , because language rules SomeEnum it. Its effect matches that of the final keyword.

An example of an anonymous class that is implicitly final is the lack of a language construct for overriding an anonymous class. Therefore, it behaves as if it were final . I think the word effective is better here.


However, you cannot make assumptions based on how things reflect. Consider the following snippet:

 public class Test { interface SomeInterface { } abstract interface SomeAbstractInterface { } static abstract class SomeAbstractClass { } enum SomeEnum { } public static void main(String arg[]) { System.out.println(Modifier.toString(SomeInterface.class.getModifiers())); System.out.println(Modifier.toString(SomeAbstractInterface.class.getModifiers())); System.out.println(Modifier.toString(SomeAbstractClass.class.getModifiers())); System.out.println(Modifier.toString(SomeEnum.class.getModifiers())); } } 

The result is the following:

 abstract static interface abstract static interface abstract static static final 

Both interface and abstract interface are considered an abstract interface. They are also considered static when reflected. Apparently, in the process of parsing and compiling the Java source code, some modifiers can be removed or added.

+1
source share

I agree that this may be considered a mistake, given that other cases in JLS exhibit different behavior. The fact is that this is an interface: according to section 9.1.1.1 :

Each interface is implicitly abstract .

And when running below:

 interface X { void foo(); } public static void main(String arg[]) { System.out.println(Modifier.isAbstract(X.class.getModifiers())); } 

It returns true.

Another example is an enumeration in which JLS indicates :

An enum declaration is implicitly final if it contains at least one enumeration constant that has a class body

And the example below is perfectly aligned with it.

 enum X { } public static void main(String arg[]) { System.out.println(Modifier.isFinal(X.class.getModifiers())); // true } 
+3
source share

JLS 15.9.5 "... implicitly final" ... But it is not "final", it is understood that you simply cannot extend the anonymous class. There is no syntax for this, but the class is not marked final.

0
source share

All Articles