你真的理解Integer的缓存问题吗?

你真的理解Integer的缓存问题吗?

一、背景下面给出一个例子,问输出的结果是多少

代码语言:javascript复制public class IntTest {

public static void main(String[] args) {

Integer a = 100, b = 100, c = 150, d = 150;

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

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

}

}很多新手可能非常犹豫,有一些经验的同学可以回答出"标准"答案。

问原因则随口就说”Integer缓存了-128到127之间的整数对象“,为什么会缓存?还有其他答案?可能就不知道了。

what??? 难道这不是标准答案?还想咋地?

二、分析2.1 运行想知道答案很容易,直接运行,结果是 true ,false。

2.2 源码法直接看源码, 我们知道声明整数时,会通过 java.lang.Integer#valueOf(int) 构造(不信可以断点)。

代码语言:javascript复制 /**

* Returns an {@code Integer} instance representing the specified

* {@code int} value. If a new {@code Integer} instance is not

* required, this method should generally be used in preference to

* the constructor {@link #Integer(int)}, as this method is likely

* to yield significantly better space and time performance by

* caching frequently requested values.

*

* This method will always cache values in the range -128 to 127,

* inclusive, and may cache other values outside of this range.

*

* @param i an {@code int} value.

* @return an {@code Integer} instance representing {@code i}.

* @since 1.5

*/

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}通过源码和注释可以看到 如果是-128到127之间的整数,则会使用整数缓存对象,否则就new一个整形对象。

因此第一个是true,第二个是false。

2.3 反汇编前面讲到了,用到了 再问一个问题 为什么调用了 java.lang.Integer#valueOf(int) ?

我们直接反汇编:javap -c IntTest

代码语言:javascript复制Compiled from "IntTest.java"

public class com.chujianyun.common.int_test.IntTest {

public com.chujianyun.common.int_test.IntTest();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: bipush 100

2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

5: astore_1

6: bipush 100

8: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

11: astore_2

12: sipush 150

15: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

18: astore_3

19: sipush 150

22: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

25: astore 4

27: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;

30: aload_1

31: aload_2

32: if_acmpne 39

35: iconst_1

36: goto 40

39: iconst_0

40: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V

43: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;

46: aload_3

47: aload 4

49: if_acmpne 56

52: iconst_1

53: goto 57

56: iconst_0

57: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V

60: return

}很明显 四个Integer对象的构造使用了java/lang/Integer.valueOf函数。

那么除了上面的回答还有哪些更完善的回答呢?

我们继续看 java.lang.Integer.IntegerCache的源码

代码语言:javascript复制/**

* Cache to support the object identity semantics of autoboxing for values between

* -128 and 127 (inclusive) as required by JLS.

*

* The cache is initialized on first usage. The size of the cache

* may be controlled by the {@code -XX:AutoBoxCacheMax=} option.

* During VM initialization, java.lang.Integer.IntegerCache.high property

* may be set and saved in the private system properties in the

* sun.misc.VM class.

*/

private static class IntegerCache {

static final int low = -128;

static final int high;

static final Integer cache[];

// 省略

}可以看到可以通过设置虚拟机参数:XX:AutoBoxCacheMax=或 -Djava.lang.Integer.IntegerCache.high=

来设置缓存范围的最大值(包含)。

因此如果将最大值设置为150或者以上。则程序的答案就是 true, true。

另外缓存是 《Java语言规范》的要求,具体可以去语言规范里看。

三、总结我们看一些文章的时候,不要止步于文章给出的标准答案,否则总是“背”文章,印象不深刻。

最好自己能够动手DEMO一下,能过亲自去源码里看一看,能够有自己的思考,才能学得更多。

研究Java相关问题除了多看源码外,还可以多反汇编,不要惧怕,一回生两回熟,慢慢就会乐此不疲。

总之希望本文能够给大家一些启发,养成读源码,反汇编等好的学习方法,更快进阶。

相关推荐

用友软件明细账打印步骤怎么操作
123656的网站怎么打开

用友软件明细账打印步骤怎么操作

⌛ 11-16 👁️ 988
小米电视用的哪个厂家面板
365体育投注ribo88

小米电视用的哪个厂家面板

⌛ 01-21 👁️ 4231