2009-08-10 21 views
3

私は、この構造を反映させて、変更できないクラスのセットにアクセスする以外に選択肢はありませんでした。 ただし、以下のmainメソッドに示されているメソッドを使用すると、NullPointerExceptionがスローされます。 f1.get(null)が呼び出されたときに、NULLポインタがコンストラクタの "table"になります。Javaクラスの静的変数に反射的にアクセスする

唯一のコンストラクタがプライベートであるため、クラスを事前にインスタンス化できません。だから明示的にテーブルを設定する方法はありません。

私がLegacy.Aと反射的に電話する方法を知っている人は誰ですか?

public class Legacy { 
    public static final Legacy A = new Legacy("A"); 
    public static final Legacy B = new Legacy("B"); 

    private String type0; 
    private static Map<String, Legacy> table = new HashMap<String, Legacy>(); 

    private Legacy(String id) { 
     type0 = id; 
     table.put(type0, this); 
    } 

    public static void main(String[] args) throws Exception { 
     Field f1 = Legacy.class.getDeclaredField("A"); 
     Object o = f1.get(null);  
    } 
} 

"Reflection == BAD !!!"

+0

実際には、NPE、反射でもなくても、あなたがLegacy.Aにアクセスできる方法は見えません(この反射コードを 'Object o = Legacy.A'で置き換えてください)。あなたのコードを実行しようとしたとき、例外はクラスの初期化中に起こりました。 – kdgregory

+0

これは、保存時に自動フォーマットされたコードを持つために得られるものです。 – Andrew

答えて

7

静的初期化子の順序が間違っているため、コンストラクタが呼び出される前にテーブルが必要です。

これは、クラスが読み込まれて初期化されたときに例外が発生する理由です。これは反射とは関係ありません。

0

あなたの例に何が間違っているか分からないので、これを試しました。宣言を並べ替えると、うまくいった:

import java.lang.reflect.Field; 
import java.util.HashMap; 
import java.util.Map; 

public class Legacy { 
    private String type0; 
    private static Map< String, Legacy > table = new HashMap< String, Legacy >(); 

    private Legacy(String id) { 
     type0 = id; 
     table.put(type0, this); 
    } 
    public static final Legacy A = new Legacy("A"); 
    public static final Legacy B = new Legacy("B"); 

    public static void main(String[] args) throws Exception { 
     Field f1 = Legacy.class.getDeclaredField("A"); 
     Object o = f1.get(null); 
    } 
} 

静的宣言には(先行の)コンストラクタが必要です。これは混乱の元ですので

4

、私はこのようにそれを記述します。

public class Legacy { 
     static { 
      table = new HashMap<String, Legacy>(); 
      A = new Legacy("A"); 
      B = new Legacy("B"); 
     } 

     public static final Legacy A; 
     public static final Legacy B; 

     private String type0; 
     private static Map<String, Legacy> table; 

     private Legacy(String id) { 
       type0 = id; 
       table.put(type0, this); 
     } 

    public static void main(String[] args) throws Exception { 
       Field f1 = Legacy.class.getDeclaredField("A"); 
       Object o = f1.get(null);   
     } 
} 

この方法は、メンバーが(原因リファクタリング、ラインアライメントまたは任意の)場所を変更した場合でも、コードが常に動作します。

関連する問題