web-dev-qa-db-ja.com

不正な修飾子を示す匿名内部クラス

私の理解では、次のコードは出力としてtrueを出力しているはずです。

ただし、このコードを実行すると、falseが出力されます。

Javaのドキュメント 匿名クラス15.9.5。 から:

匿名クラスは常に暗黙的に最終です

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()));
    }
}

なぜこのコードはこのように動作しているのですか?

45
Joker

それ以降、その特定のセクションのJLSの表現が大幅に変更されていることに注意してください。現在(JLS 11)は次のようになっています。

15.9.5。匿名クラス宣言

匿名クラスは決して最終的なものではありません( §8.1.1.2 )。

匿名クラスがfinalではないという事実は、キャスト、特にキャスト演算子に許可されているナローイング参照変換( §5.5 )に関連しています。匿名クラスはfinal節では名前を付けることができないため、匿名クラスはfinalではないので、匿名クラスのサブクラスを宣言することは不可能であるという点で、サブクラス化にも関心があります( §8.1。 4 )。

この表現の変更はJLS 9で導入されました。匿名クラスのセマンティクスと質問のメソッドの動作は変更されていません。この質問に関する混乱の種類を正確に回避することが目的でした。

変更を引き起こしたチケット は言う:

1.3以降のjavacの長年の動作は、ほとんどの場合、クラスを「最終」として扱うnotです。この不整合に対処するには、リファレンス実装を正確に反映するように仕様を変更する必要があります。

特に、ACC_FINALフラグが設定された匿名クラスはほとんど生成されません。一部のシリアル化クライアントに影響を与えずに、この長期にわたる動作を変更することはできません(これは許容されますが、不必要に混乱を招きます)。また、言語の修飾子をエンコードするクラスファイルなしでClass.getModifers(「Java言語修飾子」を提供することを約束)を忠実に実装することはできません。

47
Hulk

匿名クラスは決してfinal§8.1.1.2 )にはなりません。

JLS 11-15.9.5。匿名クラス宣言

私はこれの背後にある理由を知りませんでしたが、@ Hulkの回答と このバグレポート によれば、以前のバージョンの仕様は匿名クラスが最終であるとわずかに誤解しているようです。

10
Andrew Tobilko

匿名クラスはサブクラスを作成できないため、暗黙的にfinalと見なされます。これは、Modifier.FINAL修飾子は匿名クラスに設定する必要があります。

9
Eran