Java SDK源码中Integer的源码解析系列开篇

文章标题:

Java SDK源码中Integer的源码剖析系列起始篇

文章内容:

目录

  • 1. 应用场景
  • 2. 原理探究
    • 2.1. 构造机制
    • 2.2. valueOf方法
    • 2.2.1. 处于-128到127范围时从缓存获取
    • 2.2.2. 解读Integer.valueOf(1)==Integer.valueOf(1)
    • 2.2.3. 解读(Integer val1 = 1) == (Integer val2 = 1)
    • 2.2.4. 解读(Integer val1 = 128) != (Integer val2 = 128)

1. 应用场景

在Java代码中,我们经常会用到Integer类型来处理整数相关操作。下面通过一个示例类来展示不同方式创建Integer对象时的引用比较情况:

public class IntegerUsageDemo
{
    public static void main(String[] args)
    {
        // 通过new关键字创建的两个Integer对象,引用不同
        Integer num1 = new Integer(1);
        Integer num2 = new Integer(1);
        System.out.println(num1 == num2); // 输出false

        // 直接赋值方式创建的Integer对象,引用相同
        Integer num3 = 1;
        Integer num4 = 1;
        System.out.println(num3 == num4); // 输出true

        // 使用valueOf方法创建的Integer对象,引用相同
        Integer num5 = Integer.valueOf(1);
        Integer num6 = Integer.valueOf(1);
        System.out.println(num5 == num6); // 输出true
        System.out.println(num3 == num5); // 输出true
    }
}

2. 原理探究

2.1. 构造机制
// final修饰表示Integer类不可被继承,实现Comparable<Integer>接口以支持比较操作
public final class Integer extends Number implements Comparable<Integer> {
    private final int value; // 底层使用int类型存储数值,且被final修饰

    public Integer(int value) {
        this.value = value; // 简单的属性赋值操作
    }
}

Integer类具有不可变性,具体体现在以下几点:
* 类被final修饰,无法被继承扩展。
* 内部存储数值的属性value被final修饰,一旦赋值不可更改。
* 没有提供任何对外修改value属性的方法。

2.2. valueOf方法
public static Integer valueOf(String s) throws NumberFormatException {
    return Integer.valueOf(parseInt(s, 10));
}

public static Integer valueOf(int i) {
    // 当数值在-128到127范围内时,直接从缓存中获取对应对象
    if (i >= IntegerCache.low && i <= IntegerCache.high) {
        return IntegerCache.cache[i + (-IntegerCache.low)];
    }
    // 超出范围则创建新的Integer对象
    return new Integer(i);
}
2.2.1. 处于-128到127范围时从缓存获取

这里涉及到IntegerCache类,其内部实现如下:

private static class IntegerCache {
    static final int low = -128; // 缓存的最小数值
    static final int high;       // 缓存的最大数值,需要动态计算
    static final Integer cache[]; // 用于存储缓存的Integer对象数组

    static {
        // 默认最大缓存数值为127
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = Integer.parseInt(integerCacheHighPropValue);
                h = Math.max(i, 127);
                // 确保不超过Integer能表示的最大范围
                h = Math.min(h, Integer.MAX_VALUE - (-low) - 1);
            } catch (NumberFormatException nfe) {
                // 解析属性失败时忽略,使用默认值
            }
        }
        high = h;

        // 初始化缓存数组,将low到high范围内的数值都存入缓存
        cache = new Integer[(high - low) + 1];
        int j = low;
        for (int k = 0; k < cache.length; k++) {
            cache[k] = new Integer(j++);
        }

        assert IntegerCache.high >= 127; // 断言最大缓存值不小于127
    }

    private IntegerCache() {} // 私有构造方法,防止实例化
}
2.2.2. 解读Integer.valueOf(1)==Integer.valueOf(1)

当执行Integer.valueOf(1)时,由于1处于-128到127的缓存范围内,会直接从IntegerCache的缓存数组中获取已存在的对象,所以两次调用Integer.valueOf(1)返回的是同一个对象,因此Integer.valueOf(1) == Integer.valueOf(1)的结果为true。

2.2.3. 解读(Integer val1 = 1) == (Integer val2 = 1)

在Java中,直接将基本类型int赋值给Integer类型时,实际上会自动调用Integer.valueOf方法。所以Integer val3 = 1;等同于Integer val3 = Integer.valueOf(1);,同理Integer val4 = 1;也是如此,因此val3和val4引用的是同一个缓存对象,所以val3 == val4的结果为true。

2.2.4. 解读(Integer val1 = 128) != (Integer val2 = 128)

由于IntegerCache只缓存了-128到127范围内的Integer对象,128超出了这个范围,所以每次调用Integer.valueOf(128)都会创建一个新的Integer对象,因此val1和val2是两个不同的对象,它们的引用不同,所以val1 != val2的结果为false。

版权声明:程序员胖胖胖虎阿 发表于 2025年7月19日 下午2:33。
转载请注明:Java SDK源码中Integer的源码解析系列开篇 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...