47 votes

Classes internes anonymes Affichage de l'indicateur incorrect

À ma compréhension, le code suivant aurait dû afficher true en sortie.

Cependant, lorsque j'ai exécuté ce code, il affiche false.

À partir de la documentation Java de Classes Anonymes 15.9.5. :

Une classe anonyme est toujours implicitement finale

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

Pourquoi ce code se comporte-t-il de cette manière ?

0 votes

0 votes

@miken32 J'ai annulé le vote de fermeture sur votre suggestion, car les réponses à cette question sont bien plus claires que sur la question que vous avez suggérée.

50voto

Hulk Points 2145

Notez que le libellé dans la JLS de cette section particulière a changé de façon significative depuis lors. Il se lit désormais (JLS 11) :

15.9.5. Déclarations de classes anonymes:

Une classe anonyme n'est jamais finale (§8.1.1.2).

<em>Le fait qu'une classe anonyme ne soit pas finale est pertinent en matière de cast, en particulier la conversion de référence rétrécissante autorisée pour l'opérateur cast (<a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-5.html#jls-5.5" rel="noreferrer">§5.5</a>). Cela est également intéressant en matière de sous-classe, car il est impossible de déclarer une sous-classe d'une classe anonyme, malgré le fait qu'une classe anonyme ne soit pas finale, car une classe anonyme ne peut pas être nommée par une clause extends (<a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.1.4" rel="noreferrer">§8.1.4</a>).</em>

Ce changement de libellé a été introduit dans la JLS 9. Les sémantiques des classes anonymes et le comportement des méthodes dans la question sont restés principalement inchangés, l'intention étant d'éviter exactement le type de confusion à propos duquel porte cette question.

Le ticket ayant causé le changement indique :

Le comportement de longue date de javac, depuis 1.3, a été, pour la plupart, de ne pas considérer les classes comme 'final'. Pour remédier à cette incohérence, la spécification devrait être modifiée pour refléter avec précision l'implémentation de référence.

En particulier, les classes anonymes sont presque jamais générées avec le drapeau ACC_FINAL défini. Nous ne pouvons pas changer ce comportement de longue date sans impacter certains clients de sérialisation (ceci serait autorisé, mais perturberait inutilement). Et nous ne pouvons pas implémenter fidèlement Class.getModifers (qui promet de fournir les "modificateurs de langage Java") sans que les fichiers de classe codent les modificateurs du langage.

Cependant, le changement a effectivement modifié les sémantiques dans une certaine mesure, et cela a également été documenté dans ce ticket comme un impact acceptable :

Le changement influence l'ensemble des programmes légaux, en ce sens qu'il permet certains casts qui seraient considérés illégaux selon la spécification actuelle (voir JDK-6219964). Mais, après avoir recherché des mentions de classes 'final' dans la JLS, je n'anticipe aucun autre impact, ce qui signifie que ceci est une correction compatible avec les sources.

10voto

Andrew Tobilko Points 1283

Une classe anonyme n'est jamais final (§8.1.1.2).

JLS 11 - 15.9.5. Déclarations de classes anonymes

Je ne connaissais pas la raison derrière cela, mais, selon la réponse de @Hulk et ce rapport de bug, il semble que la spécification des versions précédentes nous ait un peu induits en erreur en affirmant que les classes anonymes sont finales.

9voto

Eran Points 35360

Les classes anonymes sont considérées implicitement final car vous ne pouvez pas créer de sous-classes d'elles. Cela ne signifie pas que le modificateur FINAL doit être défini pour les classes anonymes.

0 votes

Lorsque vous dites implicitement final, cela ne signifie-t-il pas que c'est FINAL et que cela devrait suivre toutes les règles du mot-clé final en java

1 votes

@ShowStopper eh bien, il suit effectivement les règles de final : vous ne pouvez pas les sous-classer, car il n'y a aucun moyen de les référencer en tant que type. Je suppose que c'est pourquoi ils sont implicitement finals.

-2voto

Prasad Karunagoda Points 1878

Voir la Javadoc de Class.getModifiers() : [https://docs.oracle.com/javase/10/docs/api/java/lang/Class.html#getModifiers()](https://docs.oracle.com/javase/10/docs/api/java/lang/Class.html#getModifiers())

Il est indiqué "...Les valeurs de ses autres modificateurs ne sont pas déterminées par cette spécification".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X