您的位置:首页 > 移动开发 > Objective-C

谈谈 Object 类

2016-03-18 16:04 447 查看

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=a2
a2.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=a1
a2.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;@16352be6
a1.name=xxzz
a1.list.size=2
a2.name=[Ljava.lang.String;@16352be6
a2.name=xxzz
a2.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;@3cbdcccc
a1.name=xxyy
a2.name=[Ljava.lang.String;@50d0843b
a2.name=xxzz


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

int hashCode() 方法

返回该对象的哈希码值(是一串数字 int 类型)。

如果有必要,子类要对这个方法进行重写,让子类和父类的 hashcode() 返回值不一样。

两个对象不相等,那么这两个对象的 hashcode() 返回值可能不一样,但是程序员应该意识到,为不相等的对象产生不同整数结果可以提高哈希表性能。

equals() 方法

如果重写了 equals 方法,则必须重写 hashCode() 方法。因为如果 equals 返回 true,hashCode() 返回值必须是相同值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: