关于Java中Cloneable的一些个人理解

Cloneable:
  • 官方注释:
一个类实现了Cloneable接口,以向Object.clone()方法指示该方法制作该类实例的字段对字段副本是合法的。
在未实现Cloneable接口的实例上调用 Object 的 clone 方法会导致抛出异常CloneNotSupportedException 。
按照惯例,实现此接口的类应该使用公共方法覆盖Object.clone (受保护)。 有关覆盖此方法的详细信息,请参阅Object.clone() 。
注意,此接口不包含clone方法。 因此,不能仅仅凭借对象实现了这个接口就克隆一个对象。 即使以反射方式调用 clone 方法,也不能保证它会成功。
  • 例子(代码省略get set方法):

  • public class School {
        private String name;
    }
    
    public class Student implements Cloneable {
        private String name;
        private int age;
        private String gender;
        private School school;
    
        @Override
        public Student clone() throws CloneNotSupportedException {
            return (Student) super.clone();
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Student zhangshan = new Student("张三",23,"female",new School("第一中学"));
            Student clone = zhangshan.clone();
            System.out.println(clone == zhangshan);
            System.out.println(clone.school == zhangshan.school);
        }
    
    ===============输出================
    false
    true
    
  • 使用注意事项:

    1. 如果一个类需要被Clone,那么这个类需要实现Cloneable接口,并且实现Clone()方法,注意方法的访问修饰符和返回类型。
    2. 类Object本身不实现接口Cloneable ,因此在类为Object的对象上调用clone方法将导致在运行时抛出异常
    3. Object的clone()方法实现由本地方法实现
    4. clone()方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存
  • 实现深拷贝:

    public class School implements Cloneable {
        private String name;
    
        @Override
        public School clone() throws CloneNotSupportedException {
            return (School) super.clone();
        }
    }
    
    public class Student implements Cloneable {
        private String name;
        private int age;
        private String gender;
        private School school;
    
        @Override
        public Student clone() throws CloneNotSupportedException {
            Student clone = (Student) super.clone();
            clone.school = this.school.clone();
            return clone;
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Student zhangshan = new Student("张三",23,"female",new School("第一中学"));
            Student clone = zhangshan.clone();
            System.out.println(clone == zhangshan);
            System.out.println(clone.school == zhangshan.school);
        }
    }
    ===============输出================
    false
    false
    
  • 关于字符串String的一些理解

    我们知道String是引用类型,当被clone对象中的String字段,clone出来的对象的String字段和被clone的对象具有相同的引用,他们有可能都指向string intern pool中的某个字符串常量,也有可能都指向堆中的某个字符串

    public class Student implements Cloneable {
        private String name;
        private int age;
        private String gender;
        private School school;
    
        @Override
        public Student clone() throws CloneNotSupportedException {
            Student clone = (Student) super.clone();
            clone.school = this.school.clone();
            return clone;
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Student zhangshan = new Student("张三",23,"female",new School("第一中学"));
            Student clone = zhangshan.clone();
            System.out.println(clone.getName() == zhangshan.getName());
            System.out.println(clone.getName() == zhangshan.getName().intern());
        }
    }
    ===============输出================
    true
    true
    

    仅修改main()第一行代码:

    Student zhangshan = new Student(new String("张三"),23,"female",new School("第一中学"));
    ===============输出================
    true
    false
    

    intern()方法是从string intern pool中取出此字符串常量,如果pool中不存在此字符串,先将当前字符串存储在pool中再返回对象的引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值