赞
踩
目录
目标:通过调用object的clone方法将对象student1的内容拷贝到student2中去
省流总结:浅拷贝的常见问题:
1:Object的clone方法是protected修饰需要在克隆类中重写
2:编译时异常/受查异常
3:向下转型时需要强制类型转换
4:克隆类需要设置标记接口
首先我们有一个Student对象并给他实例化
- package csda克隆代码示范;
- class Student{
- public int age;
-
- public Student(int age) {
- this.age = age;
- }
- }
- public class Test {
- public static void main(String[] args) {
- Student student1 = new Student(30);//待拷贝内容
-
- }
- }
因为Java中所有的类都会默认继承Object父类,所以我们最简单直接的想法是直接通过student1调用Object的clone方法并用student2接收
不幸的是,student1无法调用clone方法——————————。。。。。。。。。。。。
为什么呢?
我们查看来查看object的clone方法的原码(双击shift键搜索object然后回车,在左侧Structure中找打clone方法)
clone方法如下:
真相大白!!!!
Object中clone方法是用protected修饰的!!!所以无法通过不同包的非子类来调用;
同时我们发现clone方法确实会返回一个满足我们拷贝需求的对象,并且是Object类型的(后面要用)。
那怎么解决这个问题呢?
答案是在我们的Student类中重写一个clone方法并在这个方法中用super调用Object类的clone方法、
快捷方法:右键+generate+Override Methdos+clone
结果:
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
同时,student1中可以点出clone方法
但是,这是我们发现clone方法还是错的。。。。。。。
这里的错误是受查异常/编译时异常,解决方法:鼠标放在clone上,同时alt+回车
选择第一个选项。
令人悲伤的:
红线变长了。。。。。
又一个错误出现。
我们回忆一下,刚刚clone方法的原码。。。。。
Object的clone方法会返回一个Object类型的对象给student中重写的clone方法,然后我们用student2来给这个对象实例化。
总结一下:我们将父类的Object类交给了子类Student。这是一个什么过程?——向下转型
向下转型需要将我们的父类强制类型转换成子类类型:
Student studen2 = (Student)student1.clone();
然后运行。你以为这就结束了?
。。。。。。。。。。。。。。。。
别急,还有最后一个问题需要解决(真的是最后一个)
上面的报错是:不支持克隆
我们需要在Student类继承一个克隆接口
- class Student implements Cloneable{
- }
这个接口是一个空接口也叫标记接口,证明当前类是可以被克隆的。
-
- package csda克隆代码示范;
- class Student implements Cloneable{
- public int age;//需要克隆的成员变量
-
- //构造函数
- public Student(int age) {
- this.age = age;
- }
-
- @Override//重写的clone方法
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();//调用Object的clone方法
- }
-
- }
- public class Test {
- public static void main(String[] args) throws CloneNotSupportedException {
- Student student1 = new Student(30);
- Student student2 = (Student)student1.clone();
- System.out.println(student1.age);
- System.out.println(student2.age);
-
-
- }
- }
-
我们现在写一个Number类,给Student类中设置一个Number类型的成员变量,并在Student的构造方法中给其实例化。
接下来在Test类中先输出student1和student2的值,然后修改student2的m的num值,发现student1中的m的num值也随之改变
-
- package csda克隆代码示范;
- //
- class Number{
- int num;
- }
- class Student implements Cloneable{
- public int age;
- public Number m;//在原来的代码的基础上添加一个Number类型的成员变量,名称为m
-
- public Student(int age) {
- this.age = age;
- this.m = new Number();//实例化
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- }
- public class Test {
- public static void main(String[] args) throws CloneNotSupportedException {
- Student student1 = new Student(30);
- Student student2 = (Student)student1.clone();
- System.out.println(student1.m.num);
- System.out.println(student2.m.num);
- student1.m.num = 1;//更改student2的m的num的值
- System.out.println(student1.m.num);
- System.out.println(student2.m.num);
-
-
-
-
- }
- }
-
结果:
为什么我们更改了student2的m的num值,student1的m的num值也改变了?
浅拷贝图解:
当我们在student类中实例化一个m类后:
我们的super.clone克隆了student1中的内容,所以我们在student2中也实例化了一个Number类型的m对象,它们都引用了类Number,所以我们在通过student2更改m的值之后,student1的m的num值也会改变。
用上述代码我们在克隆一个对象(这个对象里还有一个对象)时,对象里的对象并不满足拷贝,这种情况我们就称作浅拷贝。
那怎么改成深拷贝呢?
1:在克隆对象里的对象对应的类重写克隆方法并添加标记接口(本文中时Number类)
- class Number implements Cloneable{
- int num;
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
2:设置一个过渡的类接收clone返回的克隆对象并返回tmp
- protected Object clone() throws CloneNotSupportedException {
- Student tmp = (Student)super.clone();
- tmp.m = (Number)this.m.clone();
- return tmp;
- }
-
- package csda克隆代码示范;
- class Number implements Cloneable{
- int num;
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
- class Student implements Cloneable{
- public int age;
- public Number m;
-
- public Student(int age) {
- this.age = age;
- this.m = new Number();
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- Student tmp = (Student)super.clone();
- tmp.m = (Number)this.m.clone();
- return tmp;
- }
-
- }
- public class Test {
- public static void main(String[] args) throws CloneNotSupportedException {
- Student student1 = new Student(30);
- Student student2 = (Student)student1.clone();
- System.out.println(student1.m.num);
- System.out.println(student2.m.num);
- student2.m.num = 1;
- System.out.println(student1.m.num);
- System.out.println(student2.m.num);
-
-
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。