🎇个人主页:Ice_Sugar_7
🎇所属专栏:快来卷Java啦
🎇欢迎点赞收藏加关注哦!
抽象类&接口3
- 🍉Clonable 接口和深拷贝
 - 🍌浅拷贝和深拷贝
 
- 🍉Object类
 - 🍉抽象类和接口的区别
 - 🍉总结
 
🍉Clonable 接口和深拷贝
Object 类中存在一个 clone 方法,调用这个方法可以创建一个对象的拷贝
 要调用 clone 方法,需要先实现 Clonable 接口,否则就会抛出 CloneNotSupportedException 异常(不支持克隆异常)
🍌浅拷贝和深拷贝
Cloneable拷贝出的对象是一份浅拷贝,下面用一个例子来解释一下:
class Money implements Cloneable{
    public double m = 19.9;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public String name;
    public int age;
    public Money money = new Money();  //实例化一个Money对象
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
	@Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person("张三",20);
        Person person2 = (Person)person.clone();//clone
        System.out.println("person "+person.money.m);
        System.out.println("person2 "+person2.money.m);
        System.out.println("===========");
        person.money.m = 100;
        //观察将m修改为100之后两个对象的m是多少
        System.out.println("person "+person.money.m);
        System.out.println("person2 "+person2.money.m);
    }
}
 

 可以看到两个对象的m都变为100.0,说明person、person2的money都指向同一个m
 
由此我们可以总结浅拷贝的特征:
 浅拷贝会创建一个新对象,但是对于引用类型的字段,只复制了引用,而不是复制引用指向的对象
而深拷贝就会复制引用所指对象
 现在想实现深拷贝,我们就要给money也拷贝一份,需要把Person的clone方法改一下:
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person) super.clone();  //对原对象进行克隆
        tmp.money = (Money) this.money.clone();  //克隆对象中引用类型所指的对象
        return tmp;
    }
 

 
 
 深拷贝后,再修改person的m,就不会影响person2的了
 
🍉Object类
Object是Java默认提供的一个类,Java中所有类默认继承Object父类。即所有类的对象都可以使用Object的引用进行接收,举个例子:
    public static void func(Object obj) {
        System.out.println(obj);
    }
    public static void main(String[] args) {
        func(new Student("Sugar",90));
        func(new Money());
    }
 

 Object类中也有一些定义好的方法,本文讲解其中的 toString( ) 和 equals( )
 
- toString( )
如果要打印对象中的内容,就需要重写Object类中的toString()方法,不然会打印出它的地址(内存地址的字符串表示形式) 
// Object类中的toString()方法实现:
public String toString() {
	return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
 
- equals( )
我们常见的==就可以实现比较,它在比较时:
如果它左右操作数是基本类型变量,比较的是变量中值是否相同
如果左右两侧是引用类型变量,则比较引用变量地址是否相同 
要比较对象的内容是否相等,那就要用到equals方法,但是需要进行重写,因为它默认是按地址进行比较的
// Object类中的equals方法
public boolean equals(Object obj) {
	return (this == obj); // 使用引用中的地址直接来进行比较
}
 
	//Student类中重写equals,用idea的generate可以直接生成
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return grade == student.grade;
    }
    public static void main(String[] args) {
        Student student1 = new Student("砂糖橘",98);
        Student student2 = new Student("zs",98);
        boolean ret = student1.equals(student2);
        System.out.println(ret);  //运行结果为true
    }
 
🍉抽象类和接口的区别
抽象类和接口都是 Java 中多态的常见使用方式,都需要重点掌握,同时也需要了解二者之间的区别
 核心区别:
- 抽象类中可以包含
普通方法和字段,这样的普通方法和字段可以被子类直接使用(不必重写) - 而接口中不能包含普通方法,子类
必须重写所有的抽象方法 

🍉总结
- Cloneable接口的clone方法可以实现浅拷贝,如果要实现深拷贝,那么让需要对对象中的引用类型进行拷贝
 - Java中默认Object类是所有类的父类。Object中已经实现了一些方法,子类通过重写这些方法可以实现相应的功能
 - 注意区分抽象类和接口
 



















