Java-Object类中的clone和(finalize)方法

1.clone

1.1概念:

protected Object clone() throws CloneNotSupportedException创建并返回此对象的副本。

  • API文档内容:

“复制”的精确含义可能取决于对象的类。一般的意图是,对于任何对象x ,
表达式:
如果此对象的类不实现接口Cloneable,则抛出CloneNotSupportedException 。
Cloneable接口中没有任何的成员变量和成员方法,像这样的接口称之为标记接口。
将其所有字段初始化为完全符合该对象的相应字段的内容,就像通过赋值一样。
这些字段的内容本身不被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深度拷贝”操作。

注意点:

  • 必须要有类(Student1)去实现 cloneable 的接口
  • 然后再类(Student1)抛出异常:
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
  • 其次,在main 方法里也要抛出异常
    public static void main(String[] args) throws CloneNotSupportedException{

-## 克隆出来的对象以多态的形式接收

        Object obj = s.clone();
              在这里是以多态的形式接收的
        System.out.println(obj);
  • 然后向下转型:
        //向下转型
        Student1 clonestudent = (Student1)obj;

深拷贝,浅拷贝(面试必问)

    /** java中有两种不同的拷贝形式。深拷贝和浅拷贝(面试必问)
     *第一步:什么是和浅拷贝深拷贝??
     * 浅拷贝:指拷贝完成后,会产生一个和原来地址值不一样的对象,但是对象中存在引用数据类型的
     *        成员变量,该成员变量拷贝完成后指向的依旧是同一个对象。其他基本数据类型的变量是一样的
     * 深拷贝:指的是在拷贝完后,本身会产生一个与原来地址值不一样的对象并且如果对象中存在引用
     *         数据类型的成员变量拷贝后与拷贝前的成员变量地址值也是不一样的。
    */

图解:image

如何验证深拷贝开始浅拷贝

  • 1.创建一个拷贝前对象 -对象必须有一个引用变量Demo
  • 2.调用clone 方法拷贝
  • 3.用父类Object接收后再向下转型
  • 4.比较拷贝前后的地址值
  • 5.比较拷贝前与拷贝后的成员变量demo对象的地址值

代码:1-main方法,2-Student1对象,3-Demo对象(比较深浅)

1

package com.bigdat.java.day16;
import com.bigdat.java.day16.ObjectDemo1;
public class ObjectDemo2{
    public static void main(String[] args) throws CloneNotSupportedException{
        Student1 s = new Student1();
        s.setName("阿涛");
        s.setAge(24);
        System.out.println(s);
        //直接打印了一个对地址值,说明默认使用了toString()方法
        //如果打印的是一对象的信息,说明该类重写了toString方法
        System.out.println("======================================");
        //java: clone() 在 java.lang.Object 中是 protected 访问控制
        //java: 未报告的异常错误java.lang.CloneNotSupportedException; 必须对其进行捕获或声明以便抛出
        //java.lang.CloneNotSupportedException: com.shujia.wyh.day15.Student2
        //在学生类中实现 Cloneable 的接口,然后再方法体中重写Clone方法

        Object obj = s.clone(); //在这里是以多态的形式接收的
        System.out.println(obj);
        //向下转型
        Student1 clonestudent = (Student1)obj;
        System.out.println(clonestudent.getName()+"-------"+clonestudent.getAge());
        System.out.println(s.getName()+"--------"+s.getAge());
        /** java中有两种不同的拷贝形式。深拷贝和浅拷贝(面试必问)
         *第一步:什么是和浅拷贝深拷贝??
         * 浅拷贝:指拷贝完成后,会产生一个和原来地址值不一样的对象,但是对象中存在引用数据类型的
         *        成员变量,该成员变量拷贝完成后指向的依旧是同一个对象。其他基本数据类型的变量是一样的
         * 深拷贝:指的是在拷贝完后,本身会产生一个与原来地址值不一样的对象并且如果对象中存在引用
         *         数据类型的成员变量拷贝后与拷贝前的成员变量地址值也是不一样的。
        */
        System.out.println("=============验证Object类中的 Clone方法是深拷贝还是浅拷贝==============");
        //创建一个拷贝前的对象
        Demo demo = new Demo();
        Student1 copyQian = new Student1("阿涛",20,demo);
        //调用拷贝方法
        Object obj2 =copyQian.clone();
        //向下转型
        Student1 copyHou = (Student1) obj2;
        //比较拷贝前后的地址值
        System.out.println(copyQian.hashCode() == copyHou.hashCode());
        //比较拷贝前后的成员变量demo对象的地址值

        //在 Student 中重写了equals 方法。才能知道真假;
        Demo copyQianDemo = copyQian.getDemo();
        Demo copyHouDemo = copyHou.getDemo();
        System.out.println(copyQian.hashCode() == copyHou.hashCode());
    }
}

2

package com.bigdat.java.day16;

import java.util.Objects;

public class Student1 implements Cloneable{
    private String name;
    private int age;
    private Demo demo;

    public Student1() {
    }

    public Student1(String name, int age,Demo demo) {
        this.name = name;
        this.age = age;
        this.demo = demo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Demo getDemo() {
        return demo;
    }

    public void setDemo(Demo demo) {
        this.demo = demo;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Student1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", demo=" + demo +
                '}';
    }

//    @Override
//    public boolean equals(Object o) {
//        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
//        Student1 student1 = (Student1) o;
//        return age == student1.age && Objects.equals(name, student1.name) && Objects.equals(demo, student1.demo);
//    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, demo);
    }
}

3

package com.bigdat.java.day16;

import java.util.Objects;

public class Demo {
    private String name;
    private int age;

    public Demo() {
    }

    public Demo(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Demo{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

//    @Override
//    public boolean equals(Object o) {
//        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
//        Demo demo = (Demo) o;
//        return age == demo.age && Objects.equals(name, demo.name);
//    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

finlize方法:

protected void finalize()
    protected void finalize() throws Throwable
    当垃圾收集确定不再有对该对象的引用时,垃圾收集器在对象上调用该对象。
    一个子类覆盖了处理系统资源或执行其他清理的finalize方法。
    简单来说,这个方法就是用来做垃圾回收的,但是,什么时候回收我们并不清楚![](https://img2022.cnblogs.com/blog/2738901/202203/2738901-20220326125622341-1043005187.png)

posted @ 2022-03-26 12:58  a-tao必须奥利给  阅读(106)  评论(0)    收藏  举报