Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous-Inner classes showing incorrect modifier

To my understanding, the following code should have printed true as output.

However, when I ran this code it is printing false.

From Java docs of Anonymous Classes 15.9.5. :

An anonymous class is always implicitly final

public class Test {     public static void main(String args[]) {         Object o = new Object() {         };         System.out.println("Annonymous class is final: " + Modifier.isFinal(o.getClass().getModifiers()));     } } 

Why this code is behaving like this ?

like image 629
Sachin Sachdeva Avatar asked Jan 03 '19 09:01

Sachin Sachdeva


People also ask

How do you define anonymous inner class?

Java anonymous inner class is an inner class without a name and for which only a single object is created. An anonymous inner class can be useful when making an instance of an object with certain "extras" such as overloading methods of a class or interface, without having to actually subclass a class.

Is an anonymous class an inner class?

Anonymous classes are inner classes with no name. As a result, we have to declare and instantiate anonymous classes in a single expression at the point of use. We may either extend an existing class or implement an interface.

Can inner class instantiate anonymously?

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.


2 Answers

Note that the wording in the JLS of that particular section has changed significantly since then. It now (JLS 11) reads:

15.9.5. Anonymous Class Declarations:

An anonymous class is never final (§8.1.1.2).

The fact that an anonymous class is not final is relevant in casting, in particular the narrowing reference conversion allowed for the cast operator (§5.5). It is also of interest in subclassing, in that it is impossible to declare a subclass of an anonymous class, despite an anonymous class being non-final, because an anonymous class cannot be named by an extends clause (§8.1.4).

This change in wording was introduced in JLS 9. The semantics of anonymous classes and the behavior of the methods in the question remained mostly unchanged, the intention was to avoid exactly the kind of confusion this question is about.

The ticket that caused the change says:

Longstanding behavior of javac, since 1.3, has been, for the most part, not to treat the classes as 'final'. To address this inconsistency, the specification should be changed to accurately reflect the reference implementation.

Specifically, anonymous classes are almost never generated with the ACC_FINAL flag set. We can't change this longstanding behavior without impacting some serialization clients (this would be permissible, but is unnecessarily disruptive). And we can't faithfully implement Class.getModifers (which promises to provide the "Java language modifiers") without the class files encoding the language's modifiers.

However, the change did actually change semantics to some degree, and this was also documented in this ticket as an acceptable impact:

The change impacts the set of legal programs, in that it allows some casts that would be considered illegal under the current specification (see JDK-6219964). But, after searching for mentions of 'final' classes in JLS, I don't anticipate any other impact, meaning that this is a source-compatible fix.

like image 133
Hulk Avatar answered Sep 28 '22 04:09

Hulk


An anonymous class is never final (§8.1.1.2).

JLS 11 - 15.9.5. Anonymous Class Declarations

I didn't know the reasoning behind this, but, according to @Hulk's answer and this bug report, it seems the specification of previous versions slightly misled us saying that anonymous classes are final.

like image 33
Andrew Tobilko Avatar answered Sep 28 '22 05:09

Andrew Tobilko