在Java类中反射访问静态变量

3
我别无选择,只能通过反射来访问一组类,而我无法修改这些类的结构。但是,使用下面main方法中所示的方法会抛出NullPointerException。在调用f1.get(null)时,空指针引用“table”会导致此错误。
我无法事先实例化这些类,因为唯一的构造函数是私有的,如所示。因此,我无法显式设置table。
有人知道我如何通过反射调用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);    
    }
}

之前的"反射 == 坏!!!"


实际上,我看不到任何可以访问Legacy.A的方法,无论是否使用反射(将反射代码替换为“Object o = Legacy.A”即可看到此情况)。当我尝试运行您的代码时,异常发生在类初始化期间。 - kdgregory
这就是我在保存时使用代码自动格式化的结果。 - Andrew
3个回答

7

静态初始化程序的顺序有误,表格必须在构造函数调用之前。

这就是在加载和初始化类时出现异常的原因。这与反射无关。


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

这样,即使成员更改位置(由于重构、行对齐或其他原因),代码仍将正常工作。


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

静态声明需要(前置)构造函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接