🎇个人主页: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中已经实现了一些方法,子类通过重写这些方法可以实现相应的功能
- 注意区分抽象类和接口