提示:书接上回,我们已经提到过了抽象类,抽象类存在的意义就是被继承,一个普通类如果继承抽象类,那么就必须重写抽象类中的抽象方法,我们也提到过可以解决不重写的方法,但是随着我们学习的深入,就必须要有一个规范来真正解决这一问题。那么这篇关于接口的文章就可以解决心中的疑惑。
接口
接口的概念
我们在现实生活中碰到到的接口有哪些,电脑的USB接口,手机的Type-c🔋充电接口,在Java中接口的定义是⬇️:
接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
通俗点来说,接口是一种规范,如果你想用这个接口,你必须实现我的规范。在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型。
简单介绍接口
提示:一个Java文件要么是一个类或者是一个接口
我们在建立一个接口时,同样是右击src文件,选中interface,生成一个接口。

注意:
- 接口的定义和类的定义是差不多的,只需要将class换成interface
- 创建接口时,接口的命名都是以大写的字母I开头,这样就是定义了一个接口
- 接口的命名一般是以形容词的单词,比如Shape形状,Aniaml动物,这样一个具有统称,包含多种实例的名称
接口的特点
接口也是有属性和方法的,接口的声明中方法默认是抽象方法(方法没有方法体)
接口有以下特点需要记住
- 接口是表示一个类需要做哪些事情(想要实现这个接口,就必须重写它的方法)
- 我们将跑步设计成接口,狮子和狗都会跑步,你要想实现跑步这个接口接口,就必须按照我的规范来完成,才有资格去实现接口。
- 如果一个类实现了接口中的所有方法,没有方法体,那么这个类一定是抽象类,所以抽象方法只能存在于抽象类和接口中。
接口的语法规则
提示:接口不能直接使用,必须要有一个"实现类"来"实现"接口,实现接口中的抽象方法
子类和父类继承关系用extends,接口使用implements
interface ISahpe{
//实现一个接口,关键字 interface
abstract void func();
}
class Rect implements ISahpe{
//子类和父类继承关系是用extends,接口则使用implements实现关系
@Override
public void func() {
System.out.println("想要实现这个接口,就必须重写接口中的抽象方法");
}
}
public class Main {
public static void main(String[] args) {
}
}
关于接口的特性有多个,我们一一来解释
1.接口是一种引用类型,不能直接new对象

因为能包含抽象方法的只有抽象类能做到,而接口中是可以有抽象方法的,从某种意义上来说,接口也是一种抽象类,所以无法实现实例化。
2.接口只中的成员默认是使用,public static final修饰的,不写也不会报错。

3.接口中的方法默认是public abstract修饰的,不写也不会报错,如果使用其他修饰符都会报错。

4.接口中的方法不能在接口类中实现,只能由实现接口的类实现,通过关键字implements

接口中的方法是抽象方法,是不能直接实现的,所以必须要有一个类来实现接口中的方法。⬇️(下面代码是正确实现接口中的抽象方法)
interface IShape{
public abstract void draw();
}
class Retc implements IShape{
@Override
public void draw() {
System.out.println("画一个矩形");
}
}
class Flower implements IShape{
@Override
public void draw() {
System.out.println("画一朵花🌹");
}
}
public class Test {
public static void main(String[] args) {
IShape iShape=new Retc();
IShape iShape1=new Flower();
iShape.draw();
iShape1.draw();
}
}
5.从JDK8开始,可以开始写一个default修饰的方法,重写接口中的方法时,不能使用默认的访问权限
使用default去修饰方法的时候,这个方法可以有具体的实现,但是在重写的阶段如果还用default修饰的话,就会报错。这里和我们重写的概念是吻合的(重写的时候 子类的访问权限一定要大雨等于父类的访问权限,所以前面的public不能省略掉。)

6.接口中不能有静态代码块和构造方法
7.接口虽然不是类,但是接口编译完成之后字节码文件的后缀是.class

8.如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类。抽象方法只出现在抽象类以及接口当中,所以我的类要么是抽象类或者是接口,必须要满足接口中的要求。
结合接口特性实现一个小练习
介绍了接口的相关特性,我们用一个小练习来巩固一下知识点。在实现之前我们理清一下思路,我的电脑本身就是有USB接口的,是不需要再去实现的(假设电脑没有蓝牙这个功能,必须要通过USB接口)。接口中有打开和关闭的功能,既然有这个功能键盘和鼠标就需要根据接口的规范来设计。
实现一个笔记本使用USB接口的键盘以及一个USB接口的鼠标
USB接口:拥有的功能,打开,关闭。
鼠标类:实现USB接口并拥有点击的功能。
键盘类:实现USB接口并拥有输入的功能。
笔记本类:拥有开机和关机的功能并使用USB。
USB 接口
public interface IUSB {
//实现一个IUSB接口,有打开和关闭设备的功能
void openDevice();//打开
void closeDevice();//关闭
//注意这里的方法默认是public abstract的,想要实现接口必须实现这些抽象方法
}
鼠标类🖱️
public class Mouse implements IUSB{
//建立一个鼠标类,通过关键implements来实现IUSB接口
//并重写接口中的所有抽象方法
@Override
public void openDevice() {
System.out.println("打开鼠标🖱️");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标🖱️");
}
public void click(){
System.out.println("点击鼠标🖱️");
}
}
键盘类⌨️
public class Keyboard implements IUSB{
//建立一个键盘类,通过关键implements来实现IUSB接口
//并重写接口中的所有抽象方法
@Override
public void openDevice() {
System.out.println("打开键盘⌨️");
}
@Override
public void closeDevice() {
System.out.println("关闭键盘⌨️");
}
public void inPut(){
System.out.println("敲击键盘⌨️");
}
}
电脑类💻
public class Computer {
public void powerOn(){
System.out.println("开机💻");
}
public void powerOff(){
System.out.println("关机💻");
}
public void useDevice(IUSB iusb){//此处代表要开始使用USB的功能了
iusb.openDevice();//接口中的打开功能
if(iusb instanceof Mouse){//如果接的是鼠标,那么就调用鼠标的方法
Mouse mouse =(Mouse)iusb;//这里是强制转换
mouse.click();
} else if (iusb instanceof Keyboard) {//如果接的是键盘,那么就调用键盘的方法
Keyboard keyboard=(Keyboard)iusb ;//这里是强制转换
keyboard.inPut();
}
iusb.closeDevice();//接口中的关闭功能
}
}
测试类
public class Main {
public static void main(String[] args) {
Computer computer=new Computer();
computer.powerOn();//开机
//使用鼠标设备
computer.useDevice(new Mouse());
//使用键盘设备
computer.useDevice(new Keyboard());
computer.powerOff();//关机
}
}
运行结果:

代码中提到了instanceof方法,此处可能不太熟悉,在这里推荐一个博客链接,大家可以去看看。instanceof的使用方法
实现多个接口
在Java中。类和类都是单继承,一个类只能有一个父类,我们在继承中也提到了,Java是不支持多继承的,但是一个类可以实现多个接口。我们还是用代码的方式给大家展现。
我们先建立一个动物Animal类,实现跑,游泳,飞三个接口,再创建三个类狮子,于,猫头鹰继承于Animal,并实现三个接口。
public abstract class Animal {
String name;
public Animal(String name) {//抽象类是可以有构造方法的
this.name = name;
}
}
//接口部分
interface IRunning {//接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
void run();//接口当中的方法不写也是默认为 public abstract的
}
interface ISwimming{//接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
void swim();//接口当中的方法不写也是默认为 public abstract的
}
interface IFly{//接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
void fly();//接口当中的方法不写也是默认为 public abstract的
}
//子类部分
class Lion extends Animal implements IRunning{
public Lion(String name) {//因为我的父类中有构造方法,说明一定有属性
super(name);//这里便是通过super帮助父类实现初始化
//名字我们实例化的时候再给
}
@Override
public void run() {
System.out.println(name+"🦁️正在用四条腿跑步");
}
}
class Fish extends Animal implements ISwimming{
public Fish(String name) {//这里便是通过super帮助父类实现初始化
super(name);
}
@Override
public void swim() {
System.out.println(name+"🐟正在用游泳");
}
}
class Bird extends Animal implements IFly{
public Bird(String name) {//这里便是通过super帮助父类实现初始化
super(name);
}
@Override
public void fly() {
System.out.println(name+"🦉正在用翅膀飞");
}
}
会不会有一种生物,可以飞,可以游泳,可以跑步,没错我们的大鹅🦢,它可以一次性实现三个接口的功能,也就是实现多个接口
class Goose extends Animal implements IRunning,IFly,ISwimming{
//建立了一个大鹅类,继承于Animal类,继承三个接口,并重写了三个接口中的抽象方法
public Goose(String name) {
super(name);
}
@Override
public void run() {
System.out.println(name+"🦢正在用鹅掌跑步");
}
@Override
public void swim() {
System.out.println(name+"🦢正在用鹅腿游泳");
}
@Override
public void fly() {
System.out.println(name+"🦢正在用翅膀飞");
}
}
通过测试类来实现
public class Test{
public static void walk(IRunning iRunning){
iRunning.run();
}
public static void swim(ISwimming iSwimming){
iSwimming.swim();
}
public static void fly(IFly iFly){
iFly.fly();
}
public static void main(String[] args) {
swim(new Goose("嘎嘎"));
fly(new Goose("嘎嘎"));
walk(new Goose("嘎嘎"));
System.out.println("============");
walk(new Lion("辛巴"));
swim(new Fish("杰克"));
}
}

上面的代码展示Java面向对象编程最常见的用法:一个类继承一个父类,同时实现了多个接口
继承所表达的意思是is-a的含义,而接口表达意思则是具有xx的特性,这样设计的好处就是让我们忘记类型。有了接口以后,类的使用者这就不必关心具体的类型,而是关注某个类是否具备某种能力。
甚至我可以实现一个机器人来实现跑步的接口。
class Robot implements IRunning{
@Override
//只要实现了IRunning这个接口,都可以实现跑步这个动作
public void run() {
System.out.println("机器人正在用机器腿🦿跑步");
}
}

虽然机器人不是Animal的子类,此处是撇开了类型,实现了这个接口,所以我可以调用run方法。
接口的继承
在Java中,类和类之间是单继承的,一个类可以实现多个接口,而接口和接口之间是可以多继承。也就是接口可以达到多继承的效果。⬇️
interface IDouble extends IRunning,ISwimming{
//实现一个IDouble接口,可以理解为两栖,既能跑也可以游泳。接口可以继承一个接口,达到复用的效果,使用extends的关键字
@Override
default void run() {
}
@Override
default void swim() {
}
}
class Frog extends Animal implements IDouble{
public Frog(String name) {
super(name);
}
@Override
public void run() {
System.out.println(name+"用四条腿跑步");
}
@Override
public void swim() {
System.out.println(name+"用两只腿游泳");
}
}
public class Test{
public static void main(String[] args) {
Frog frog=new Frog("青蛙王子");
frog.run();
frog.swim();
}
接口的继承相当于把接口合在一起,将多个功能揉杂在一起实现。
我们在实现接口的多继承时,用到了关键字extends,除了在拥有继承的意思之外,其实还有一层扩展延伸的意思。

类可以继承(extends)一个普通类
类可以继承(extends)一个抽象类
类可以继承(extends)一个普通类和抽象类的同时实现多个接口
接口可以通过extends 拓展多个接口的功能
为什么要用到接口?
- 接口是一种功能,既然抽象类是没有方法体,不能实现的,那我们就需要一个规范的接口,按照接口的标准来实现我们的效果。
- 接口也是Java独有的特点,和之前说到的多态有异曲同工之妙。
- 使用接口从代码的角度来说,帮我们省略了代码,融入了设计的思想从而使代码变得更加高大上
本文详细介绍了Java中的接口,包括接口的概念、特点、语法规则以及接口的实现和继承。通过实例展示了如何创建接口,实现多个接口,以及接口在实际编程中的应用。接口作为Java中的一个重要特性,提供了规范化的标准,使得代码更加灵活和易于维护。


被折叠的 条评论
为什么被折叠?



