引用等同性与对象等同性及对象复制

来源:互联网 发布:史崔克 知乎 编辑:程序博客网 时间:2024/04/30 14:04

 在Java中判断一个对象是否“相等”,往往引入一些混乱的认识,本文就介绍一下,他们到底有什么差别。

Java中的判等可以分为引用等同性和对象等同性两类。

对于任何引用类型而言,该类型的某个变量所保存的值是一个引用,这个引用或者是特殊值null,或者是一个指向内存的指针。引用类型的赋值只是对引用的复制过程。因此,赋值过程不会创建一个新对象,只是为同一个对象创建了另外的一个名称(引用)而已。这一规则适用于数组、字符串和用户定义的类,但是对基本类型,如int、float等是不适用的。

当对基本数据类型使用==时比较的具体的内容,而不是引用。例如:

 public class TestIntComparison {
        public static void main(String[] args) {
                int x = 5, y = 5;
                System.out.println(    "x == y yields " + (x == y));
        }
}

输出:

x == y yields true 

用于对象时比较的是对象的引用而不是对象的实际内容。下面举一个例子:

class Dog{

        int age;
        int height;
        int length;
        public Dog(int a,int h,int l){
                this.age = a;
                this.height = h;
                this.length = l;
        }
}

public class TestOjbectComparison{
        public static void main(String args[]){
                Dog s = new Dog(2,3,4);
                Dog ss = s;
                Dog w = new Dog(2,4,5);
                Dog q = new Dog(3,6,9);

                Dog [] arr,arr2,arr3,arr4;
                arr = new Dog[5];
                arr[0] = s;
                arr[1] = ss;
                arr[2] = w;
                arr[3] = q;

                arr2 = arr;
                arr3 = (Dog [])arr.clone();

                System.out.println("Dog Object s==ss is "+(s==ss));
                System.out.println("Dog Object s==q is "+(s==q));
                System.out.println("Array arr == arr2 is "+ (arr == arr2));
                System.out.println("Array arr == arr3 is "+ (arr == arr3));

                System.out.println("Dog Object s.equals(ss) is "+(s.equals(ss)));
                System.out.println("Dog Object s.equals(q) is "+(s.equals(q)));
                System.out.println("Array arr.equals(arr2) is "+ (arr.equals(arr2)));
                System.out.println("Array arr.equals(arr3) is "+ (arr.equals(arr3)));
        }
}

这时内存中的数据结构如下图所示:

 

代码输出结果如下:

Dog Object s==ss is true
Dog Object s==q is false
Array arr == arr2 is true
Array arr == arr3 is false
Dog Object s.equals(ss) is true
Dog Object s.equals(q) is false
Array arr.equals(arr2) is true
Array arr.equals(arr3) is false

以上代码和图示说明了如下问题:

1. 引用类型的赋值只是对引用的赋值过程;

2. 要赋值一个新的对象,例如arr3,就要使用clone方法

3. clone方法只是对原对象中的引用复制一份,引用所指向的对象并不被复制,比如arr和arr3共享了数组中具体的对象,虽然arr3已经比arr2有了自己的引用

4. 要复制对象中指向的对象,需要重载clone方法

5. Object对象的equals方法的默认实现是 引用等同性比较(见下面的代码),如果要做对象等同性比较,还需要重载equals方法。

     public boolean equals(Object obj) {
 return (this == obj);
    }

 一个重载equals方法的例子如下:

        public boolean equals(Object o){
                if(o instanceof Dog){
                        Dog d = (Dog)o;
                        if((this.age == d.age)&&(this.height == d.height)&&(this.length == d.length))
                                return true;
                }
                        return false;
        }

String对象的equals方法已经被重载过了,所以下面的代码

                boolean hi = ("abc" == "abc");
                String str = new String("abc");
                str.equals("abc");

都返回true