2013-01-05 3 views
11

リフレクションを使用しているときに興味深いものが見つかりました。私は単純なクラスとその修飾子のコンストラクタを取得しようとしました。ここで予期しない "一時的な"コンストラクタの修飾子

public class Test { 
    public Test(Object... args) {} 
} 

はコンストラクタ修飾子を取得するためのコードです:

Class<?> clazz = Test.class; 
Constructor<?>[] ctors = clazz.getDeclaredConstructors(); 
for (Constructor<?> ctor : ctors) {   
    int mod = ctor.getModifiers(); 
    /*if not package-private modifier*/ 
    if(mod!=0) { 
     System.out.println(Modifier.toString(mod))); 
    } 
} 

結果は次のとおりです。私は変数ではないパラメータが、ちょうど配列をコンストラクタに渡すと

public transient 

、それは大丈夫です。

public class Test { 
    public Test(Object[] args) {} 
} 

結果は:

public 

同じに関係なく、コンストラクタ剤(パブリック、保護、プライベート)またはパラメータタイプ(プリミティブまたは参照)の起こります。どのようにすることができますが、 "一時的な"コンストラクタの有効な修飾子ではないのですか?

答えて

17

アクセス修飾子は、クラスファイル内のビットマスクとしてエンコードされます。 JVM仕様では、メソッド修飾子またはフィールド修飾子のどちらに現れるかによって、ビットのいくつかに異なる意味が割り当てられます。ビット7(0x0080)はそのようなビットの1つです。

For methods

ACC_VARARGS 0x0080 Declared with variable number of arguments. 

For fields

ACC_TRANSIENT 0x0080 Declared transient; not written or read by a persistent 
         object manager. 

あなたが方法を見ているので、この修飾子の正しい解釈はACC_VARARGSないACC_TRANSIENTです。

しかし、Modifierクラスは、JVM仕様で定義されている修飾子のサブセットを扱うことしかできません。それにかかる時間はintなので、ACC_VARARGSACC_TRANSIENTを区別することはできません。

+1

これは 'toString'メソッドのバグとしてカウントされますか? –

+1

@JanDvorak:わかりません。物事が進むにつれ、 'Modifier'クラスはJVM仕様で定義されている修飾子のサブセットを扱うことができます(同じビット値を持つ修飾子を区別することはできません)。 – NPE

+1

私は疑問に思っています - 実際にビット値が衝突するのはなぜですか? JVM開発者からの監視ではありませんか? –

関連する問題