让我们深度理解Java中的抽象类与接口

🎐

本篇主要介绍Java中的抽象类与接口

其实不是很难,就是一些语法知识,大家需要多多动手理解。


👩🏻‍🏫作者: 初入编程的菜鸟哒哒
📚系列文章目录:

一、TvT——JavaSE(1)–Java的数据类型与变量
二、TvT——JavaSE(2)–Java的运算符
三、TvT——JavaSE(3)–Java的逻辑控制
四、TvT——JavaSE(4)–Java方法的使用
五、你真的学会了JavaSE中数组的定义与使用吗?
六、Java中的类与对象来袭
七、类与对象有关static成员的知识你真的了解吗?
八、有关代码块的知识你真的了解吗?
九、初步学会JavaSE内部类知识
十、java继承真的一点也不难
十一、Java多态你学会了吗?


📜刷题笔记:
📖TvT——C语言进阶の刷题【1】:指针进阶
📖面试高频题の环形链表 环形链表Ⅱ 全解析



🥡一、抽象类

在这里插入图片描述

🍣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修饰这个类。
  • 抽象类是不能进行实例化的
    在这里插入图片描述
  • 抽象方法不可以是privatestaticfinal的,因为这类方法就不可以重写了。
    在这里插入图片描述
  • 抽象类当中可以有和普通类一样的方法,成员,最突出的和普通类不一样的地方是不可以被实例化
    在这里插入图片描述
  • 抽象类虽然不能进行实例化,但是可以被继承。(也就是说抽象类就是为了被继承)
  • 当一个类继承一个抽象类,那这个类必须重写这个抽象类当中所有的抽象方法。否则代码不能通过编译。
    除非这个子类也是一个抽象类,但是这个子类被下一个类所继承的时候,下一个类还是需要重写第一个父类(抽象类)里面所有的抽象方法。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
  • 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

在这里插入图片描述

🍣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修饰的全局常量。

  • 成员方法:抽象类可以有除privatestaticfinal修饰以外的普通成员方法,也可以有构造方法,但是接口只允许有 public abstract修饰的成员方法。

  • 抽象类允许有静态代码块和实例代码块,接口不允许。

  • 抽象类只能被单继承,但是接口允许一个子类实现多个接口。

总结

在这里插入图片描述

你可以叫我哒哒呀
非常欢迎以及感谢友友们的指出问题和支持!
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值