谈谈 Object 类

来源:互联网 发布:数据筛选软件 编辑:程序博客网 时间:2024/05/21 22:23

clone() 方法

Java 中并没有指针的概念,许多程序员往往会忽略对象与引用的区别。 

Java 不能通过简单的赋值来解决对象复制的问题,常用 clone() 方法来复制对象。比如函数参数类型是自定义的类时,此时便是引用传递而不是值传递。

请看如下代码:

// 测试代码:A a1=new A();A a2=new A(); a1.name="a1";a2=a1;a2.name="a2";System.out.println("a1.name="+a1.name);System.out.println("a2.name="+a2.name);// 输出结果:a1.name=a2a2.name=a2

其实 al 和 a2 指向同一块内存地址,修改一个必然会影响到另一个。如果希望修改 a1 不影响到 a2 的话,可以使用 clone() 方法。

使用 clone() 方法要求如下:

1. 必须实现 Cloneable 接口(为什么呢?该接口是空的,可以看做是一个规定,如果不实现该接口,就会报 ClassNotSupported 异常。类似的还有 Serializable 接口)

2. 必须重载 clone() 方法,使用 super.clone() 调用 Object 类的 clone() 方法。

// 测试代码public class A implements Cloneable{    public  String name;    public Object clone() {        A obj = null;        try{            obj =(A)super.clone();        }catch(CloneNotSupportedException e){            e.printStackTrace();        }        return obj;    }}public class ObjectTest {    @Test    public void testClone(){        A a1 = new A();        a1.name= "a1";        A a2 = (A)a1.clone();        a2.name = "a2";        System.out.println("a1.name="+a1.name);        System.out.println("a2.name="+a2.name);    }}// 输出结果:a1.name=a1a2.name=a2

由输出结果可以看出,当 Class A 的成员变量类型都为基本类型的时候,只要如上面进行简单的 clone() 就可以了(称为影子克隆)。 

但是如果 Class A 的成员变量类型包括非基本类型的话,请看下面例子:

// 测试代码public class A implements Cloneable {    public String[] name;    public A() {        name = new String[2];        name[0] = "xx";        name[1] = "yy";    }    public Object clone() {        A obj = null;        try {            obj = (A) super.clone();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return obj;    }}public class ObjectTest {    @Test    public void testClone(){        A a1 = new A();        A a2 = (A)a1.clone();        a2.name[1]="zz";        System.out.println("a1.name="+a1.name);        System.out.println("a1.name="+a1.name[0]+a1.name[1]);        System.out.println("a2.name="+a2.name);        System.out.println("a2.name="+a2.name[0]+a2.name[1]);    }}// 输出结果:a1.name=[Ljava.lang.String;@16352be6a1.name=xxzza1.list.size=2a2.name=[Ljava.lang.String;@16352be6a2.name=xxzza2.list.size=2
由此看出,如果类中有复杂的成员变量,影子克隆已经达不到效果,因为两个对象的成员变量指向的地址还是一样的,这时候就需要使用深度 clone,成员变量也需要进行 clone。

// 代码public class A implements Cloneable {    public String[] name;    public A() {        name = new String[2];        name[0] = "xx";        name[1] = "yy";    }    public Object clone() {        A obj = null;        try {            obj = (A) super.clone();            obj.name = (String[])name.clone();                  } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return obj;    }}public class ObjectTest {    @Test    public void testClone(){        A a1 = new A();        A a2 = (A)a1.clone();        a2.name[1]="zz";        System.out.println("a1.name="+a1.name);        System.out.println("a1.name="+a1.name[0]+a1.name[1]);        System.out.println("a2.name="+a2.name);        System.out.println("a2.name="+a2.name[0]+a2.name[1]);    }}// 输出a1.name=[Ljava.lang.String;@3cbdcccca1.name=xxyya2.name=[Ljava.lang.String;@50d0843ba2.name=xxzz

类复制成功,且 al 和 a2 之间不会相互影响。clone() 方法的分析到此结束。


int hashCode() 方法

返回该对象的哈希码值(是一串数字 int 类型)。 
如果有必要,子类要对这个方法进行重写,让子类和父类的 hashcode() 返回值不一样。 
两个对象不相等,那么这两个对象的 hashcode() 返回值可能不一样,但是程序员应该意识到,为不相等的对象产生不同整数结果可以提高哈希表性能。


equals() 方法

如果重写了 equals 方法,则必须重写 hashCode() 方法。因为如果 equals 返回 true,hashCode() 返回值必须是相同值。


0 0
原创粉丝点击