黑马程序员技术交流社区
标题:
Integer 类的小问题
[打印本页]
作者:
november
时间:
2014-1-15 21:32
标题:
Integer 类的小问题
Integer i1 = 127;
Integer i2 = 127;
i1 == i2;为什么返回的是true?
Integer i3 = 128;
Integer i4 = 128;
i3 == i4;为什么返回的事false?
作者:
yaohsieh
时间:
2014-1-15 21:35
如果数字小于byte范围,装箱成为Integer对象的时候,会把这个数字缓存起来到缓存池里,下一次再用这个数字,会直接引用这个数字,所以下面打印为true。
如果大于byte范围(-128~127),则i3 == i4的结果是false,因为
Integer i3 = 128;
Integer i4 = 128;
是创建了两个对象
i3 == i4,是比较的对象地址值,所以是false
作者:
疯狂的土贼
时间:
2014-1-15 21:46
本帖最后由 疯狂的土贼 于 2014-1-15 21:49 编辑
朋友 你这个问题我以前解决过不过呢上次说的不是很明白 后来搞懂了 一下是我学习时候收藏的一篇不错的文章 你看看 应该可以完全解决了 如果还有什么不明白的你可以继续问 顺便给你地址你看下 http://www.ticmy.com/?p=110
jdk1.5引入了自动装箱(autoboxing)与自动拆箱(unboxing),这方便了集合类以及一些方法的调用,同时也使初学者对其感到非常之困惑。在此,我们来揭开其神秘的面纱。
首先,需要厘清一些概念:
1、
Integer是一个类,用Integer声明一个变量其是一个对象类型(或者说引用类型);int是基本类型,用int声明的变量是非对象类型,即不能在其上调用方法。
2、
“==”作用于对象上的时候,其比较的是对象的引用本身的值(或者说对象的地址更容易理解),而作用于基本类型的时候比较的就是基本类型的值。
接下来看一段代码:
[size=1em]public class Test {
[size=1em] public static void main(String[] args) {
[size=1em] Integer i1 = 2;
[size=1em] int i2 = 2;
[size=1em] System.out.println(i1 == i2);
[size=1em] }
[size=1em]}
[/td][/tr]
[/table]
在这段代码中有两个令人困惑的问题,首先是将一个基本类型的值赋值给对象的引用,即Integer i1 =2;其次是拿一个对象类型和一个基本类型比较。按理说这两种做法肯定都是有问题的,在jdk1.4(若使用的jdk版本是1.5或之后的版本中,可以使用
javac -source 1.4 Test.java
来编译)上,确实如此,第一个问题在编译时会报“
不兼容的类型
”错误,第二个问题会报“
运算符 == 不能应用于 java.lang.Integer,int
”的错误。
但是jdk1.5引入的自动装箱和自动拆箱,那么,必然要将其中的一种类型转换成另一种类型,究竟是将Integer对象i1转换成int基本类型呢?还是将int基本类型的i2转换成Integer对象?通过
javap -c Test
反编译Test.class文件就知道答案了:
[size=1em]public static void main(java.lang.String[]);
[size=1em] Code:
[size=1em] 0: iconst_2
[size=1em] 1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
[size=1em] 4: astore_1
[size=1em] 5: iconst_2
[size=1em] 6: istore_2
[size=1em] 7: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
[size=1em] 10: aload_1
[size=1em] 11: invokevirtual #4; //Method java/lang/Integer.intValue:()I
[size=1em] 14: iload_2
[size=1em] 15: if_icmpne 22
[size=1em] 18: iconst_1
[size=1em] 19: goto 23
[size=1em] 22: iconst_0
[size=1em] 23: invokevirtual #5; //Method java/io/PrintStream.println:(Z)V
[size=1em] 26: return
[size=1em]}
[/td][/tr]
[/table]
其中,[0-4]是Integer i1 = 2的实现,我们发现,编译的字节码里调用了Integer.valueOf方法,因此Integer i1 = 2编译后就等同于Integer i1 = Integer.valueOf(2);[5,6]是int i2 = 2的实现;[7,23]是System.out.println(i1 == i2)的实现,也容易看到,里面调用了Integer.intValue()方法。因此,这个i1 == i2这两个不同类型的变量比较,在编译的时候,编译器是将其转换成相同的类型进行比较的,即将对象类型转换成基本类型,System.out.println(i1 == i2)就等同于System.out.println(i1.intValue() == i2),前面说了,“==”作用于基本类型的时候比较的就是基本类型的值,两个值都是2,所以结果是true。
另外一个令人困惑的例子就是:
[size=1em]public class Test {
[size=1em] public static void main(String[] args) {
[size=1em] Integer i1 = 127;
[size=1em] Integer i2 = 127;
[size=1em] System.out.println(i1 == i2);
[size=1em] Integer i3 = 128;
[size=1em] Integer i4 = 128;
[size=1em] System.out.println(i3 == i4);
[size=1em] }
[size=1em]}
[/td][/tr]
[/table]
运行后发现,i1==i2的结果为true,i3==i4的结果为false?这令不知原因的人头疼不已。在前面一个例子里我们已经说过,诸如Integer i1 = 127,在编译后就等同于Integer i1 = Integer.valueOf(127),既然是调用一个方法来获得对象,那么就有必要对valueOf方法一探究竟了。我们看下源码:
[size=1em]public static Integer valueOf(int i) {
[size=1em] final int offset = 128;
[size=1em] if (i >= -128 && i <= 127) { // must cache
[size=1em] return IntegerCache.cache[i + offset];
[size=1em] }
[size=1em] return new Integer(i);
[size=1em]}
[/td][/tr]
[/table]
到此应该恍然大悟了,IntegerCache缓存了[-128,127]之间的Integer对象,如果valueOf的参数i处于这之间,就返回缓存的对象。否则就new一个新的Integer。前面已经说过,“==”作用于对象上的时候,其比较的是对象的地址,例子中的i1和i2都是从缓存中拿的,当然是同一个对象,i3和i4都是通过new Integer获得的,当然不是同一个对象了。
类似地,java.lang.Long,java.lang.Short分别缓存了[-128,127]之间的Long和Short对象,java.lang.Byte缓存了所有的对象,java.lang.Character缓存了[0,127]之间的Character对象。java缓存这些对象是为了性能优化,既然我们已经知道其缓存了这么些对象,在需要new Integer/Long/…的地方,可改用Integer/Long/Short…#valueOf方法。
作者:
高丽华
时间:
2014-1-15 21:49
总而言之byte范围(-128~127),所以只要超过这个范围就是错误的!
Integer i1 = 127;
Integer i2 = 127;
i1 == i2;返回的是true,是因为没有超过范围!
Integer i3 = 128;
Integer i4 = 128;
i3 == i4;返回的事false,是因为超过范围了!
作者:
孤独的天奇
时间:
2014-1-15 22:27
这个是享元模式的应用,小的数字会认为应用的机会很大,所以第一次时候的时候放在缓存里,下一次直接用就可以。大的数字应用的机会很小,因此每次使用都新创建一个对象。
作者:
黄晓鑫
时间:
2014-1-15 22:38
因为在Java中 如果Integer类型的值如果不超过byte类型范围.就不会再开辟空间 所以才有这样的结果
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2