支持泛型的克隆接口和克隆类
# 支持泛型的克隆接口和克隆类
# 1. 背景及问题
在 Java 中,原生的 Cloneable
接口和 clone()
方法存在以下几个问题:
Cloneable
是一个标记接口,没有方法定义。clone()
方法在Object
类中定义,返回类型为Object
,需要手动进行类型转换,这既繁琐又容易出错。
为了解决这些问题,Hutool 提供了更加便捷且支持泛型的克隆工具。
# 2. 泛型克隆接口
Hutool 提供了 cn.hutool.core.clone.Cloneable
接口,它定义了一个泛型的 clone()
方法,可以让实现此接口的类在编写时自动提示返回具体类型的 clone()
方法,避免手动类型转换的麻烦。
# 代码示例
import cn.hutool.core.clone.CloneRuntimeException;
import cn.hutool.core.clone.Cloneable;
/**
* 使用 Hutool 泛型 Cloneable 接口的示例类
* 该类实现 Cloneable 接口并提供泛型克隆支持,避免了手动类型转换
*/
public class Cat implements Cloneable<Cat> {
private String name; // 猫的名字
private int age; // 猫的年龄
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 实现泛型的克隆方法
* @return 返回克隆后的 Cat 对象
*/
@Override
public Cat clone() {
try {
// 调用 Object 类的 clone() 方法进行浅拷贝
return (Cat) super.clone();
} catch (CloneNotSupportedException e) {
// 捕获异常并抛出运行时异常
throw new CloneRuntimeException(e);
}
}
@Override
public String toString() {
return "Cat{name='" + name + "', age=" + age + "}";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
代码解释
Cloneable<Cat>
接口:泛型接口,定义了一个泛型的clone()
方法,避免了手动类型转换。clone()
方法实现:通过super.clone()
实现浅拷贝,并捕获可能的CloneNotSupportedException
异常。CloneRuntimeException
异常:Hutool 提供的自定义运行时异常,用于包装CloneNotSupportedException
。
# 实际开发场景
在实际开发中,如果你有一个需要频繁克隆的类,使用 Hutool 的泛型 Cloneable
接口可以简化代码并提高类型安全性。
示例应用
public class Application {
public static void main(String[] args) {
Cat originalCat = new Cat("Miaomiao", 2); // 创建一个 Cat 对象
Cat clonedCat = originalCat.clone(); // 克隆 Cat 对象
// 输出克隆结果
System.out.println(originalCat); // Cat{name='Miaomiao', age=2}
System.out.println(clonedCat); // Cat{name='Miaomiao', age=2}
// 验证是否为不同的对象
System.out.println(originalCat == clonedCat); // false,克隆后的对象是新的实例
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 3. 泛型克隆类
为了进一步简化实现,Hutool 提供了一个已经实现了泛型克隆功能的基类 cn.hutool.core.clone.CloneSupport
。继承这个类可以自动获得克隆能力,无需手动实现 clone()
方法。
# 代码示例
import cn.hutool.core.clone.CloneSupport;
/**
* 使用 Hutool 泛型 CloneSupport 类的示例类
* 通过继承 CloneSupport 类,自动获得克隆功能
*/
public class Dog extends CloneSupport<Dog> {
private String name; // 狗的名字
private int age; // 狗的年龄
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{name='" + name + "', age=" + age + "}";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
代码解释
CloneSupport<Dog>
类:泛型基类,已经实现了clone()
方法,继承此类的子类自动获得克隆功能。- 无需手动实现
clone()
方法:继承CloneSupport
类即可直接调用clone()
。
# 实际开发场景
在实际开发中,如果你需要为某个类提供克隆功能,但不想每次都手动实现 clone()
方法,可以直接继承 CloneSupport
类。
示例应用
public class Application {
public static void main(String[] args) {
Dog originalDog = new Dog("Wangwang", 3); // 创建一个 Dog 对象
Dog clonedDog = originalDog.clone(); // 克隆 Dog 对象
// 输出克隆结果
System.out.println(originalDog); // Dog{name='Wangwang', age=3}
System.out.println(clonedDog); // Dog{name='Wangwang', age=3}
// 验证是否为不同的对象
System.out.println(originalDog == clonedDog); // false,克隆后的对象是新的实例
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4. 深克隆
浅克隆只复制基本数据类型和引用,但对象内部的引用类型依然指向原来的对象。为了实现深克隆(完全复制,包括对象内部的引用),Hutool 提供了 ObjectUtil.cloneByStream()
方法,通过序列化和反序列化的方式进行深度复制。
# 代码示例
import cn.hutool.core.util.ObjectUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 配置类,支持序列化,演示深克隆
*/
public class Config implements Serializable {
private List<String> values; // 配置值列表
public Config(List<String> values) {
this.values = values;
}
public List<String> getValues() {
return values;
}
@Override
public String toString() {
return "Config{values=" + values + "}";
}
}
public class DeepCloneExample {
public static void main(String[] args) {
Config originalConfig = new Config(new ArrayList<>(List.of("value1", "value2"))); // 创建一个配置对象
// 通过 Hutool 的 ObjectUtil.cloneByStream() 方法实现深克隆
Config clonedConfig = ObjectUtil.cloneByStream(originalConfig);
// 修改原对象
originalConfig.getValues().add("value3");
// 输出结果验证深克隆
System.out.println("Original: " + originalConfig); // Original: Config{values=[value1, value2, value3]}
System.out.println("Cloned: " + clonedConfig); // Cloned: Config{values=[value1, value2]}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
代码解释
cloneByStream()
方法:通过序列化和反序列化进行深度复制,适合需要复制复杂对象结构的场景。- 支持深克隆的类:类需要实现
Serializable
接口,以便支持序列化操作。
# 实际开发场景
深克隆适用于需要复制复杂对象(如配置类、模型类)并确保新对象与原对象完全独立的场景。
总结
- 泛型克隆接口:Hutool 的
Cloneable
接口提供了类型安全的克隆方法,避免了手动类型转换的麻烦。 - 泛型克隆类:通过继承
CloneSupport
类,可以简化克隆功能的实现,无需手动编写clone()
方法。 - 深克隆:使用
ObjectUtil.cloneByStream()
可以实现深克隆,适用于复杂对象的完全复制需求。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08