1.为什么有拷贝?
因为new一个对象太占用资源,当要复制大量对象的时候用拷贝实现的方式很有优势,很快。
2.浅拷贝与深拷贝
浅拷贝是指对一个类进行拷贝是,会对基本数据类型进行值传递(string也是基本类型),而对于类属性中对象类型变量(包括数组)会让他们直接指向同一个内存地址,所以修改其中一个的值会影响到拷贝对象中的值,所以具有局限性
深拷贝基本数据类型拷贝同浅拷贝一样,引用类型变量会直接拷贝,而不是让他们指向同一地址。
具体实现方式:1.通过Object中的clone方法; 2.自己通过构造函数方式实现;3.序列化方法实现
直接赋值
直接赋值是我们最常用的方式,在我们代码中的体现是Persona = new Person();Person b = a
,是一种简单明了的方式,但是它只是拷贝了对象引用地址而已,并没有在内存中生成新的对象,我们可以通过下面这个例子来证明这一点
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.tompai.clone;
/**
* @desc: demo
* @name: SimplePerson.java
* @author: tompai
* @email:liinux@qq.com
* @createTime: 2020年1月3日 下午1:21:28
* @history:
* @version: v1.0
*/
public class SimplePerson {
// 姓名
private String name;
// 年龄
private int age;
// 邮件
private String email;
// 房屋描述
private String houseDesc;
public SimplePerson(String name, int age, String email, String houseDesc) {
super();
this.name = name;
this.age = age;
this.email = email;
this.houseDesc = houseDesc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getHouseDesc() {
return houseDesc;
}
public void setHouseDesc(String houseDesc) {
this.houseDesc = houseDesc;
}
@Override
public String toString() {
return "{\"name\":\"" + name + "\", \"age\":\"" + age + "\", \"email\":\"" + email + "\", \"houseDesc\":\""
+ houseDesc + "\"}";
}
}
测试:
// 初始化一个对象
SimplePerson tompai = new SimplePerson("tompai", 20, "liinux@qq.com", "i am tompai.");
// 直接赋值
SimplePerson tompai1 = tompai;
// 改变 person1 的属性值
tompai1.setName("not tompai");
System.out.println("person对象:" + tompai);
System.out.println("person直接赋值对象:" + tompai1);
我们将 person 对象复制给了 person1 对象,我们对 person1 对象的 name 属性进行了修改,并未修改 person 对象的name 属性值,但是我们最后发现 person 对象的 name 属性也发生了变化,其实不止这一个值,对于其他值也是一样的,所以这结果证明了我们上面的结论:直接赋值的方式没有生产新的对象,只是生新增了一个对象引用,直接赋值在 Java 内存中的模型大概是这样的
浅拷贝
浅拷贝也可以实现对象克隆,从这名字你或许可以知道,这种拷贝一定存在某种缺陷,是的,它就是存在一定的缺陷,先来看看浅拷贝的定义:如果原型对象的成员变量是值类型,将复制一份给克隆对象,也就是说在堆中拥有独立的空间;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。换句话说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。 可能你没太理解这段话,那么我们在来看看浅拷贝的通用模型:
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the A