Java中什么是反射以及怎么用反射修改static final的字段(静态常量)

Java中的反射

Java反射机制发生在运行时期,对于任意一个实体类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。反射一直被冠以"简单粗暴"的称号, 反射是暴力的, 也是很重要的, 众多框架的底层实现都用到了反射.

Class类

我们用类来描述对象, 比如有一个Animal类, 有三个对象: dog、bird、cat, 我们用Animal类来描述这三个对象; 有一个类Person, 有三个对象xiaoMing、xiaoHong、xiaoFang, 我们用Person类去描述这三个对象.
那问题来了, 在Java中, 一切都是对象, 类也可以理解为对象, 那我们该用什么来描述类呢?
就是Class类!
我们通过Class类来获取一个类的字节码对象, 得到它的字节码对象后, 你就可以随意操纵它, 你拥有它的最高权力, 这就好比是手机Root之后, 你就获得了操纵手机的最高权力

获取字节码对象的三种方式

假设有一个类如下

public class ReflectionDemo {
    private static final String NAME = "Will"; //NAME是私有静态常量
}

方法一: Class.forName(“类的全限定名称”);

Class<?> clz = Class.forName("com.pac1.ReflectionDemo");	//得到ReflectionDemo类的字节码对象,这种方式最常用

方法二: 类名.class

Class<ReflectionDemo> clz= ReflectionDemo.class;

方法三: 对象名.getClass()

Class<? extends ReflectionDemo> clz= reflectionDemo.getClass();

附上修改static final字段的完整代码

public class ReflectionDemo {
    private static final String NAME = "AAA"; //NAME是静态常量
}

class Test{
    public static void main(String[] args) throws Exception{
        //得到字节码对象
        Class<?> clz = Class.forName("com.pac1.ReflectionDemo");
        //获取变量名为"NAME"的私有字段
        Field field = clz.getDeclaredField("NAME");
        //无视private修饰符,暴力访问
        field.setAccessible(true);

        Field modifiers = Field.class.getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        //去掉final修饰符
        modifiers.setInt(field,field.getModifiers() & ~Modifier.FINAL);

        System.out.println("修改前: "+ field.get(null));
        field.set(null,"BBB");
        System.out.println("修改后: "+field.get(null));

        //再把final修饰符给加回来
        modifiers.setInt(field,field.getModifiers() & ~Modifier.FINAL);
    }
}

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java,使用 `final` 修饰字段有以下作用: 1. 不可修改:使用 `final` 修饰的字段在初始化后不能再被修改。一旦给 `final` 字段赋予了初始值,就不能再改变它的值。这可以用来确保字段的值在对象的整个生命周期内保持不变。 2. 线程安全:由于 `final` 字段不能被修改,它们在多线程环境下具有可见性和原子性。当一个线程对一个对象的 `final` 字段进行初始化后,其他线程将立即看到该字段的最新值,避免了线程间的数据竞争问题。 3. 优化机会:编译器可以对 `final` 字段进行优化,例如内联(inline)操作。内联可以消除方法调用的开销,将字段的值直接嵌入到使用该字段的代码,提高性能。 下面是一个示例: ```java public class Circle { private static final double PI = 3.14159; // 声明一个常量 PI private final double radius; // 声明一个不可修改的半径字段 public Circle(double radius) { this.radius = radius; } public double getArea() { return PI * radius * radius; } } ``` 在上述示例,`PI` 字段被声明为 `final`,表示它是一个常量,其值在初始化后不能再改变。`radius` 字段也被声明为 `final`,表示它在初始化后不能再被修改。这样可以确保 `Circle` 对象的半径和圆的面积保持不变。 使用 `final` 修饰字段可以提供代码的可读性和稳定性,同时也可以带来一些性能优化和线程安全的好处。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值