把java对象的引用复制给另外一个对象,方法有三个:1.直接赋值、2.浅拷贝、3.深拷贝
1.直接赋值
实际上,直接赋值,是对象引用的复制,即这两个引用是指向同一个内存地址。A a2=a1,引用a1和a2是指向同一个对象,当修改任何一个引用时,都是修改同一个对象。
public class Student {
private String name;
private int age;
private String sex;
public Student(String name,int age,String sex){
this.name=name;
this.age=age;
this.sex=sex;
}
public String getName() {
return name;
}
public void setName(String name){this.name=name;}
public String getSex() {
return sex;
}
public void setSex(String sex){this.sex=sex;}
public int getAge(){
return age;
}
public void setAge(int age){this.age=age;}
}
class MainTest{
public static void main(String[] args){
Student student=new Student("小晴 ",15,"男");
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge()+" 性别:"+student.getSex());
Student student1=student;
student1.setAge(100);
System.out.println("姓名:"+student1.getName()+" 年龄:"+student1.getAge()+" 性别:"+student1.getSex());
}
}
输出:
姓名:小晴 年龄:15 性别:男
姓名:小晴 年龄:100 性别:男
可见两个引用实际指向同一个对象。
2.浅拷贝
如果想要两个引用相互独立,互不影响,我们可以利用Object 的clone()方法。而浅拷贝是指,如果是对象的非静态普通成员变量(值变量),则直接复制;如果是非静态类对象(引用类型),则复制引用但不复制引用的对象。
//对象内成员都是值变量
public class Student implements Cloneable{
private String name;
private int age;
private String sex;
public Student(String name,int age,String sex){
this.name=name;
this.age=age;
this.sex=sex;
}
public String getName() {
return name;
}
public void setName(String name){this.name=name;}
public String getSex() {
return sex;
}
public void setSex(String sex){this.sex=sex;}
public int getAge(){
return age;
}
public void setAge(int age){this.age=age;}
public Object clone(){
try {
return (Student)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
class MainTest{
public static void main(String[] args){
Student student=new Student("小晴 ",15,"男");
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge()+" 性别:"+student.getSex());
Student student1=(Student) student.clone();
student1.setAge(100);
System.out.println("姓名:"+student1.getName()+" 年龄:"+student1.getAge()+" 性别:"+student1.getSex());
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge()+" 性别:"+student.getSex());
}
}
姓名:小晴 年龄:15 性别:男
姓名:小晴 年龄:100 性别:男
姓名:小晴 年龄:15 性别:男
//成员有个类类型引用变量
public class Student implements Cloneable{
private String name;
private int age;
private String sex;
private Mother mother;
public Student(String name,int age,String sex){
this.name=name;
this.age=age;
this.sex=sex;
this.mother=new Mother();
}
public Mother getMother() {
return mother;
}
public void setMother(String name){mother.setName(name);}
public String getName() {
return name;
}
public void setName(String name){this.name=name;}
public String getSex() {
return sex;
}
public void setSex(String sex){this.sex=sex;}
public int getAge(){
return age;
}
public void setAge(int age){this.age=age;}
public Object clone(){
try {
return (Student)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
class MainTest{
public static void main(String[] args){
Student student=new Student("小晴 ",15,"男");
student.setMother("andy");
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge()+" 性别:"+student.getSex()+" mother:"+student.getMother().toString());
Student student1=(Student) student.clone();
student1.setAge(100);
student1.setMother("alice");
System.out.println("姓名:"+student1.getName()+" 年龄:"+student1.getAge()+" 性别:"+student1.getSex()+" mother:"+student1.getMother().toString());
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge()+" 性别:"+student.getSex()+" mother:"+student.getMother().toString());
}
}
姓名:小晴 年龄:15 性别:男 mother:andy
姓名:小晴 年龄:100 性别:男 mother:alice
姓名:小晴 年龄:15 性别:男 mother:alice
可见浅拷贝只会复制值变量,对于引用类型还是只想同一个对象。
3.深拷贝
顾名思义,深拷贝就是要拷贝一个完全独立的对象。在浅拷贝的基础上,我只需要把引用类型变量指向不同的对象即可。只需修改:
//浅拷贝
public void setMother(String name){mother.setName(name);}
//深拷贝
public void setMother(String name) {
mother=new Mother();//重新创建一个对象,即可指向不同的对象空间了。
mother.setName(name);
}
姓名:小晴 年龄:15 性别:男 mother:andy
姓名:小晴 年龄:100 性别:男 mother:alice
姓名:小晴 年龄:15 性别:男 mother:andy
另一种方式,对Mother对象也进行clone方法覆盖:
package com.example.demo.common;
public class Student implements Cloneable {
private String name;
private int age;
private String sex;
private Mother mother;
public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.mother = new Mother();
}
public Mother getMother() {
return mother;
}
public void setMother(String name) {
// mother=new Mother();
mother.setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Object clone() {
Student student=null;
try {
student=(Student) super.clone();
student.mother=(Mother)mother.clone();
return student;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
class MainTest {
public static void main(String[] args) {
Student student = new Student("小晴 ", 15, "男");
student.setMother("andy");
System.out.println("姓名:" + student.getName() + " 年龄:" + student.getAge() + " 性别:" + student.getSex() + " mother:" + student.getMother().toString());
Student student1 = (Student) student.clone();
student1.setAge(100);
student1.setMother("alice");
System.out.println("姓名:" + student1.getName() + " 年龄:" + student1.getAge() + " 性别:" + student1.getSex() + " mother:" + student1.getMother().toString());
System.out.println("姓名:" + student.getName() + " 年龄:" + student.getAge() + " 性别:" + student.getSex() + " mother:" + student.getMother().toString());
}
}
class Mother implements Cloneable {
private String name;
public void setName(String name) {
this.name = name;
}
public String toString() {
return name;
}
public Object clone(){
try {
Mother mother=(Mother)super.clone();
return mother;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}