本篇主要介绍Java中的抽象类与接口
其实不是很难,就是一些语法知识,大家需要多多动手理解。
👩🏻🏫作者: 初入编程的菜鸟哒哒
📚系列文章目录:一、TvT——JavaSE(1)–Java的数据类型与变量
二、TvT——JavaSE(2)–Java的运算符
三、TvT——JavaSE(3)–Java的逻辑控制
四、TvT——JavaSE(4)–Java方法的使用
五、你真的学会了JavaSE中数组的定义与使用吗?
六、Java中的类与对象来袭
七、类与对象有关static成员的知识你真的了解吗?
八、有关代码块的知识你真的了解吗?
九、初步学会JavaSE内部类知识
十、java继承真的一点也不难
十一、Java多态你学会了吗?
文章目录
🥡一、抽象类
🍣1.1 什么是抽象类
我们发现在多态的情况中,父类的方法经常是不会被使用到的。
动态绑定会自动绑定到子类的方法中。
class Shape {
public void draw() {
System.out.println("画图形!");
}
}
class Pig extends Shape {
@Override
public void draw() {
System.out.println("🐖");
}
}
class Dog extends Shape {
@Override
public void draw() {
System.out.println("🐕");
}
}
public class Test1 {
public static void drawShape(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Pig pig = new Pig();
Dog dog = new Dog();
drawShape(pig);
drawShape(dog);
}
}
那我们可不可以直接在父类的方法中直接什么都不写呢?
我们发现这样写可以。
那可不可以大括号也不写呢?
结果是报错了。
🍣1.2 抽象类语法
这时只要使用abstract
关键字:
这就是抽象方法。
❗ 注意:
抽象方法
必须要在抽象类
里,所以我们在类前也加上了abstract
关键字。
此时Shape
变成了抽象类。
简单来说:
父类
Shape
中的draw
方法好像并没有什么实际工作, 主要的绘制图形都是由Shape
的各种子类的draw
方法来完成的。 像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstract method
)
包含抽象方法的类我们称为 抽象类(abstract class
)
🍣1.3 抽象类注意事项
⭕抽象类须知:
- 使用
abstract
修饰的方法,叫做抽象方法- 包含抽象方法的类,必须设计为抽象类,使用
abstract
修饰这个类。- 抽象类是不能进行实例化的
- 抽象方法不可以是
private
,static
,final
的,因为这类方法就不可以重写了。
- 抽象类当中可以有和普通类一样的方法,成员,最突出的和普通类不一样的地方是不可以被实例化。
- 抽象类虽然不能进行实例化,但是可以被继承。(也就是说抽象类就是为了被继承)
- 当一个类继承一个抽象类,那这个类必须重写这个抽象类当中所有的抽象方法。否则代码不能通过编译。
除非这个子类也是一个抽象类,但是这个子类被下一个类所继承的时候,下一个类还是需要重写第一个父类(抽象类)里面所有的抽象方法。- 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
- 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
🍣1.4 抽象类的作用
🍡抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类,然后让子类重写抽象类中的抽象方法。
使用抽象类相当于多了一重编译器的校验。 使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成,而应由子类完成。
那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的。 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题。
🥡二、接口
接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。
在Java中,接口可以看成是:
多个类的公共规范,是一种引用数据类型。 |
🍣2.1 语法规则
接口的定义格式与定义类的格式基本相同,将class
关键字换成 interface
关键字,就定义了一个接口。
🍣2.2 如何使用接口
接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法。
使用implements
关键字来实现方法。
❗ 注意:
子类和父类之间是extends
继承关系,类与接口之间是 implements
实现关系。
那我们用接口来实现一下画画:
interface Ishape {
public abstract void draw();
}
class Dog implements Ishape{
@Override
public void draw() {
System.out.println("一只修狗:🐕");
}
}
class Pig implements Ishape{
@Override
public void draw() {
System.out.println("一只修猪:🐖");
}
}
class Cat implements Ishape{
@Override
public void draw() {
System.out.println("一只修喵:🐱");
}
}
public class Test {
public static void draw(Ishape ishape) {
ishape.draw();
}
public static void main(String[] args) {
draw(new Dog());
draw(new Pig());
draw(new Cat());
}
}
🍣2.3 接口特性
接口中的成员对象默认都是public static final
修饰的,必须要初始化,因为final
是常量类型。
- 使用
interface
来修饰接口
接口当中的成员变量,默认是public static final
修饰的,必须要初始化,因为final
是常量类型。
如果public static final
没有写全,编译器会自动给补上。
- 接口当中的成员方法,默认都是抽象方法,
public abstract
修饰的。
如果public abstract
没有写全,编译器也会自动给补上。
- 接口中的实例成员方法,不能有具体的实现。
接口当中的普通成员方法,如果要有具体的实现,必须加上default
修饰(默认是public
修饰)(从JDK8开始才有),此时这个方法称作这个接口的默认方法。
- 接口当中可以有静态成员方法,但是不管是静态的成员方法还是
default
方法,都是用public
修饰的。
- 接口本身也是不可以进行实例化的
- 类和接口的关系是使用
implements
。- 一个接口可以引用其他类型,相当于向上转型。
- 重写接口中方法时,不能使用
default
访问权限修饰
- 接口中不能有静态、实例代码块和构造方法
- 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是
.class
- 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
- jdk8中:接口中还可以包含
default
方法。
🍣2.4 实现多个接口
💗在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。
下面通过类来表示一组植物:
另外我们再提供一组接口, 分别表示 “辣的”, “苦的”, “艳丽的”,“孤傲的”,“藤蔓上的”。
接下来我们创建几个具体的植物:
🌶辣椒是辣的,并且长在藤上
class Pepper extends Botany implements Spicy,Onvine{
public Pepper(String name) {
super(name);
}
@Override
public void photosynthesis() {
System.out.println(name+"可以光合作用");
}
@Override
public void Spicy() {
System.out.println(name+"是辣的");
}
@Override
public void Onvine() {
System.out.println(name+"在藤上生长");
}
}
}
苦瓜是苦的,并且长在藤上
class Balsampear extends Botany implements Bitter,Onvine{
public Balsampear(String name) {
super(name);
}
@Override
public void photosynthesis() {
System.out.println(name+"可以光合作用");
}
@Override
public void Bitter() {
System.out.println(name+"是苦的");
}
@Override
public void Onvine() {
System.out.println(name+"在藤上生长");
}
}
牡丹是艳丽的
class peony extends Botany implements Gorgeous{
public peony(String name) {
super(name);
}
@Override
public void photosynthesis() {
System.out.println(name+"可以光合作用");
}
@Override
public void Gorgeous() {
System.out.println(name+"是艳丽的");
}
}
梅花是孤傲的
class Plumblossom extends Botany implements Aloof{
public Plumblossom(String name) {
super(name);
}
@Override
public void photosynthesis() {
System.out.println(name+"可以光合作用");
}
@Override
public void Aloof() {
System.out.println(name+"是孤傲的");
}
}
💦 注意:
一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
上面的代码展示了 Java
面向对象编程中最常见的用法:
一个类继承一个父类, 同时实现多种接口。 |
继承表达的含义是 is - a
语义, 而接口表达的含义是 具有 xxx 特性
。
牡丹是一种植物,具有颜色艳丽的特性.
辣椒是一种动物,具有辣的味道,并且长在藤蔓上
苦瓜是一种动物,具有苦的味道,并且长在藤蔓上
这样设计有什么好处呢?
有了接口之后, 类的使用者就不必关注具体类型,而只关注某个类是否具备某种能力。
🍣2.5 接口间的继承
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。
即:用接口可以达到多继承的目的。
接口可以继承一个接口, 达到复用的效果。
使用 extends
关键字
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
...
}
通过接口继承创建一个新的接口 IAmphibious
表示 “两栖的”。
此时实现接口创建的 Frog
类, 就继续要实现 run
方法, 也需要实现 swim
方法。
接口间的继承相当于把多个接口合并在一起。
🥡三 、抽象类和接口的区别
(重要!!! 常见面试题)
象类和接口都是 Java 中多态的常见使用方式。
都需要重点掌握, 同时又要认清两者的区别。
我们可以从成员对象和成员方法两部分来分析:
抽象类与接口的区别:
成员对象: 抽象类可以有普通的成员对象,比如
public,protected
等都可以有,但是接口只允许有public static final
修饰的全局常量。成员方法:抽象类可以有除
private
、static
、final
修饰以外的普通成员方法,也可以有构造方法,但是接口只允许有public abstract
修饰的成员方法。抽象类允许有静态代码块和实例代码块,接口不允许。
抽象类只能被单继承,但是接口允许一个子类实现多个接口。