Java Integer(-128~127)值的==和equals比较产生的思考
最近在项目中遇到一个问题,两个值相同的Integer型值进行==比较时,发现Integer其中的一些奥秘,顺便也复习一下==和equals的区别,先通过Damo代码解释如下:
- System.out.println("<-128~127以内的Integer值,Integer x = value;的方式赋值!>");
- Integer i = 127;
- Integer j = 127;
- System.out.println("i=" + i + ",j =" + j);
- System.out.println("i == j:" + (i == j) + "<--比较-->i.equals(j):"+ i.equals(j));
- System.out.println("<-128~127以外的Integer值,Integer x = value;的方式赋值!>");
- Integer m = 128;
- Integer n = 128;
- System.out.println("m=" + m + ",n =" + n);
- System.out.println("m == n:" + (m == n) + "<--比较-->m.equals(n):"+ m.equals(n));
- System.out.println();
- <span style="white-space:pre"> </span>
- System.out.println("<任意Integer值,Integer x = new Integer(value);的方式赋值!>");
- Integer x = new Integer(299);
- Integer y = new Integer(299);
- System.out.println("x=" + x + ",y =" + y);
- System.out.println("x == y:" + (x == y) + "<--比较-->x.equals(y):"+ x.equals(y));
输出结果为:
- <-128~127以内的Integer值,Integer x = value;的方式赋值!>
- i=127,j =127
- i == j:true<--比较-->i.equals(j):true
- <-128~127以外的Integer值,Integer x = value;的方式赋值!>
- m=128,n =128
- m == n:false<--比较-->m.equals(n):true
- <任意Integer值,Integer x = new Integer(value);的方式赋值!>
- x=299,y =299
- x == y:false<--比较-->x.equals(y):true
通过以上代码及输出结果,想必大家已经看出其中奥秘!先总结如下:
1、以上代码第一段和第二段旨在说明:在-128~127的Integer值并且以Integer x = value;的方式赋值的Integer值在进行==和equals比较时,都会返回true,因为Java里面对处在在-128~127之间的Integer值,用的是原生数据类型int,会在内存里供重用,也就是说这之间的Integer值进行==比较时只是进行int原生数据类型的数值比较,而超出-128~127的范围,进行==比较时是进行地址及数值比较。
2、第三段旨在说明:==和equals的区别,==是进行地址及值比较,无法对==操作符进行重载,而对于equals方法,Integer里面的equals方法重写了Object的equals方法,查看Integer源码可以看出equals方法进行的是数值比较。
续详解:
首先看一段代码(使用JDK 5),如下:
- public class Hello
- {
- public static void main(String[] args)
- {
- int a = 1000, b = 1000;
- System.out.println(a == b);
- Integer c = 1000, d = 1000;
- System.out.println(c == d);
- Integer e = 100, f = 100;
- System.out.println(e == f);
- }
- }
输出结果:
- true
- false
- true
The Java Language Specification, 3rd Edition 写道:
- 为了节省内存,对于下列包装对象的两个实例,当它们的基本值相同时,他们总是==:
- Boolean
- Byte
- Character, \u0000 - \u007f(7f是十进制的127)
- Integer, -128 — 127
查看jdk源码,如下:
- /**
- * 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. During VM initialization the
- * getAndRemoveCacheProperties method may be used to get and remove any system
- * properites that configure the cache size. At this time, the size of the
- * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
- */
- // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
- private static String integerCacheHighPropValue;
- static void getAndRemoveCacheProperties() {
- if (!sun.misc.VM.isBooted()) {
- Properties props = System.getProperties();
- integerCacheHighPropValue =
- (String)props.remove("java.lang.Integer.IntegerCache.high");
- if (integerCacheHighPropValue != null)
- System.setProperties(props); // remove from system props
- }
- }
- private static class IntegerCache {
- static final int high;
- static final Integer cache[];
- static {
- final int low = -128;
- // high value may be configured by property
- int h = 127;
- if (integerCacheHighPropValue != null) {
- // Use Long.decode here to avoid invoking methods that
- // require Integer's autoboxing cache to be initialized
- int i = Long.decode(integerCacheHighPropValue).intValue();
- i = Math.max(i, 127);
- // Maximum array size is Integer.MAX_VALUE
- h = Math.min(i, Integer.MAX_VALUE - -low);
- }
- 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() {}
- }
- /**
- * Returns a <tt>Integer</tt> instance representing the specified
- * <tt>int</tt> value.
- * If a new <tt>Integer</tt> 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.
- *
- * @param i an <code>int</code> value.
- * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
- * @since 1.5
- */
- public static Integer valueOf(int i) {
- if(i >= -128 && i <= IntegerCache.high)
- return IntegerCache.cache[i + 128];
- else
- return new Integer(i);
- }
这儿的IntegerCache有一个静态的Integer数组,在类加载时就将-128 到 127 的Integer对象创建了,并保存在cache数组中,一旦程序调用valueOf 方法,如果i的值是在-128 到 127 之间就直接在cache缓存数组中去取Integer对象。
再看其它的包装器:
- Boolean:(全部缓存)
- Byte:(全部缓存)
- Character(<= 127缓存)
- Short(-128 — 127缓存)
- Long(-128 — 127缓存)
- Float(没有缓存)
- Doulbe(没有缓存)
同样对于垃圾回收器来说:
- Integer i = 100;
- i = null;//will not make any object available for GC at all.
这里的代码不会有对象符合垃圾回收器的条件,这儿的i虽然被赋予null,但它之前指向的是cache中的Integer对象,而cache没有被赋null,所以Integer(100)这个对象还是存在。
而如果i大于127或小于-128则它所指向的对象将符合垃圾回收的条件:
- Integer i = 10000;
- i = null;//will make the newly created Integer object available for GC.
那么缓存如何修改呢?
下面例子使用32位Windows上的Sun JDK 1.6.0 update 18。
在Java语言规范第三版,5.1.7 Boxing Conversion中,
这就是为什么符合规范的Java实现必须保证Integer的缓存至少要覆盖[-128, 127]的范围。
使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN参数即可将Integer的自动缓存区间设置为[-128,NNN]。注意区间的下界固定在-128不可配置。
在client模式下该参数无效。这个参数是server模式专有的,在c2_globals.hpp中声明,默认值是128;不过这个默认值在默认条件下不起作用,要手动设置它的值或者是开启-XX:+AggressiveOpts参数才起作用。
在设置了-XX:+AggressiveOpts启动参数后,AutoBoxCacheMax的默认值会被修改为20000并且生效。参考arguments.cpp:
- // Aggressive optimization flags -XX:+AggressiveOpts
- void Arguments::set_aggressive_opts_flags() {
- #ifdef COMPILER2
- if (AggressiveOpts || !FLAG_IS_DEFAULT(AutoBoxCacheMax)) {
- if (FLAG_IS_DEFAULT(EliminateAutoBox)) {
- FLAG_SET_DEFAULT(EliminateAutoBox, true);
- }
- if (FLAG_IS_DEFAULT(AutoBoxCacheMax)) {
- FLAG_SET_DEFAULT(AutoBoxCacheMax, 20000);
- }
- // Feed the cache size setting into the JDK
- char buffer[1024];
- sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
- add_property(buffer);
- }
- // ...
- #endif
- }
测试代码:
- // run with:
- // java -server -XX:AutoBoxCacheMax=1000 TestAutoBoxCache
- public class TestAutoBoxCache {
- public static void main(String[] args) {
- Integer a = 1000;
- Integer b = 1000;
- System.out.println(a == b);
- Integer c = 1001;
- Integer d = 1001;
- System.out.println(c == d);
- Integer e = 20000;
- Integer f = 20000;
- System.out.println(e == f);
- }
- }
在命令行上测试:
- D:\>javac TestAutoBoxCache.java
- D:\>java TestAutoBoxCache
- false
- false
- false
- D:\>java -server TestAutoBoxCache
- false
- false
- false
- D:\>java -Djava.lang.Integer.IntegerCache.high=1000 TestAutoBoxCache
- true
- false
- false
- D:\>java -server -Djava.lang.Integer.IntegerCache.high=1000 TestAutoBoxCache
- true
- false
- false
- D:\>java -Djava.lang.Integer.IntegerCache.high=1001 TestAutoBoxCache
- true
- true
- false
- D:\>java -server -Djava.lang.Integer.IntegerCache.high=1001 TestAutoBoxCache
- true
- true
- false
- D:\>java -XX:AutoBoxCacheMax=1000 TestAutoBoxCache
- Unrecognized VM option 'AutoBoxCacheMax=1000'
- Could not create the Java virtual machine.
- D:\>java -server -XX:AutoBoxCacheMax=1000 TestAutoBoxCache
- true
- false
- false
- D:\>java -server -XX:AutoBoxCacheMax=1001 TestAutoBoxCache
- true
- true
- false
- D:\>java -server -XX:+AggressiveOpts TestAutoBoxCache
- true
- true
- true
中间报Unrecognized VM option 'AutoBoxCacheMax=1000'错误是因为这个参数只能在HotSpot Server VM上使用,在HotSpot Client VM上不支持。
Java Integer(-128~127)值的==和equals比较产生的思考的更多相关文章
- JAVA Integer值的范围
原文出处:http://hi.baidu.com/eduask%C9%BD%C8%AA/blog/item/227bf4d81c71ebf538012f53.html package com.test ...
- java Integer类的缓存(转)
首先看一段代码(使用JDK 5),如下: public class Hello { public static void main(String[] args) { int a = 1000, b = ...
- Java Integer类的缓存
首先看一段代码(使用JDK 5),如下: public class Hello { public static void main(String[] args) { int a = 1000, b = ...
- java jdk缓存-128~127的Long与Integer
先推断下以下代码的输出结果 Qa:---------------------------------------------- Long a = Long.valueOf(127) ...
- Java判断Integer类型的值是否相等
我们知道Integer是int的包装类,在jdk1.5以上,可以实现自动装箱拆箱,就是jdk里面会自动帮我们转换,不需要我们手动去强转,所以我们经常在这两种类型中随意写,平时也没什么注意 但Integ ...
- Integer a= 127 与 Integer b = 128相关
Integer a = 127; Integer b = 127; Integer c = 128; Integer d = 128; a == b 与 c == d 的比较结果是什么? a == b ...
- 为什么在 Java 中128==128返回false,而127==127返回true呢?
为什么在 Java 中128==128返回false,而127==127返回true呢? 有这样一段代码 Integer a=127; Integer b=127; System.out.printl ...
- java中两个Integer类型的值相比较的问题
今天在做一个算法时,由于为了和其他人保持接口的数据类型一致,就把之前的int换为Integer,前几天测了几组数据,和之前的结果一样,但是今天在测其它数据 的时候,突然出现了一个奇怪的bug,由于之前 ...
- byte类型的取值为什么是-128~127
参考:https://blog.csdn.net/qq_22771739/article/details/84496115 https://blog.csdn.net/boatalways/artic ...
随机推荐
- Bitnami Redmine插件记录
1.bitnami安装时自带了开发环境,如ruby.rails.devkit. 为了版本兼容,应使用bitnami的命令行. 2.通过use_redmine启动命令行:运行Bitnami\redmin ...
- python 编辑文件时路径问题解决方法:文件或者目录不存在、文件编辑后无法保存等(以编辑xml文件为例)
1.获取工程所在根路径:根路径=os.path.dirname(os.path.abspath('__file__')) 2.将获取的根路径和相对路径组合:组合路径=os.path.join(根路径, ...
- jQ中对attr()方法的理解
在JS中设置节点的属性与属性值用到setAttribute(),获得节点的属性与属性值用到getAttribute(),而在jquery中,用一个attr()就可以全部搞定了,赞一个先 ^^jquer ...
- mysql xml 参数
drop PROCEDURE IF EXISTS tt;CREATE PROCEDURE tt(para text,OUT para1 DECIMAL(18, 6),OUT para2 DECIMAL ...
- Glide 图片加载库
compile 'com.github.bumptech.glide:glide:3.7.0' Glide.with(context) //图片url .load("http://www.b ...
- Discuz!模板解析语法
<!--{eval echo autostart("); }--> PHP中使用template()函数显示已存在模板 在Discuz!程序执行中可以通过 include tem ...
- 关于AJAX 的交互模型、交互流程及代码示范
AJAX = 异步JavaScript + XML. 它是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况 ...
- 设计一个泛型类orderedCollection
设计一个泛型类orderedCollection,它存储的Comparable对象的集合(在数组中),以及该集合的当前大小.提供public方法isEmpty,makeEmpty,insert,rem ...
- for循环嵌套的优化
public static void main(String[] args) { int x = 0; for (int i = 0; i < 2; i++) { ...
- wordcount 过程
hdfs原始数据 hello a hello b map阶段: 输入数据:<0,"hello a"> <8,"hello b"> key ...