Java - 使用反射查找对象的字段

时间:2014-04-16 15:25:44

标签: java reflection

我有一个对象引用'inst',字段名'f',以及对另一个对象'v'的引用,它应该是对象'inst'上名字为n的字段的新值。

为了通过反射来实现这一点,我可以使用getDeclaredField()和'set'方法,但是当字段'f'是某个祖先超类的字段时,或者当字段时,我不确定要做的最好的事情当对象是匿名内部类的实例时,属于封闭类。

因此,在我看来,有两条路径可以找到该字段 - 父类(使用getSuperClass())和封闭类(使用getEnclosingClass())。

我的问题是找到这个领域最优雅的方式是什么?

1 个答案:

答案 0 :(得分:2)

有两种不太优雅的方法可以实现这一点,我知道:

  1. 使用静态递归方法创建一个帮助器类,该方法检查所有 跨越继承层次结构,该字段是否存在,以及集合 它 - 非常不优雅且潜在的错误
  2. 使用" bean" -conventional getters / setters并使用getDeclaredMethod,以便利用运行时多态性
  3. 这是一个快速的&点 2

    的详细阐述
    package test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyClass {
        boolean foo;
        int bar;
    
        public void setFoo(boolean value) {
            foo = value;
        }
    
        public boolean getFoo() {
            return foo;
        }
    
        public void setBar(int value) {
            bar = value;
        }
    
        public int getBar() {
            return bar;
        }
    
        @Override
        public String toString() {
            return String.format("Foo is %b and bar is %d", foo, bar);
        }
    
        public static String toGetterMethodName(String fieldName) {
            // TODO no null nor length check here
            return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        }
    
        public static String toSetterMethodName(String fieldName) {
            // TODO no null nor length check here
            return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        }
    
        public static void main(String[] args) {
            // a bunch of reflection...
            try {
                List<MyClass> instances = new ArrayList<MyClass>();
                instances.add((MyClass) Class.forName("test.MyClass$MyChildClass")
                        .newInstance());
                instances.add((MyClass) Class.forName("test.MyClass")
                        .newInstance());
                // default values
                System.out.println(instances);
                MyClass.class.getMethod(toSetterMethodName("foo"), boolean.class).invoke(instances.get(0), true);
                MyClass.class.getMethod(toSetterMethodName("foo"), boolean.class).invoke(instances.get(1), true);
                MyClass.class.getMethod(toSetterMethodName("bar"), int.class).invoke(instances.get(0), 42);
                MyClass.class.getMethod(toSetterMethodName("bar"), int.class).invoke(instances.get(1), 42);
                // values are now set
                System.out.println(instances);
    
            }
            // TODO no specific Exception handling
            catch (Throwable t) {
                t.printStackTrace();
            }
        }
    
        static class MyChildClass extends MyClass {
    
        }
    }
    

    <强>输出

    [Foo is false and bar is 0, Foo is false and bar is 0]
    [Foo is true and bar is 42, Foo is true and bar is 42]