小生刚学Java,有几个问题硬是没想明白,希望各位前辈能不吝赐教^_^。
【问题1】关于==与equals()
小生对==和equals()的工作方式不太了解,麻烦大家解释下下面的代码的输出值:class MyClass
{
    public Integer value1;
}
public class NewClass1 {
    public static void main(String[] args) {
        Integer a0=new Integer("1");
        Integer b0=new Integer("1");
        System.out.println("a0==b0: "+(a0==b0));
        System.out.println("a0.equals(b0): "+a0.equals(b0));
        MyClass a1=new MyClass();
        MyClass b1=new MyClass();
        a1.value1=b1.value1=2;
        System.out.println("a1==b1: "+(a1==b1));
        System.out.println("a1.equals(b1): "+a1.equals(b1));
        System.out.println("a1.value1==b1.value1: "+(a1.value1==b1.value1));
        System.out.println("a1.value1.equals(b1.value1): "+a1.value1.equals(b1.value1));
        Object a2=new Object();
        Object b2=new Object();
        System.out.println("a2==b2: "+(a2==b2));
        System.out.println("a2.equals(b2): "+a2.equals(b2));
    }
}【问题2】关于交换int值引发的问题
【问题2.1】众所周知,C语言中下面的代码可以用来交换a、b的值,而在Java中,运行结果是a=0,b=3。这是为什么?能不能解释一下Java中运算符的结合性。int a=3;
int b=7;
a^=b^=a^=b;【问题2.2】尝试过使用下面的方法交换两个int值,显然无法成功,这是为什么?能不能解释下Java中对象和基本类型的存储、赋值和参数传递的方式?void Swap(Integer a,Integer b)
    {
        Integer temp=a;
        a=b;
        b=temp;
    }【问题2.3】Java中如何使用函数交换两个int值,C++和C#中可以用下列方式实现,Java中就无能为力了么?void Swap(int &a,int &b)
void Swap(ref int a,ref int b)【问题3】break label和continue label怎么使用?下面的代码输出什么,为什么没有陷入死循环呢?    public static void main(String[] args)
    {
        loop:        
            for (int i=1;i<10;++i)
            {
                System.out.println();
                for (int j=i;j<10;++j)
                {
                    if(j==8)
                    {
                        continue loop;
                    }
                    System.out.print("*");
                }
            }        
    }

解决方案 »

  1.   

    问题真够多的.
    a^=b^=a^=b;这个我以前遇到过,好像最左的^=时a的值用的是原来的值,并不是最右面赋值之后的a的值,为什么是这样,不太清楚.
    我是用下面的办法来的解决的,
    b^=a^=b;
    a^=b;
      

  2.   

    初学者先要明白一点:记住这点就好理解了,==是比较的地址,可以理解为比较的是引用,equals比较的是内容,区分开引用和内容的概念就好理解了。刚开始我也是搞不懂。
      

  3.   

    2.2,2.3
    2.2之所以不能交换是因为,java都是值传递,你在方法中交换两个参数的值,实参的值是不会发生变化的。包装类好像都是常量,不能修改。所以不能通过传 基本类型或其包装类型来交换两个值。
      

  4.   

    【问题3】当continue loop;的时候,本次循环结束,准备下次循环开始,i++,  会跳转到最外层的循环,此时如果i<10不满足了必然循环结束   所以不会死循环
      

  5.   

    那为什么
    a1.value1==b1.value1: true
    a1.value1.equals(b1.value1): true
    难道a1.value1与b1.value1地址相同么?但是value1不是静态的呀~~那他们地址为什么相同呢?
      

  6.   

    3 continue label:转到label处执行,但两个循环的状态不变,接着循环(不是重新开始,不会重新赋初值,循环控制变量的值保持不变)。
      break label:转到label处执行,退出break所在的循环,但label处的循环断续。
      

  7.   

    a1.value1==b1.value1: true
    但是value1是Integer类型呀~~,他们为什么会引用到同一个对象呢?是不是因为这条语句?a1.value1=b1.value1=2;
      

  8.   

    那到了这里loop:        
                for (int i=1;i<10;++i)i为什么没有变成1呢?实在是不太明白~~
    i的作用域是什么呢?
      

  9.   


    这个讨论过多次了,
    -128~127之间的Integer用的是常量池中的Integer,不会在堆中重新分配新空间的,所以是同一个常量,地址也就相同了。
      

  10.   


    a1.value1=b1.value1=2;
    的过程是:
    1、创建一个值为 2 的 int
    2、创建一个值为 2 的 Integer(自动装箱)
    3、将这个 Integer 对象的引用同时赋给 b1.value1 和 a1.value1所以 b1.value1 和 a1.value1 得到的是同一个对象的引用。
      

  11.   

    我想楼主还没有理解for()的用法,
    for (int i=1;i<10;++i)
    首先 int i=1 只在循环第一次开始的时候执行
    i<10 用来判断循环条件是否成立
    ++i,是每次循环结束之后执行
      

  12.   

    这个问题我没有发现(我只注意continue了),但是在NetBeans输出是这样的run:*******
    ******
    *****
    ****
    ***
    **
    **成功生成(总时间:0 秒)后来我单步跟踪看了,i=9的时候就跳出循环了,不知道为什么~~
      

  13.   

    输出一样啊   i=9的时候执行完 就跳出循环了 因为i=9的循环执行完后会 ++i  这个时候i=10 不满足条件了所以跳出
      

  14.   


    【问题1】关于==与equals() 
    ==比较的是地址
    equals比较内容和数据类型【问题2.2】尝试过使用下面的方法交换两个int值,显然无法成功,这是为什么?能不能解释下Java中对象和基本类型的存储、赋值和参数传递的方式? 
    Java code
    void Swap(Integer a,Integer b)
        {
            Integer temp=a;
            a=b;
            b=temp;
        }
    【问题2.3】Java中如何使用函数交换两个int值,C++和C#中可以用下列方式实现,Java中就无能为力了么? 
    public void show(int a, int b) {
      a = a + b;
      b = a - b;
      a = a - b;
    }
      

  15.   

    简单点
    ==   对象比较(对象地址/内容比较)
    equals  内容比较
      

  16.   

    Java中,运行结果是a=0,b=3。这是为什么?
    C/C++ code
    int a=3;
    int b=7;
    a^=b^=a^=b;
      

  17.   

    == :比较的是引用,较equals严格,要求两个比较对象指向同一个对象的地址。
    equals :比较的是值相等,可以是两个不同的对象引用。注意有一点:equals是Object对象的成员方法,也就是说我们可以通过重写equals
    改变判断两个对象的值相等的标准,完全有可能两个对象的值理论上不相等(如3!=5)通过
    改写equals方法让他们相等。而至于同一个类的两个对象实例为什么不同了,好像是这样的:一个类每生成一个对象
    实例就会产生一个序列号,如每个人一生下来就有一个身份证id,这个id正是写在equals
    方法中成为判断两个类实例是否相等的标准。还请高人指点上述存在的问题。
      

  18.   

    ==是比较的地址,可以理解为比较的是引用,equals比较的是内容,区分开引用和内容的概念就好理解了
      

  19.   

    问题11.a0==b0: false
    当Integer a0=new Integer("1"); 后编译器是把内容“1”放到堆中存放,它的引用放到栈中起名为a0,其中存放的是 “1”中在堆中的地址。
    每次new的对象都会这样,无论值是否相同。
    a0与b0是两个不同的引用,这里他们也引用着不同的对象(里边存放着堆中不同的地址)。
    a0==b0比较的是a0与b0两个引用(即里边存放着堆的地址),所以是不相同的false。
    但如果  
    Integer a0=1;
    Integer b0=1; 这样定义
    这样定义会把对象放到pool里。java会维护这个对象pool以减少对内存的消耗。当定义b0时候,java会先去pool中查看是否存在该对象,如果有直接返回,否则再new出个新的来。
    所以这个a0 == b0 值是true
    2.a0.equals(b0): true
    当Integer a0=new Integer("1");时,由于你使用的是字符串构造方法
    public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
        }
    最后会把值放到value属性中。
    而在Integer类中equals方法
    public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
        }
    比较的是两个obj从intValue()中得到的value,所以 true
    3.a1==b1: false
    跟上一个类似你定义两个obj后就存放在堆中具有不同的地址,a1与b1分别引用着不同的地址。用==比较的是引用所以是false
    4.a1.equals(b1): false
    a1是MyClass类的对象,而在MyClass这个类中并没有对equals方法进行重写,则调用的是父类Obj的原始equals方法
     public boolean equals(Object obj) {
    return (this == obj);
        }
    比较的是“引用”所以跟用“==”比较结果相同 是false
    5.a1.value1==b1.value1: true
    6.a1.value1.equals(b1.value1): true
    a1.value1=b1.value1=2; 执行后b1.value1的引用与a1.value1的引用相同,而且他们指向的obj的值都是2.所以 5,6都是true
    7.a2==b2: false
    8.a2.equals(b2): false
    a2与b2都是obj类型,跟前面一样定义两个不同地址的对象,a2与b2引用是不同的。即使他们的值都是null但object类中的equals比较的是引用,故也是不同的。都是false表达能力差了些,也请高手指点
      

  20.   

    给楼主第一个问题一个例子,以证明两个牛马不对头的对象通过重写equals 的方法,完全可以相同:
    public class Demo {
    public static void main(String args[]){
    A a=new A();
    B b=new B();
    System.out.println(a.equals(b));
    }
    }
    class A{
    public boolean equals(Object obj){
    return true;
    }
    }
    class B{
    public boolean equals(Object obj){
    return true;
    }
    }运行结果:
    true
      

  21.   

    问题2
    关于连等的问题,深层的意思也不是很懂。下面是我的认识,java中就是这么个策略。连等运算 
    a^=b^=a^=b  与    a = a^b;
     b = b^a;
     a = a^b; 是不等价的
    连等运算是记录初始值的,具体为什么这样?我不知道。但它的策略是这样的
    a^=b^=a^=b
      等价于a=3^b;b=7^a;a=3^b;每个式子的左边的变量是被初始化的。
                          a=3^7; --> 4
                 b=7^4; --> 3
           a=3^3; --> 0不知道明白不 
      

  22.   

    问题2.2
    java中方法中传值都是引用void Swap(Integer a,Integer b)
        {
            Integer temp=a;
            a=b;
            b=temp;
        }这里的 a , b 是引用的复制
    举个例子加入你的代码是这样的
    ...
    Integer a = new Integer(1);
    Integer b = new Integer(2);
    //在定义完a,b时候内存中栈是这样的
    栈            堆
    ----      ---------
    |a |----->|1       |
    ----      |2       |
    |b |----->|        |
    |__|      |________|
    Swap(a,b);
    ....
    当你进入Swap方法里,得到的a,b参数其实不是上面栈中的a,b了。而是两个新的引用可以起名为a1,b1
    栈            堆
    ----      ---------
    |a |----->|1       |
    ----      |2       |
    |b |----->|        |
    |__|      --^-------
    |a1|--------|
    ----        ^
    |b1|--------|
    |__|
    a1,b1也指向堆中1,2地址,但在方法中不管你怎么操作,都只是a1,b1两个引用。不会影响到原来的a,b,a,b中的指向并没有因为方法里的折腾而变化。
    这就是引用传值与c是不一样的。但如果你改变的是a,b中的property ,这样就会发生变化。为什么呢?
    这里传到方法中的依然是引用的复制 a1,b1。但它们的指向是堆中原来的obj,你改变堆中obj的属性,原来的a,b是跟它们的复制指向的是同一个obj。所以都会发生改变
    例如public class MyClass {
    public Integer value1 ;
    }public static void main(String[] args) {
    // TODO Auto-generated method stub
            MyClass a  = new MyClass();
            a.value1 = 1;
            MyClass b  = new MyClass();
            b.value1 = 2;
            swap(a,b);
            System.out.println(a.value1);
            System.out.println(b.value1);
    }
    private static void swap(MyClass a,MyClass b){
    a.value1=2;
    b.value1=1;
    }
    输出的结果是 2 ,1 发生了变化
    这种情况跟上面的是两回事
      

  23.   

    continue的意思就是跳出当前的循环,执行下一次的循环。
    你定义loop:只能放在for语句上。
    指的是
    当执行continue时候,会继续执行loop所在的for上的下一次循环。所以没有重新执行for循环而是接着循环下一次,当然i也就自动加1没有变为初始值。
    循环变量的作用域当然是在循环体里了,出了循环就释放掉了。break道理是一样的,只不过是跳出当前循环。你定义的loop是指定执行break时跳出的循环体。所以你这段代码不可能一直重新跑,等最外层的循环执行完也就完了。我回答的是不是你想要问的 
      

  24.   

    这个有什么办法么?
    [/Quote]没有办法,除非把a,b放入对象内,再把对象的引用传给swap方法.
      

  25.   

    32楼的解释清楚了的~~~
    本来equals造出来就是想比较内容的,但如果你新写一个类的话,不重写equals方法,就会调用Object中的equals方法,而Object中的equals确还是比较地址的,所以这儿就有问题了。
    但好比Integer、String这类的就不一样了,因为它们已经重写了equals方法,用来比较内容了,与你新写的类不一样