给定一个类的实例,可以使用反射来设置该类中字段的值。这通常只在无法以常规方式设置值的特殊情况下进行。由于这种访问通常会违反类的设计意图,因此应当极其谨慎地使用。

注意:通过反射设置字段的值会带来一定的性能开销,因为需要进行各种操作,例如验证访问权限。从运行时的角度来看,效果是相同的,并且这个操作与直接在类代码中更改值一样具有原子性。

使用反射可能会导致一些运行时优化失效。例如,以下代码极有可能被Java虚拟机优化:

int x = 100;
x = 500;
x = 800;

使用 Field.set*() 的等效代码可能不会被优化。

下面给出通过反射设置字段值的示例:

package com.team.getclassobject.demo1;

import java.lang.reflect.Field;
import java.util.Arrays;

enum Hobby {
    RUNNING, READING
}


/**
 * 获取并设置字段的值
 */
public class Demo {
    
    public long score = 0;
    public String[] names = {"张三", "李四"};
    public Hobby hobby = Hobby.READING;

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Demo demo = new Demo();
        String fmt = "%s:  %-6s = %s%n";
        
        Field scoreField = demo.getClass().getDeclaredField("score");
        System.out.format(fmt, "修改前", "score", demo.score);
        scoreField.setLong(demo, 100);
        System.out.format(fmt, "修改后", "score", demo.score);
        
        Field namesField = demo.getClass().getDeclaredField("names");
        System.out.format(fmt, "修改前", "names", Arrays.asList(demo.names));
        String[] newNames = {"王五", "马六"};
        namesField.set(demo, newNames);       
        System.out.format(fmt, "修改后", "names", Arrays.asList(demo.names));
        
        Field hobbyField = demo.getClass().getDeclaredField("hobby");
        System.out.format(fmt, "修改前", "hobby", demo.hobby);
        hobbyField.set(demo, Hobby.RUNNING);
        System.out.format(fmt, "修改后", "hobby", demo.hobby);
    }

}

运行结果:
在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐