Integer源码解读


该源码基于 jdk 1.8.0_261 版本。

一:问题导入

 Integer a=500;
 Integer b=500;
 System.out.println(a==b);
 System.out.println(a.equals(b));
 
 Integer c=90;
 Integer d=90;
 System.out.println(c==d);
 System.out.println(c.equals(d));

 Integer e = 127;
 Integer f = new Integer(127);
 System.out.println(e==f);

 Integer g = 128;
 int h = 128;
 System.out.println(g==h);


发现结果是:
在这里插入图片描述

看到这里我就有点迷了,equals是用来比较两个对象的值是否想等,这个都为true没问题,但是 “==” 不就是用来比较两个对象的地址是否相等吗,按理说应该都为false呀,那为什么一个为false,一个为true呢?

于是就想深入的去看一下源码。
在这里插入图片描述
从中我们可以看出 500 在初始化的时候是new 了一个新的 Integer 对象;
而 90 在初始化时:是在 IntegerCache 中取的值。
在这里插入图片描述
那我们接着往下看 IntegerCache :
这是Integer类中的一个内部类

    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) {
                try {
                    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);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

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

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

默认缓存的范围是 [-128,127],当Integer的值范围在 [-128,127] 时则直接从缓存中获取对应的Integer对象,不必重新实例化。这些缓存值都是静态且 final 的,避免重复的实例化和回收
我们再看看控制台:
在这里插入图片描述
发现c 和 d 的地址确实是相同的,所以问题解决!!

那么 e 和 f 是怎么回事呢?
还是通过源码:Integer e,e 是从 IntegerCache 中取到的,但是 f 是 又 new 出来的,它们两个肯定不是一个对象,所以肯定为 false 。其实不管 e 是不是从 IntegerCache 中取出来的,它和 new 出来的 f 也肯定不是一个对象。肯定为 false 。

那么 g 和 h 是怎么回事呢?
凡是涉及到基本数据类型, == 号比对的都是值,因为包装类都会自动拆箱。

二:equals方法

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

    public int intValue() {
        return value;
    }

这个没什么说的,显而易见,也比较常用。

三:自动装箱拆箱

装箱就是自动将基本数据类型转换为包装器类型;
拆箱就是自动将包装器类型转换为基本数据类型。

下表是基本数据类型对应的包装器类型:
在这里插入图片描述

 //自动装箱
 Integer a = 99;

 //自动拆箱
 int b = a;

这个过程是自动执行的:

Integer a = 99;
执行上面那句代码的时候,系统为我们执行了:
Integer a = Integer.valueOf(99);

int b = a;
执行上面那句代码的时候,系统为我们执行了:
int b = a.intValue();

1、谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般情况下要优于第一种情况。
因为如果直接new Integer的话,它就会调用构造方法new出来一个Integer对象出来。但是要是用Integer i = xxx,它会调用valueOf方法,如果数的范围在IntegerCache范围内时,那么它就不需要再new出来一个对象,直接就从这个缓冲池中直接取出数据了

2、Double类的valueOf方法

出于好奇,就想看看其他的包装类是什么样的情况:
猜猜,下面的结果:

Double a = 50.0;
Double b = 50.0;
System.out.println(a==b);

Double c = 200.0;
Double d = 200.0;
System.out.println(c==d);

答案是:
在这里插入图片描述
看看valueOf源码:

public static Double valueOf(double d) {
    return new Double(d);
}

public static Double valueOf(String s) throws NumberFormatException {
    return new Double(parseDouble(s));
}

发现它是没有缓冲的,都是直接new对象。

为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现?
很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。

3、Boolean类的valueOf方法

Boolean a = false;
Boolean b = false;
System.out.println(a==b);

Boolean c = true;
Boolean d = true;
System.out.println(c==d);

在这里插入图片描述

看看valueOf源码:

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

public static Boolean valueOf(String s) {
   return parseBoolean(s) ? TRUE : FALSE;
}

TRUE 、 FALSE两个常量

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

注意:
 Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
 Double、Float的valueOf方法的实现是类似的。

四:问题升级

Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;

System.out.println(c==d);
System.out.println(e==f);
System.out.println(c==(a+b));
System.out.println(c.equals(a+b));
System.out.println(g==(a+b));
System.out.println(g.equals(a+b));
System.out.println(g.equals(a+h));

在这里插入图片描述
当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。

第一个和第二个输出结果没有什么疑问。第三句由于 a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。

而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样。

不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。

未完待续!!!

参考博文:https://www.cnblogs.com/dolphin0520/p/3780005.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`_.nth` 函数是 Lodash 中的一个工具函数,用于获取数组 `array` 中第 `num` 个元素。它的码实现如下: ```javascript function nth(array, n) { var length = array == null ? 0 : array.length if (!length) { return } n += n < 0 ? length : 0 return isIndex(n, length) ? array[n] : undefined } ``` 该函数首先判断传入的数组是否为空,如果为空则直接返回 `undefined`。然后对传入的 `num` 进行一些处理,如果 `num` 是负数,则将其转化为正数。最后,通过 `isIndex` 函数判断 `num` 是否为有效的下标,如果是,则返回对应元素,否则返回 `undefined`。 其中,`isIndex` 函数的实现如下: ```javascript function isIndex(value, length) { var type = typeof value length = length == null ? MAX_SAFE_INTEGER : length return !!length && (type === 'number' || (type !== 'symbol' && reIsUint.test(value))) && (value > -1 && value % 1 == 0 && value < length) } ``` 该函数用于判断一个值是否为有效的数组下标。它首先判断传入的 `length` 是否为有效的数字,然后判断 `value` 是否为有效的数字或字符串,并且在范围内。如果满足以上条件,则返回 `true`,否则返回 `false`。 需要注意的是,`reIsUint` 是一个正则表达式,用于判断一个字符串是否表示一个非负整数: ```javascript var reIsUint = /^(?:0|[1-9]\d*)$/ ``` 综上所述,`_.nth` 函数是一个简单实用的工具函数,用于获取数组中指定位置的元素,并且具有较好的健壮性和可读性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小本科生debug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值