谈谈Object中为什么要出现clone()
其实这部分是最难讲清楚的,很多文章只讲了,为什么要用super.clone(),为什么要implements Cloneable,如何clone等等
- 都知道Java没有指针的概念,实际上是有“指针”引用的概念;八大基本数据类型的参数传递是按照值传递(即传递的是参数的一个拷贝,参数的值改变不会影响原值);除此之外的其他类型都是按照引用传递(传递对象的引用,指向原对象);"="传递也是引用传递;
- 实际中当我们将对象作为参数传递时,我们不允许某一个方法对该对象有set的权限,只能get,但是其他方法又可以set对象里面的属性(这只是一种假设),或许又干脆不想别人碰你的对象,所以不得不在对象里提供set方法,即这个对象是可更改的对象,或许这可以用封装(在下面演示自己想到的一种方法)或者aop的思想来实现(其实怎么实现自己也不太熟悉),但仅仅为了这个就用封装或者aop可能显得有些麻烦,这时候你只需要在某些地方传递一份对象的拷贝就可以了,随他怎么玩都跟你没有关系。
演示:
一种利用接口来实现第二点需求(红色字体)的代码演示(这似乎违背了接口出现的初衷,即接口不是为了用来干这个事情的)
package modifyTest;
//将所有的get()抽象出来
public interface Info {
String getName();
int getAge();
}
//有一个Person类
package modifyTest;
public class Person implements Info {
private String name;
private int age;
public Person(String name, int typeName) {
this.name = name;
this.age = typeName;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
测试:
package modifyTest;
import org.junit.Test;
public class main {
@Test
public void run(){
Person p = new Person("zhangsan",24);
justGet(p);
canSet(p);
}
//在不允许修改属性的方法里传递接口,那么就只能使用get方法了
private static void justGet(Info inf){
System.out.println("只能获得属性:"+inf.getName()+":"+inf.getAge());
}
//在一般的方法里传递实现类,可以正常访问
private static void canSet(Person p){
System.out.println("原信息:"+p.toString());
p.setName("我改名字了");
System.out.println("修改后:"+p.toString());
}
}
运行结果:
只能获得属性:zhangsan:24
原信息:Person{name='zhangsan', age='24'}
修改后:Person{name='我改名字了', age='24'}
对象的拷贝
- 前面讲了,对象的传递是引用传递,所以一般的赋值法肯定不行的,所以出现了clone,即将对象复制一份。在讲clone()之前,先谈谈另外一种拷贝对象的思路:叫做拷贝构造函数的方式拷贝一个对象,代码演示如下:
-
package CopyConstructors; /* 想要复制一个对象,无非就是复制对象的成员而已,我们可以通过重载构造函数的方式实现 */ public final class Galaxy { private Double mass; privat