[Java]PTA:(选做) jmu-Java-03面向对象基础-clone方法、标识接口、深拷贝
Object的clone
方法可以帮助我们克隆对象。现在需编写一个类Car
包含:
1.属性:
private String name;
private CarDriver driver;
private int[] scores;
2.无参构造函数
public Car() {
}
3.方法:
@Override
public String toString() {return "Car [name=" + name + ", driver=" + driver + ", scores=" + Arrays.toString(scores) + "]";
}
setter/getter方法与clone
方法。注意:clone
方法需实现对象的深度克隆。
CarDriver
为已经定义好的类,部分代码如下:
class CarDriver {private String name;public CarDriver() {}//setter/getter//toString
}
/* 请在这里填写答案,即Car类的完整代码 */
代码如下:
class Car implements Cloneable {// 属性private String name;private CarDriver driver;private int[] scores;// 无参构造函数public Car() {}// getter和setter方法public String getName() {return name;}public void setName(String name) {this.name = name;}public CarDriver getDriver() {return driver;}public void setDriver(CarDriver driver) {this.driver = driver;}public int[] getScores() {return scores;}public void setScores(int[] scores) {this.scores = scores;}// 重写clone方法实现深拷贝@Overridepublic Car clone() throws CloneNotSupportedException {// 先进行浅拷贝Car cloned = (Car) super.clone();// 深拷贝CarDriver:创建新对象并复制属性if (this.driver != null) {CarDriver newDriver = new CarDriver();newDriver.setName(this.driver.getName()); // 复制name属性cloned.setDriver(newDriver);}// 深拷贝数组if (this.scores != null) {cloned.scores = Arrays.copyOf(this.scores, this.scores.length);}// String类型本身不可变,无需额外处理return cloned;}@Overridepublic String toString() {return "Car [name=" + name + ", driver=" + driver + ", scores=" + Arrays.toString(scores) + "]";}
}
学习记录:
1、clone() 方法
clone() 方法是 Object 类中定义的一个原生方法,所有 Java 类都默认继承了这个方法。
Object 类中 clone() 方法的声明如下:
protected native Object clone() throws CloneNotSupportedException;
注意:
1)访问修饰符是 protected:这意味着如果子类不重写 clone() 方法并修改访问权限(通常改为 public),则只能在同一个包或子类中调用该方法。
2)需要实现 Cloneable 接口:Cloneable 是一个标识接口(无任何方法),如果类没有实现它,调用 clone() 会抛出 CloneNotSupportedException。
3)默认浅拷贝:Object 类的 clone() 方法默认实现的是浅拷贝—— 对于基本类型属性会复制值,对于引用类型属性只会复制引用(两个对象共享同一个引用指向的实例)。
4)返回值是 Object 类型:因此重写时通常需要进行类型强转,例如 Car cloned = (Car) super.clone();
2、重写clone()方法的语法格式
// 1. 实现Cloneable接口(标识接口,无方法)
public class 类名 implements Cloneable {// 成员变量...// 2. 重写clone()方法,修改访问权限为public@Overridepublic 类名 clone() throws CloneNotSupportedException {// 3. 调用父类(Object)的clone()方法完成基础拷贝类名 克隆对象 = (类名) super.clone();// 4. (可选)如果需要深拷贝,这里补充引用类型成员的克隆逻辑// 例如:克隆对象.引用类型成员 = 原对象.引用类型成员的拷贝;return 克隆对象;}
}
注意:
1)要实现 Cloneable 接口:这是一个 “标识接口”(无任何方法),仅用于告诉 JVM:该类允许被克隆。如果不实现此接口,调用 clone() 会抛出 CloneNotSupportedException。
2)重写 clone() 方法:
- 必须声明抛出CloneNotSupportedException(或在方法内捕获)。
- 访问权限从 Object 类的 protected 改为 public,否则外部无法调用。
- 返回值从 Object 改为当前类类型,避免外部强转。
3)调用 super.clone() :这是克隆的核心步骤,Object 类的 clone() 会创建一个新对象,并将原对象的所有成员变量值(包括基本类型和引用类型的引用)复制到新对象中(浅拷贝)。
4)若是深拷贝:需要处理引用类型成员对于引用类型(如对象、数组等),super.clone() 只会复制引用(浅拷贝)。若要深拷贝,需为这些成员单独创建副本,例如:
- 数组:使用 Arrays.copyOf() 或 System.arraycopy()
- 自定义对象:调用该对象的 clone() 方法(需确保其也实现了 Cloneable 并正确重写 clone())