【问题标题】:Set field value with reflection使用反射设置字段值
【发布时间】:2014-07-28 11:50:50
【问题描述】:

我正在处理一个非开源项目,我需要修改它的一个或多个类。

在一个类中是以下集合:

private Map<Integer, TTP> ttp = new HashMap<>(); 

我需要做的就是在这里使用反射并使用concurrenthashmap。 我试过下面的代码,但它不起作用。

Field f = ..getClass().getDeclaredField("ttp");
f.setAccessible(true);
f.set(null, new ConcurrentHashMap<>());

【问题讨论】:

  • 这是什么意思:但它不起作用?你在哪个对象上调用.getClass().getDeclaredField("ttp")

标签: java reflection field


【解决方案1】:

希望这是您正在尝试做的事情:

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

public class Test {

    private Map ttp = new HashMap(); 

    public  void test() {
        Field declaredField =  null;
        try {

            declaredField = Test.class.getDeclaredField("ttp");
            boolean accessible = declaredField.isAccessible();

            declaredField.setAccessible(true);

            ConcurrentHashMap<Object, Object> concHashMap = new ConcurrentHashMap<Object, Object>();
            concHashMap.put("key1", "value1");
            declaredField.set(this, concHashMap);
            Object value = ttp.get("key1");

            System.out.println(value);

            declaredField.setAccessible(accessible);

        } catch (NoSuchFieldException 
                | SecurityException
                | IllegalArgumentException 
                | IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    public static void main(String... args) {
        Test test = new Test();
        test.test(); 
    }
}

打印出来:

value1

【讨论】:

  • 我正在寻找一些用于将所有字段值从一个类复制到另一个的代码。但这些字段不仅仅是原生类型。有可能吗?
  • @Krismorte “字段不仅仅是原生类型” 是什么意思?例如?
  • @Krismorte 迟到@#$%,但有可能——是的。听起来您正在寻找“bean 到 bean 映射器”,您可能感兴趣的一个示例是 github.com/DozerMapper/dozer
  • @Visruth 表示像“HisOwnClass”这样的字段,而不是“int”或“Integer”等。
【解决方案2】:

值得一读Oracle Java Tutorial - Getting and Setting Field Values

Field#set(Object object, Object value)指定对象 参数上的此 Field 对象表示的字段设置为指定的新值。

应该是这样的

f.set(objectOfTheClass, new ConcurrentHashMap<>());

你不能在null对象中设置任何值如果尝试那么它将导致NullPointerException


注意:通过反射设置字段的值有一定的性能开销,因为必须进行各种操作,例如验证访问权限。从运行时的角度来看,效果是一样的,并且操作是原子的,就好像直接在类代码中改变了值一样。

【讨论】:

    【解决方案3】:

    下面的方法在你的对象上设置一个字段,即使该字段在超类中

    /**
     * Sets a field value on a given object
     *
     * @param targetObject the object to set the field value on
     * @param fieldName    exact name of the field
     * @param fieldValue   value to set on the field
     * @return true if the value was successfully set, false otherwise
     */
    public static boolean setField(Object targetObject, String fieldName, Object fieldValue) {
        Field field;
        try {
            field = targetObject.getClass().getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            field = null;
        }
        Class superClass = targetObject.getClass().getSuperclass();
        while (field == null && superClass != null) {
            try {
                field = superClass.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                superClass = superClass.getSuperclass();
            }
        }
        if (field == null) {
            return false;
        }
        field.setAccessible(true);
        try {
            field.set(targetObject, fieldValue);
            return true;
        } catch (IllegalAccessException e) {
            return false;
        }
    }
    

    【讨论】:

      【解决方案4】:

      你可以试试这个:

      //Your class instance
      Publication publication = new Publication();
      
      //Get class with full path(with package name)
      Class<?> c = Class.forName("com.example.publication.models.Publication");
      
      //Get method
      Method  method = c.getDeclaredMethod ("setTitle", String.class);
      
      //set value
      method.invoke (publication,  "Value to want to set here...");
      

      【讨论】:

        【解决方案5】:

        你可以试试这个:

        static class Student {
            private int age;
            private int number;
        
            public Student(int age, int number) {
                this.age = age;
                this.number = number;
            }
        
            public Student() {
            }
        }
        public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
            Student student1=new Student();
           // Class g=student1.getClass();
            Field[]fields=student1.getClass().getDeclaredFields();
            Field age=student1.getClass().getDeclaredField("age");
            age.setAccessible(true);
            age.setInt(student1,13);
            Field number=student1.getClass().getDeclaredField("number");
            number.setAccessible(true);
            number.setInt(student1,936);
        
            for (Field f:fields
                 ) {
                f.setAccessible(true);
        
                System.out.println(f.getName()+" "+f.getInt(student1));
        
            }
        }
        

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-16
          • 2019-04-22
          • 2014-10-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多