【JavaSE】抽象类和接口


CSDN话题挑战赛第2期

一. 抽象类

1.1 抽象类概念

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
比如我们之前讲到的动物类,猫和狗:
在这里插入图片描述

Animal是一个动物类,不能具体化实现狗类中的bark方法,狗类和Animal又是继承关系,所以我们称Animal是一个抽象类。
我们发现, 父类 Animal 中的 bark 方法好像并没有什么实际工作, 主要的bark都是由 Animal的各种子类的 bark 方法来完成的. 像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstractmethod), 包含抽象方法的类我们称为 抽象类(abstract class).

1.2 抽象类语法

在Java中,一个类如果abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
在这里插入图片描述
abstract修饰的类是抽象类,abstract修饰的方法是抽象方法,注意抽象类不一定非要抽象方法组成。

1.3 抽象类特性

  1. 抽象类不能直接实例化对象
    在这里插入图片描述

  2. 抽象类里面的成员变量和成员方法都是和普通类一样的,只不过不能进行初始化了
    在这里插入图片描述

  3. 当一个普通的类继承了这个抽象类之后,那么这个普通类必须重写这个抽象类当中所有的抽象方法
    在这里插入图片描述

  4. 抽象类存在的最大意义就是被继承
    在这里插入图片描述

  5. 抽象类也可以发生向上转型,进一步发生多态
    在这里插入图片描述

  6. 当一个抽象类A继承了抽象类B,此时抽象类A可以不重写抽象类B当中的方法
    在这里插入图片描述

  7. 当一个普通的类C继承了第六条的A,此时就得重写所有的抽象方法
    在这里插入图片描述

  8. final不能修饰抽象方法和抽象类
    在这里插入图片描述
    final修饰的不可以重写,而abstract修饰的必须要重写

  9. 抽象方法不能是private修饰的,且子类的访问修饰符范围要大于父类的(构成重写的要求)
    在这里插入图片描述

  10. 抽象类当中不一定有抽象方法,但是如果这个方法是抽象方法,那么这个类一定是抽象类
    在这里插入图片描述

1.4 抽象类的作用

抽象类本身不能被实例化,要想使用,只能创建该抽象类的子类,然后让子类重写抽象类中的抽象方法,最大意义就是被继承!!

二. 接口

2.1 接口的概念

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用,接口见面如字,生活中有很多接口,比如:笔记本上的USB口,电源插座等。
在这里插入图片描述

在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
通俗易懂来讲接口就是一种行为的规范和标准

2.2 语法规则

使用关键字interface来修饰
在这里插入图片描述

2.3 接口特性

  1. 接口当中的成员方法,只能是抽象方法,所有的方法 默认都是public abstract
    在这里插入图片描述

  2. 接口当中的成员变量,默认是public static final(静态常量)
    在这里插入图片描述

  3. 接口当中的方法,如果要实现,需要用default来修饰
    在这里插入图片描述

  4. 接口当中的静态方法,可以有具体实现
    在这里插入图片描述

  5. 接口不能进行实例化
    在这里插入图片描述

  6. 一个普通的类可以通过implements来实现这个接口(注意要重写抽象方法,默认方法可以选择性重写,静态方法无法重写)
    在这里插入图片描述
    也可以发生向上转型和多态

  7. 接口中不能有静态代码块和构造方法
    在这里插入图片描述

  8. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
    在这里插入图片描述

2.4 实现多个接口

一个类,可以继承抽象类,同时实现多个接口,每个接口之间使用逗号分开(IDEA 中使用 ctrl + i 快速实现接口,Alt + 回车后点击implement methods 实现重写)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为什么接口的出现,解决了多继承的问题?

在Java里不支持多继承,只能继承一个类,但是一个类可以实现多个接口,我们想要实现各种各样的方法和形态,就只能调用接口,这样我们就可以写各种各样的接口来满足我们的需求。

注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类(用abstract修饰)。

2.5 接口间的继承

类和接口之间是implements接口和接口之间的关系是什么?extends(扩展)
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。
在这里插入图片描述
在这里插入图片描述

接口间的继承相当于把多个接口合并在一起

2.6 接口使用实例

对一组学生数组进行排序
在这里插入图片描述
在这里插入图片描述

但是打印结果却是错误的,按照逻辑思维,我们变量有三个,名字,年龄,学分,到底按什么来排名呢?
在这里插入图片描述

正确的比较:

  1. 比较年龄:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    所以生成的结果就是按照年龄大小返回相应的值(1或者-1,0)
  2. 比较名字的字符串长度:
    在这里插入图片描述
    打印的结果也会按照字符串长度来输出相应的值
    当然,我们也可以把返回值改成相应的形式
    在这里插入图片描述
    如果我们想从大到小打印可以互换this.XXX和o.XXX的位置。

但是我们现在也可以发现一个问题,我们想要比较的成员决定权在类里面,而不是我们自己也可以随意改动的,所以此处我们引出了比较器:(返回值是自己改写的
在这里插入图片描述

然后我们只需要在main函数里new出比较器,代入学生类即可
在这里插入图片描述

总结上面可以知道,排序打印有两种方式:

方法一:让类实现一个Comparable的接口然后重写里面的ComparaTo方法,注意返回值是要按照你的意愿去改动,是返回数值呢还是比较排序。

方法二:我们自己在类外写一个构造器,实现Comparator,然后重写相应的方法,也要注意返回值按需求改动,最后在主函数new出构造器,用Array.sort方法传入要比较的成员进行排序。

但是方法一比较愚钝,把我们要比较的元素定格成固定的了,我们就没有定义成员排序的主动权了,在方法二里面我们就可以随便调用哪个构造器来满足我们自己的需求了,所以方法二比较灵活,推荐使用方法二。

2.7Clonable 接口和深拷贝

当我们想要克隆一个对象的时候,和我们之前学的数组拷贝不一样,, 必须要先实现 Clonable 接口,否则就会抛出 CloneNotSupportedException 异常。
第一步让类实现Clonable:
在这里插入图片描述

第二步生成相应的克隆方法快捷键:
在这里插入图片描述

生成克隆方法:
在这里插入图片描述

我们在主函数里进行克隆:
在这里插入图片描述

点击异常处Alt+回车+回车:
在这里插入图片描述
这样我们就成功克隆了。

浅拷贝:拷贝后的副本要改成员变量的值的话会带动原来的拷贝对象的值的改变,两者的内容互相牵连,永远一样。
在这里插入图片描述
在这里插入图片描述

简易思维流程图:
在这里插入图片描述

深拷贝:拷贝后的副本要改成员变量的值的话不会影响原来的拷贝对象的值,这个对象的引用所指向的对象拷贝前后是两个单独的个体。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

简易思维流程图:
在这里插入图片描述

以上总结:

  1. 实现深拷贝是在代码层次上进行的,而不是说某个方法是深拷贝
  2. 想要达到深拷贝,那么每个对象中,如果有引用,这个对象的引用所指向的对象也要进行克隆

2.8 抽象类和接口的区别

抽象类和接口都是 Java 中多态的常见使用方式,都需要重点掌握,同时又要认清两者的区别
核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法.
在这里插入图片描述

三. Object类

Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object的引用进行接收,Object是所有类的父类
对于我们整个Object类中的方法需要实现全部掌握,目前我们主要来熟悉这几个方法:toString()方法,equals()方法,hashcode()方法。
在这里插入图片描述

3.1 获取对象信息

如果要打印对象中的内容,可以直接重写Object类中的toString()方法,之前已经讲过了,此处不再展示

3.2 对象比较equals方法

在Java中,==进行比较时:

  1. 如果==左右两侧是基本类型变量,比较的是变量中值是否相同
  2. 如果==左右两侧是引用类型变量,比较的是引用变量地址是否相同
  3. 如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:

鼠标右键单击形成快捷键(IDEA中):
在这里插入图片描述
出现此界面之后一直点Next就会生成equals方法和hashCode方法
在这里插入图片描述

3.3 hashcode方法

帮我们算一个具体的对象位置存在,这里面涉及数据结构,但博主还没更新数据结构,没法讲述,所以我们只能说它是个内存地址。然后调用Integer.toHexString()方法,将这个地址以16进制输出。(hashCode计算一个对象在内存中的位置
当我们生成了一个hashCode方法之后,同样内容的对象所打印的地址哈希值是一样的,如果不生成hashCode方法,打印的哈希值是不一样的。
在这里插入图片描述
在这里插入图片描述

3.4 接收引用数据类型

在之前已经分析了Object可以接收任意的对象,因为Object是所有类的父类,但是Obejct并不局限于此,它可以接收所有数据类型,包括:类、数组、接口。

  1. 使用Object来接收数组对象
    在这里插入图片描述

  2. 使用Object接收接口对象
    在这里插入图片描述
    Object真正达到了参数的统一,如果一个类希望接收所有的数据类型,就是用Object完成,在Java中,泛型就是底层就是通过Object来实现的。

抽象类和接口就完结了,是不是感觉又学到了很多呢?加油吧,少年!!!

  • 67
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 66
    评论
评论 66
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Redamancy丶早晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值