A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 赵宇 于 2012-9-25 08:35 编辑

红色部分不一样
public class Test
{
              public static void main(String[] args)
                {
                     Integer i1 = 100;
                     Integer i2 = 100;
  
                           if(i1 == i2)
                      {
                       System.out.println("i1 == i2");
                       }
                      else
                      {
                     System.out.println("i1 != i2");
                     }
             }
}


public class Test
{
              public static void main(String[] args)
                {
                     Integer i1 = 200;
                     Integer i2 = 200;
  
                           if(i1 == i2)
                      {
                       System.out.println("i1 == i2");
                       }
                      else
                      {
                     System.out.println("i1 != i2");
                     }
             }
}

6 个回复

倒序浏览
你是想问什么??两个程序的结果??第一个是true把 第二个是false 我没验证 想想应该是这样的  涉及到享元设计模式,楼主可以说说答案
回复 使用道具 举报
本帖最后由 李建强 于 2012-9-23 12:05 编辑

JDK1.5出现了一个新机制:自动装箱。
对象和对象是比较的地址。
Integer在byte(-128--127)这个范围内,如果存在了这个值,
100在这个范围内,再创建这个值的时候,引用的是同一个地址,true。
但是超过了这个范围,就还是会重新创建新对象的,地址是不同的,
200已经超出了范围,两个对象地址是不会相同的,false。

补充一下,有装箱也就有拆箱了。
什么时候拆箱呢?对象和基本类型比较的时候。
Integer会先拆成int 与 int比较,这时候比较的就是值了。
Integer i1 = new Integer(200);
int i2 =200;
i1 == i2

ps:求版主加分{:soso_e154:}


回复 使用道具 举报
Integer i = 100.相当于编译器自动为您作以下的语法编译:
Integer i = new Integer(100).所以自动装箱与拆箱的功能是所谓的“编译器蜜糖”(Compiler Sugar),虽然使用这个功能很方便,但在程序运行阶段您得了解Java的语义。例如下面的程序是可以通过编译的:
Integer i = null.int j = i.这样的语法在编译时期是合法的,但是在运行时期会有错误,因为这种写法相当于:
Integer i = null.int j = i.intValue().null表示i没有参考至任何的对象实体,它可以合法地指定给对象参考名称。由于实际上i并没有参考至任何的对象,所以也就不可能操作intValue()方法,这样上面的写法在运行时会出现NullPointerException错误。
自动装箱、拆箱的功能提供了方便性,但隐藏了一些细节,所以必须小心。再来看范例4.6,您认为结果是什么呢?
Ü. 范例4.6 AutoBoxDemo2.java
public class AutoBoxDemo2 {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2)
System.out.println("i1 == i2");
else
System.out.println("i1 != i2").
}
}
从自动装箱与拆箱的机制来看,可能会觉得结果是显示i1 == i2,您是对的。那么范例4.7的这个程序,您觉得结果是什么?
Ü. 范例4.7 AutoBoxDemo3.java
public class AutoBoxDemo3 {
public static void main(String[] args) {
Integer i1 = 200;
Integer i2 = 200;
if (i1 == i2)
System.out.println("i1 == i2");
else
System.out.println("i1 != i2");
}
}
结果是显示i1 != i2,这有些令人惊讶,两个范例语法完全一样,只不过改个数值而已,结果却相反。
其实这与==运算符的比较有关,在第3章中介绍过==是用来比较两个基本数据类型的变量值是否相等,事实上==也用于判断两个对象引用名称是否参考至同一个对象。
在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,所以范例4.6中使用==进行比较时,i1 与 i2实际上参考至同一个对象。如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个Integer对象,所以范例4.7使用==进行比较时,i1与i2参考的是不同的对象。
所以不要过分依赖自动装箱与拆箱,您还是必须知道基本数据类型与对象的差异。范例4.7最好还是依正规的方式来写,而不是依赖编译器蜜糖(Compiler Sugar)。例如范例4.7必须改写为范例4.8才是正确的。
Ü. 范例4.8 AutoBoxDemo4.java
public class AutoBoxDemo4 {
public static void main(String[] args) {
Integer i1 = 200;
Integer i2 = 200;
if (i1.equals(i2))
System.out.println("i1 == i2");
else
System.out.println("i1 != i2");
}
}
结果这次是显示i1 == i2。使用这样的写法,相信也会比较放心一些,对于这些方便但隐藏细节的功能到底要不要用呢?基本上只有一个原则:如果您不确定就不要用。
回复 使用道具 举报
赵永康 发表于 2012-9-23 11:19
你是想问什么??两个程序的结果??第一个是true把 第二个是false 我没验证 想想应该是这样的  涉及到享元 ...

你的答案是对的 可是为什么啊。
看源码是这样的,不理解。好像是 缓存了,不知道什么原因
  1. static final Integer cache[] = new Integer[-(-128) + 127 + 1];

  2.         static {
  3.             for(int i = 0; i < cache.length; i++)
  4.                 cache[i] = new Integer(i - 128);
  5.         }
复制代码
回复 使用道具 举报
1.5的新特性,自动装箱操作,如果值在-128~127之间的话底层的cache[]数组是一个地址值,如果超过了可能每次装箱一个操作就要创建一个地址,所以在-128~127之间的值比较为true。
回复 使用道具 举报
楼上回答的很准确啦 就是在-128-127之间java虚拟机就会认为其实常量 就像字符串一样 超过这个范围就不会啦 会重新开启新的内存,虽然内容相同就是用equals比较式true,但是==就错啦  因为他比较的是地址值。equals比较的内容是否相同
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马