setter/getter
new 新对象后用 set/get 方法设置属性
浅克隆
被复制的类需要实现Clonenable接口(不实现的话在调用 clone 方法会抛出 CloneNotSupportedException 异常), 该接口为标记接口(不含任何方法)
覆盖clone() 方法,访问修饰符设为 public。方法中调用 super.clone() 方法得到需要的复制对象 class Address
{
private String address;
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
}
class Student implements Cloneable
{
private int number;
private Address addr;
public Address getAddr()
{
return addr;
}
public void setAddr(Address addr)
{
this.addr = addr;
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
@Override
public Object clone()
{
Student stu = null;
try
{
stu = (Student) super.clone(); //浅复制
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return stu;
}
}
public class Test
{
public static void main(String args[])
{
Address addr = new Address();
addr.setAddress("杭州市");
Student stu1 = new Student();
stu1.setNumber(123);
stu1.setAddr(addr);
Student stu2 = (Student) stu1.clone();
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress());
stu2.setNumber(124);
addr.setAddress("西湖区");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress());
}
}
/*
输出
学生1:123,地址:杭州市
学生2:123,地址:杭州市
学生1:123,地址:西湖区
学生2:124,地址:西湖区
*/
通过浅克隆获得新对象,其基本数据类型成员变量得到了复制,修改后不影响原对象
若变量为引用数据类型,则只复制地址引用,还是指向相同地址,修改时会相互影响
若变量为 String 类型,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有字符串对象保持不变
深克隆
浅复制只是复制了addr 变量的引用,并没有真正的开辟另一块空间,将值复制后再将引用返回给新对象
为了达到真正的复制对象,而不是纯粹引用复制。我们需要将 Address 类可复制化,并且修改 clone 方法,代码如下: class Address implements Cloneable
{
private String address;
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
@Override
public Object clone()//Address 类可复制化
{
Address addr = null;
try
{
addr = (Address) super.clone();
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return addr;
}
}
class Student implements Cloneable
{
private int number;
private Address addr;
public Address getAddr()
{
return addr;
}
public void setAddr(Address addr)
{
this.addr = addr;
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
@Override
public Object clone()
{
Student stu = null;
try
{
stu = (Student) super.clone(); //浅复制
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
stu.addr = (Address) addr.clone(); //引用数据类型变量深复制
return stu;
}
}
public class Test
{
public static void main(String args[])
{
Address addr = new Address();
addr.setAddress("杭州市");
Student stu1 = new Student();
stu1.setNumber(123);
stu1.setAddr(addr);
Student stu2 = (Student) stu1.clone();
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress());
stu2.setNumber(124);
addr.setAddress("西湖区");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress());
}
}
/*
输出
学生1:123,地址:杭州市
学生2:123,地址:杭州市
学生1:123,地址:西湖区
学生2:124,地址:杭州市
*/
工具类
org.apache.commons 组件 BeanUtils 和 PropertyUtils,静态方法 copyProperties(Object o1,Object o2)
序列化
序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作 class Professor implements Serializable
{
String name;
int age;
Professor(String name, int age)
{
this.name = name;
this.age = age;
}
}
class Student implements Serializable
{
String name;//常量对象
int age;
Professor p;//引用数据类型
Student(String name, int age, Professor p)
{
this.name = name;
this.age = age;
this.p = p;
}
//深克隆
public Object deepClone() throws IOException, ClassNotFoundException
{
//将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
}
public class Test
{
public static void main(String[] args) throws IOException, ClassNotFoundException
{
Professor p = new Professor("wangwu", 50);
Student s1 = new Student("zhangsan", 18, p);
Student s2 = (Student) s1.deepClone();
s2.p.name = "lisi";
s2.p.age = 30;
System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age);
//学生1的教授不改变
}
}