本文目录导读:

- 方法一:实现
Cloneable接口并重写clone()方法(推荐) - 方法二:使用拷贝构造器(Copy Constructor)
- 方法三:手动字段复制(手动实现)
- 方法四:使用
BeanUtils.cloneBean()(Apache Commons) - 浅拷贝的核心特点
在Java中,浅度拷贝(Shallow Copy)意味着创建一个新对象,然后将原对象的非静态字段的值复制到新对象中,如果字段是基本数据类型,则会复制其值;如果字段是引用类型,则复制的是引用(内存地址),因此新对象和原对象会共享同一个引用类型的子对象。
以下是几种常见的实现浅度拷贝的案例:
实现 Cloneable 接口并重写 clone() 方法(推荐)
这是Java原生支持的浅拷贝方式。
// 1. 定义一个可被浅拷贝的类
class Address implements Cloneable {
String city;
String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
@Override
public String toString() {
return "Address{" + "city='" + city + '\'' + ", street='" + street + '\'' + '}';
}
// 为了演示浅拷贝,Address也需要支持clone(但这里我们不深挖)
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// 2. 实现浅拷贝的主要类
class Person implements Cloneable {
String name;
int age; // 基本类型,直接复制值
Address address; // 引用类型,浅拷贝只复制引用
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
// 重写clone()方法,使用super.clone()实现浅拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
// 关键:调用父类的clone(),默认是浅拷贝
return super.clone();
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", address=" + address + '}';
}
}
// 3. 测试浅拷贝
public class ShallowCopyExample {
public static void main(String[] args) throws CloneNotSupportedException {
Address addr = new Address("北京", "长安街");
Person p1 = new Person("张三", 25, addr);
// 浅拷贝
Person p2 = (Person) p1.clone();
System.out.println("=== 浅拷贝后 ===");
System.out.println("p1 = " + p1);
System.out.println("p2 = " + p2);
// 修改p2的基本类型字段 → 不影响p1
p2.name = "李四";
p2.age = 30;
System.out.println("\n=== 修改p2的基本类型属性后 ===");
System.out.println("p1 = " + p1);
System.out.println("p2 = " + p2);
// 修改p2的引用类型字段(Address对象的内容) → 会影响p1(因为共享同一个Address实例)
p2.address.city = "上海";
System.out.println("\n=== 修改p2的引用类型属性后 ===");
System.out.println("p1 = " + p1);
System.out.println("p2 = " + p2);
// 验证p1和p2的address是否指向同一个对象
System.out.println("\np1.address == p2.address ? " + (p1.address == p2.address)); // true
}
}
输出结果:
=== 浅拷贝后 ===
p1 = Person{name='张三', age=25, address=Address{city='北京', street='长安街'}}
p2 = Person{name='张三', age=25, address=Address{city='北京', street='长安街'}}
=== 修改p2的基本类型属性后 ===
p1 = Person{name='张三', age=25, address=Address{city='北京', street='长安街'}}
p2 = Person{name='李四', age=30, address=Address{city='北京', street='长安街'}}
=== 修改p2的引用类型属性后 ===
p1 = Person{name='张三', age=25, address=Address{city='上海', street='长安街'}}
p2 = Person{name='李四', age=30, address=Address{city='上海', street='长安街'}}
p1.address == p2.address ? true
修改 p2.address.city 会影响 p1.address.city,因为两个对象的 address 字段指向同一个 Address 实例,这就是浅拷贝的特征。
使用拷贝构造器(Copy Constructor)
虽然不直接使用 Object.clone(),但这是另一种常见且更安全的浅拷贝实现方式。
class Person {
String name;
int age;
Address address;
// 常规构造器
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
// 拷贝构造器(实现浅拷贝)
public Person(Person other) {
this.name = other.name;
this.age = other.age;
// 直接复制引用,指向同一个Address对象
this.address = other.address;
}
}
// 使用方式
Person p2 = new Person(p1);
手动字段复制(手动实现)
class Person {
String name;
int age;
Address address;
public Person shallowCopy() {
Person copy = new Person();
copy.name = this.name;
copy.age = this.age;
copy.address = this.address; // 直接赋值引用
return copy;
}
}
使用 BeanUtils.cloneBean()(Apache Commons)
需要引入 commons-beanutils 包,默认也是浅拷贝:
import org.apache.commons.beanutils.BeanUtils; Person p2 = (Person) BeanUtils.cloneBean(p1);
浅拷贝的核心特点
| 字段类型 | 浅拷贝行为 |
|---|---|
| 基本类型(int, long 等) | 复制值,修改拷贝对象不影响原对象 |
| 引用类型(对象、数组) | 复制引用,指向同一个对象,修改一个会影响另一个(共享) |
浅拷贝适合场景:
- 对象只有基本类型字段,没有引用类型字段。
- 或者你确认需要让新对象和原对象共享某些内部对象(例如只读缓存、不可变对象)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播