web-dev-qa-db-ja.com

ModifierクラスのisAbstract()によって返される誤った結果

私の理解では、次のコードはFalseを出力するはずですが、このコードを実行するとTrueが出力されます。

From Java docs:

整数の引数に抽象修飾子が含まれる場合はtrueを、含まれない場合はfalseを返します。

public class Test{
    public static void main(String[] args) {
        System.out.println(Modifier.isAbstract(byte[].class.getModifiers())); 
    }
}

誰かがこの動作を理解するのに役立ちますか?

47
Joker

int Java.lang.Class.getModifiers() のJavadocは、配列の一部の修飾子に対して何を返すかを指定しますタイプ(たとえば、final修飾子はtrueである必要があり、interface修飾子はfalseである必要があります)。一方、配列型に対してabstractまたはstatic修飾子をどのように指定するかは指定しません。つまり、trueまたはfalseを返す決定は文書化されていません。 JDKで。したがって、どの実装でもtrueまたはfalseを返すことを選択できます。

int Java.lang.Class.getModifiers()

このクラスまたはインターフェースのJava言語修飾子を整数でエンコードして返します。修飾子は、パブリック、保護、プライベート、最終、静的、抽象、およびインターフェイスのJava仮想マシンの定数で構成されています。クラスModifierのメソッドを使用してデコードする必要があります。

基礎となるクラスが配列クラスである場合、そのpublic、private、およびprotected修飾子は、そのコンポーネントタイプの修飾子と同じです。このクラスがプリミティブ型またはvoidを表す場合、そのpublic修飾子は常にtrueであり、protectedおよびprivate修飾子は常にfalseです。 このオブジェクトが配列クラス、プリミティブ型またはvoidを表す場合、その最終修飾子は常にtrueであり、インターフェース修飾子は常にfalseです。 他の修飾子の値は、この仕様では決定されません。

修飾子のエンコードは、Java仮想マシン仕様、表4.1で定義されています。

49
Eran

この動作のヒントは、JLSで見つけることができます 10.8。配列のクラスオブジェクト

すべての配列には関連するClassオブジェクトがあり、同じコンポーネントタイプの他のすべての配列と共有されます。

配列型はクラスではありませんが、すべての配列のClassオブジェクトは次のように機能します:[snipped]

この理由では、配列は「実際の」クラスではないため、確実に具体的なクラスではありません。同じロジックが抽象と見なされるint.classにも適用されます。

6
Mureinik

abstract の定義は次のとおりです。

抽象クラスは、不完全な、または不完全と見なされるクラスです。

[]のような純粋な配列がある場合、コンポーネントタイプが提供されないため、実際には不完全になります。

これは、 15.10.1。配列作成式 の仕様に違反します。

ClassOrInterfaceTypeが再定義可能な型を示さない場合、コンパイル時エラーです。

それは単に再定義可能な型を示すのではなく、まったく型を示しません。したがって、抽象クラスの場合と同様に、[]のインスタンスを作成することはできません。

純粋な配列[]がないため、これは単なる推測にすぎません。さらに、byte[]の修飾子が返されました。 Eran で示される仕様のままです。

3
LuCio

私の説明では、配列はabstractと見なされます。これは、配列がJVM自体によってインスタンス化されるためです。

どの配列タイプにも具体的なクラスは存在しません。

配列には JLSで定義された契約 があります。

  1. インデックスのアクセシビリティ
  2. CloneableおよびSerializableの実装

しかし、言語自体を除いて誰もそれらを満たすことはできません。なぜなら、私たちは実際に実装を宣言することはできないからです。

2
Lino

私の理解から、Java getModifier() の言語仕様は:

基になるクラスが配列クラスである場合、public、private、およびprotected修飾子は、そのコンポーネント型の修飾子と同じです。このクラスがプリミティブ型またはvoidを表す場合、そのpublic修飾子は常にtrueであり、protectedおよびprivate修飾子は常にfalseです

現在、他の修飾子の値は、この仕様によって決定されていません。 [〜#〜] abstract [〜#〜]

JVMS表4.1-Aから:

ACC_ABSTRACT 0x0400宣言された要約;インスタンス化しないでください。

2
Joker