简体   繁体   中英

Java - find field of object using reflection

I have an object reference 'inst', field name 'f', and the reference to another object 'v' which should be the new value for the field with name n on object 'inst'.

In order to do this by reflection I can use getDeclaredField() and the 'set' method, however I am unsure of the best thing to do when field 'f' is a field of some ancestor superclass, or when the field belongs to an enclosing class when the object is an instance of an anonymous inner class.

Therefore it seems to me there are two paths to find the field along - parent superclasses (using getSuperClass()) and enclosing classes (using getEnclosingClass()).

My issue is what is the most elegant way to find the field?

There are two inelegant ways to achieve this, that I know of:

  1. Create a helper class with a static recursive method that checks all across the inheritance hierarchy whether the field exists, and sets it - very inelegant and potentially buggy
  2. Use "bean"-conventional getters/setters and use getDeclaredMethod , in order to leverage the runtime polymorphism instead

Here's a quick & dirty elaboration on point 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 {

    }
}

Output

[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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM