You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java反射修改Random类让Math.random()每次返回相同值

普通反射无法直接修改方法内部的运行逻辑,但我们可以通过替换Math.random()依赖的底层随机数生成器实例,实现让它每次返回固定值的效果。

实现原理

Math.random()底层调用的是RandomNumberGeneratorHolder静态内部类中持有的randomNumberGenerator实例的nextDouble()方法,我们通过反射把这个静态final字段替换为自定义的Random子类实例,让自定义实例的nextDouble()固定返回同一个值即可。

可运行代码示例

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

public class FixedRandomDemo {
    public static void main(String[] args) throws Exception {
        // 获取Math的私有静态内部类RandomNumberGeneratorHolder
        Class<?> holderClazz = Class.forName("java.lang.Math$RandomNumberGeneratorHolder");
        // 获取内部类中存储随机数生成器的字段
        Field rngField = holderClazz.getDeclaredField("randomNumberGenerator");
        rngField.setAccessible(true);

        // 移除字段的final修饰符,才能修改静态final字段
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(rngField, rngField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);

        // 自定义Random子类,重写nextDouble固定返回相同值
        Random fixedRng = new Random() {
            @Override
            public double nextDouble() {
                // 这里可以设置为任意你需要的固定double值
                return 0.618;
            }
        };

        // 替换原本的随机数生成器
        rngField.set(null, fixedRng);

        // 测试,输出结果恒为true
        System.out.println(java.lang.Math.random() == java.lang.Math.random());
    }
}

兼容性说明

  • 该方案适配Oracle JDK/OpenJDK 8及以上的标准JDK实现,非标准JDK如果修改了Math类的内部实现,需要对应调整内部类和字段名称
  • JDK 9及以上版本默认开启了模块访问限制,需要添加JVM启动参数--add-opens java.base/java.lang=ALL-UNNAMED才能正常执行反射修改操作

内容的提问来源于stack exchange,提问作者Luka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:24:04