public class TestWhile{      //1
     public static void main(String[] args)//2
    {
 
       Integer i=0;//3
        Integer j=0;//4
   //     Integer i=new Integer(0);//5
       // Integer j=new Integer(0);//6
              while(i<=j & i>=j & i!=j)//7
                   {                   //8
                       System.out.println("0000");//9
              }    }}
那一行是拆箱?while循环里的条件看似不成立,可为什么可以运行(去掉第5、6行的注释后)?

解决方案 »

  1.   

    第七行是拆箱。while不成立,可以运行。结果为false嘛。0==0。去掉注释。把34注释了。因为是对象。肯定不相等了。至于为什么是对象,我也不知道。
      

  2.   

    第7行有6次拆箱  i<=j  拆两次,拆箱后的代码相当于
    while(i.intValue()<=j.intValue() & i.intValue()>=j.intValue() & i.intValue()!=j.intValue())while条件不成立的原因是: 
    i 是 0,j 也是0
    i<=j 是 true
    i>=j 是 true
    i!=j 是 false
    true & true & false 是 false,所以条件不成立
      

  3.   


    因为 i, j 被定义成了 Integer,所以是对象
      

  4.   

    while(i<=j & i>=j & i!=j) 肯定不成立啦 i!=j
    但程序可以运行,只是while条件不成立而已,不输出 0000
    while(i<=j & i>=j & i!=j) 这句是拆箱
      

  5.   


    分析的很详细,还要注意& 与 &&的区别
      

  6.   


     Integer i=new Integer(0);
     Integer j=new Integer(0);
     while (i <= j & i >= j & i != j){ 
         System.out.println("0000");
     }i <= j  true
    i >= j  true
    这两句是自动拆箱
    i != j  true
    这句比较的是对象,i,j是两个不同的对象。
    所以这个条件是true的。语句自然可以执行
    记得在java解惑这本书看到过这个题
      

  7.   

    3、4行是装箱,i、j是两个指向Integer对象的引用,实际效果同5、6行一样
    7行i<=j 和 i>=j 是拆箱成int比大小,都为true;i!=j 则是判断i和j是否指向同一对象,显然i、j是指向两个对象,i!=j也为true。while循环条件成立,9行会得到执行
      

  8.   

    java 5以后会自动装箱拆箱
      

  9.   


    public class Test { //1    public static void main(String[] args)//2
        {
            Integer i = 0;//3
            Integer j = 0;//4
            // Integer i=new Integer(0);//5
            // Integer j=new Integer(0);//6
            while (i <= j & i >= j & i != j)//7
            { //8
                System.out.println("0000");//9
            }    }
    }这种情况下,循环不能运行。
    对于Integer类型,<,<=,>,>=操作将导致拆箱操作,也就是调用Integer的intValue()方法得到相应的基本类型值,然后比较。
    ==,!=比较变量的值。 Integer i = 0;//3
     Integer j = 0;//4
    这两句使用装箱操作,也就是调用Integer.valueOf(int i);注意,不是使用new。Integer中,valueOf(int i)的方法体为: public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // must cache 
        return IntegerCache.cache[i + offset];
    }
            return new Integer(i);
        }
    //预先创建的Integer对象,-128~+127
     private static class IntegerCache {
    private IntegerCache(){} static final Integer cache[] = new Integer[-(-128) + 127 + 1]; static {
        for(int i = 0; i < cache.length; i++)
    cache[i] = new Integer(i - 128);
    }
        }所以,i和j引用的是同一个对象。
    综上,i<=j & i>=j & i!=j中,
    i<=j 和 i>=j都成立,而i!=j不成立,因为i和j引用的是同一个对象。故此,循环不会执行。注释掉3,4两句,使用5,6两句时,i和j引用的不是同一个对象,所以i!=j成立。i<=j & i>=j & i!=j成立,循环条件总是成立的,while (i <= j & i >= j & i != j)成为无穷循环,不断输出。
      

  10.   

    3 4行指向同一个对象,因为这是常量对象.  就好比 String a="1";String b="1";内存中没有使用两个空间存放他们.
      

  11.   

    引用《Java解惑》
    循环者的诅咒
    请提供一个对i的声明,将下面的循环转变为一个无限循环: 
    while (i <= j && j <= i && i != j) {
    }
    噢,不,不要再给我看起来不可能的循环了!如果i <= j 并且 j <= i,i不是肯定等于j吗?这一属性对实数肯定有效。事实上,它是如此地重要,以至于它有这样的定义:实数上的≤关系是反对称的。Java的<=操作符在5.0版之前是反对称的,但是这从5.0版之后就不再是了。 
    直到5.0版之前,Java的数字比较操作符(<、<=、>和>=)要求它们的两个操作数都是原始数字类型的(byte、char、short、int、long、float和double)[JLS 15.20.1]。但是在5.0版中,规范作出了修改,新规范描述道:每一个操作数的类型必须可以转换成原始数字类型[JLS 15.20.1,5.1.8]。问题难就难在这里了。 
    在5.0版中,自动包装(autoboxing)和自动反包装(auto-unboxing)被添加到了Java语言中。如果你对它们并不了解,请查看:http://java.sun.com/j2se/5.0/docs/guide/language/autoboxing.html [Boxing]。<=操作符在原始数字类型集上仍然是反对称的,但是现在它还被应用到了被包装的数字类型上。(被包装的数字类型有:Byte、Character、Short、Integer、Long、Float和Double。)<=操作符在这些类型的操作数上不是反对称的,因为Java的判等操作符(==和!=)在作用于对象引用时,执行的是引用ID的比较,而不是值的比较。 
    让我们更具体一些,下面的声明赋予表达式(i <= j && j <= i && i != j)的值为true,从而将这个循环变成了一个无限循环: 
    Integer i = new Integer(0);
    Integer j = new Integer(0);
    前两个子表达式(i <= j 和j <= i)在i和j上执行解包转换[JLS 5.1.8],并且在数字上比较所产生的int数值。i和j都表示0,所以这两个子表达式都被计算为true。第三个子表达式(i != j)在对象引用i和j上执行标识比较,因为它们都初始化为一个新的Integer实例,因此,第三个子表达式同样也被计算为true,循环也就永远地环绕下去了。 
    你可能会感到奇怪,为什么语言规范没有修改为:当判等操作符作用于被包装的数字类型时,它们执行的是值比较。答案很简单:兼容性。当一种语言被广泛使用之后,以违反现有规范的方式去改变现有程序的行为是让人无法接受的。下面的程序过去总是保证可以打印false,因此它必须继续保持此特征: 
    public class ReferenceComparison {
        public static void main(String[] args) {
            System.out.println(
                 new Integer(0) == new Integer(0));
        }
    }
    判等操作符在其两个操作数中只有一个是被包装的数字类型,而另一个是原始类型时,执行的确实是数值比较。因为这在5.0版之前是非法的,所有在这里没有任何兼容性的问题。让我们更具体一些,下面的程序在1.4版中是非法的,而在5.0版中将打印true: 
    public class ValueComparison {
        public static void main(String[] args) {
            System.out.println(
                 new Integer(0) == 0);
        }
    }
    总之,当两个操作数都是被包装的数字类型时,数值比较操作符和判等操作符的行为存在着根本的差异:数值比较操作符执行的是值比较,而判等操作符执行的是引用标识的比较。 
    对语言设计者来说,如果判等操作符一直执行的都是数值比较(谜题13),那么生活可能就要简单得多、快乐得多。也许真正的教训应该是:语言设计者应该拥有高质量的水晶球,以预测语言的未来,并且做出相应的设计决策。严肃一点地讲,语言设计者应该考虑语言可能会如何演化,并且应该努力去最小化在演化之路上的各种制约影响。