浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值。
深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。
更通俗的描述:浅拷贝只复制一个对象,传递引用,不能复制实例。深拷贝对对象内部的引用均复制,它是创建一个新的实例,并且复制实例。
注意:如果变量都是基本数据类型;浅拷贝跟深拷贝都是一样的。
public class Person {
private String name;
private String sex;
private int age;
public Person(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public Person(Person person){
this.name = person.name;
this.sex = person.sex;
this.age = person.age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Asian {
private String skin;
Person mPerson;
public Asian(String skin, Person person) {
this.skin = skin;
mPerson = person;
}
public Asian(Asian asian){
this(asian.skin,asian.mPerson);
}
public static void main(String [] args){
Person person = new Person("Uart", "men", 23);
Person person1 = new Person(person);
System.out.println(person.toString());
System.out.println(person1.toString());
System.out.println(person1 == person);
Asian a1 = new Asian("yellow", new Person("Uart", "men", 23));
Asian a2 = new Asian(a1);
System.out.println(a1.toString());
System.out.println(a2.toString());
System.out.println(a1 == a2);
System.out.println(person.getName());
System.out.println(person1.getName());
System.out.println(person.getName() == person1.getName());
person.setName("Jhon");
//String是不可变对象,在拷贝的时候会被复制
System.out.println(person.getName());
System.out.println(person1.getName());
System.out.println(person.getName() == person1.getName());
}
}
总结:
1.基本类型
如果变量是基本类型,则拷贝它的值,比如int、float等;
2.对象
如果变量是一个实例对象,则拷贝其地址引用。也就是说新对象与旧对象指向同一个地址引用
3.String字符串
String是不可变对象,在拷贝的时候会被复制。
扩展知识
利用序列化实现对象的拷贝
直接上代码
使用该方法无需继承Cloneable接口实现clone()方法;该工具类的对象只要实现Serializable接口就可以实现对象的克隆。
public static
补充
浅拷贝例子
//获取真实数据
GetDateList getDateList = new GetDateList();
//获取当前年份数据(寿命期与年公用同一份数据)
year = getDateList.getYear();
//第一次进来展示最新数据
month = getDateList.getMonth(year.get(year.size() - 1));
//第一次进来展示当前天数
day = getDateList.getDay(year.get(year.size() - 1));
Log.e("TAG", "year地址值 : " + year + " month地址值 : " + month + " day地址值 : " + day);
/**
* 获取真实数据
* @param year
* @param month
* @param day
*/
private void getRealDate(ArrayList year, ArrayList month, ArrayList day) {
switch (type) {
case 2 :
case 3 :
list = year;
break;
case 1 :
list = month;
break;
case 0 :
list = day;
break;
}
}
@Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
switch (checkedId) {
case R.id.radio_day:
type = 0;
list.clear();
Log.e("TAG radio_day", "year地址值 : " + year + " month地址值 : " + month + " day地址值 : " + day);
getRealDate(year, month, day);
adapter.setList(list);
adapter.setType(type);
adapter.getClickList().clear();
adapter.notifyDataSetChanged();
break;
case R.id.radio_month:
type = 1;
list.clear();
Log.e("TAG radio_month", "year地址值 : " + year + " month地址值 : " + month + " day地址值 : " + day);
getRealDate(year, month, day);
adapter.setList(list);
adapter.setType(type);
adapter.getClickList().clear();
adapter.notifyDataSetChanged();
break;
case R.id.radio_year:
type = 2;
list.clear();
Log.e("TAG radio_year", "year地址值 : " + year + " month地址值 : " + month + " day地址值 : " + day);
getRealDate(year, month, day);
adapter.setList(list);
adapter.setType(type);
adapter.getClickList().clear();
adapter.notifyDataSetChanged();
break;
case R.id.radio_total:
type = 3;
list.clear();
Log.e("TAG radio_total", "year地址值 : " + year + " month地址值 : " + month + " day地址值 : " + day);
getRealDate(year, month, day);
adapter.setList(list);
adapter.setType(type);
adapter.getClickList().clear();
adapter.notifyDataSetChanged();
break;
}
}
这是因为浅拷贝导致数据clear原始数据也被clear。这里最简单的修改方式是addAll而不采用直接 =来赋值