java Integer、Float、Double 变量值 存放在哪了


先看一道题目

Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);
System.out.println(f3 == f4);

结果是 true、false

为什么恩,这要归宿与JVM内存分配策略

方法区中运行时常量池存放常量。

什么是运行时常量池

运行时常量池(Runtime Constant Pool),它是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到常量池中。

这里所说的常量包括: 基本类型包装类 (包装类不管理浮点型,整形只会管理-128到127)和 String (也可以通过String.intern()方法可以强制将String放入常量池)。

所以f3、f4的值没有直接保存在运行时常量池中,而是新newInteger对象。== 是比较两个值的内存地址是否一致,所以结果为false。

看看Integer源代码,发现没有

Integer f1 = 100,直接赋值的方法,那么它是如何做到的,
我们通过反编译工作查看源代码发现,代码已变为:
Integer f1 = Integer.valueOf(100);
Integer f1 = Integer.valueOf(150);
在看看Integer.valueOf方法
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
IntegerCache类定义
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            int i = parseInt(integerCacheHighPropValue);
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}
范围超过~128到127,会新new一个Integer对象。
Float、Double的值,没有存放在运行时常量池中。而是存放在堆中。
源码反编译,Flout、Double赋值后调用valueOf()方法
 Float f = Float.valueOf(0.2F);
 Double d = Double.valueOf(1.0D);
-----------------------------------------
public static Float valueOf(float f) {
    return new Float(f);
}
-----------------------------------------
public static Double valueOf(double d) {
    return new Double(d);
}
-----------------------------------------
都是新new一个对象,数据存放在堆中。

总结一下
Integer 值范围在-128~127时,存放在运行时常量池中,超过范围存放在堆中。
Flout、Double 存放在堆中。
引申问题:
同样是封装类型 Integer、Float、Double三个人的待遇为什么会不一样,其他兄弟都安安静静的待在运行时常量池,而它哥三却这么不一样?
推测: 方法区中运行时常量池的内存大小所限,常量池中对基本数据类型和封装类型的存放的变量值的大小有限制?
上面得到结论:Float(4字节)、Double(8字节),Integer(4字节)保留了-128~127,等价于1字节。
再看看:Byte(1字节)、Character(2字节)、Short(2字节)、Long(8字节)。
查看Character、Short、Long源代码中valueOf()方法发现值范围超过-128~127,重新new一个对象。
原因是这个吗,有没有其他原因恩?探究中。。。






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值