Java基础之——接口的基本使用
概述
本质:一个比抽象类更加抽象的类(而抽象类更接近一个类,只是比普通类多了抽象方法的定义)
说明:
- 接口就是一种公共的规范标准,只要符合规范标准,大家都可以用
- 接口是一种引用数据类型,最重要的内容:抽象方法
- Java中的接口更多的体现在对行为的抽象
如果一个抽象类没有字段,并且所有方法全部都是抽象方法,就可以把该抽象类改写为接口:interface
abstract class Person {
public abstract void run();
public abstract String getName();
}
interface Person {
void run();
String getName();
}
因为接口定义的所有方法默认都是public abstract的,所以这两个修饰符可以省略
接口的实现
当一个具体的类想实现一个接口时,需要使用implement关键字
实现该接口,则接受该接口的约束
class PersonImpl implements Person {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(this.name + " run");
}
@Override
public String getName() {
return this.name;
}
}
说明:
- 实现接口的类必须实现该接口中的所有抽象方法
- 如果实现类没有覆盖重写所有抽象方法,实现类就必须是一个抽象类
- 在实现一个接口的时候,实现接口的方法必须声明成 public
接口的多态
接口不能实例化,如果想要使用接口,必须使用接口的多态形式——用实现类对象来实例化
多态的形式:
- 具体类多态
- 抽象类多态
- 接口多态
多态的前提:
- 有继承或实现
- 方法重写
- 父(类/接口)引用指向(子/实现)类对象
接口名 变量名 = new 接口实现类();
例如:interface a = new interfaceImpl();
编译看左边,实现看右边:实现的内容看右边的实现类,编译的内容看左边的接口。
实现多个接口
public class My implements MyfaceA.MyfaceB {
//覆盖重写所有抽象方法
}
说明:
-
如果实现类所实现的多个接口中,存在重复的抽象方法,只需要覆盖重写一次
-
如果实现类所实现的多个接口中,存在重复的默认方法,实现类一定要对冲突的默认方法覆盖重写【并带上default关键字】
-
多个父接口当中的抽象方法如果重复,没关系
接口的规则
-
一个类可以实现多个接口
-
接口与接口之间是多继承的
-
接口中,所有方法都没有方法体
-
接口中,方法必须被定义为public或abstract形式
-
接口中,没有静态代码块或构造方法
-
接口中,定义的任意字段自动为static和final
-
抽象类只能对其子类的行为进行约束,但接口可以对实现本接口的所有类进行约束
-
抽象类实现接口的时候,可以不重写方法
-
接口不能被实例化,只能被继承或实现
-
一个类如果使用直接父类当中的方法,和接口中的默认方法产生了冲突,优先用父类的方法
接口的继承
一个接口可以继承自另一个接口
interface Hello {
void hello();
}
interface Person extends Hello {
void run();
String getName();
}
public interface 接口名称 [extends 父接口列表] {
//常量定义
//抽象方法的定义
void draw();
}
说明:
- 原来的接口称为基本接口或父接口
- 派生的接口称为派生接口或子接口
- 派生接口不仅可以继承父接口的成员,还可以加入新的成员
接口与抽象类的区别
成员区别
抽象类 | 接口 |
---|---|
变量,常量,构造方法,抽象方法,非抽象方法 | 常量,抽象方法 |
关系区别
类与类 | 类与接口 | 接口与接口 |
---|---|---|
继承,单继承 | 实现:单实现/多实现 | 继承:单继承/多继承 |
设计理念区别
抽象类 | 接口 |
---|---|
对类抽象,包括属性、行为 | 对行为抽象,主要是行为 |
接口可以同时通过extends继承多个接口,抽象类只能通过extends继承一个父类
接口中的default方法
在接口中,可以定义default方法
interface Person {
String getName();
default void run() {
System.out.println(getName() + " run");
}
}
class Student implements Person {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
public class Main {
public static void main(String[] args) {
Person p = new Student("Xiao Ming");
p.run();
}
}
格式:
public default 返回值类型 方法名称(参数列表) {
//...
}
说明:
- 实现类可以不必覆写default方法
- 默认方法可以被覆盖重写
- default方法的目的:当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。
- default方法和抽象类的普通方法是有所不同的。因为接口没有字段,default方法无法访问字段,而抽象类的普通方法可以访问实例字段。
接口的静态方法
从Java 8开始,接口中允许定义静态方法
public interface MyInterfaceStatic {
public static 返回值类型 方法名称(参数列表) {
//...
//public可省略
//就是将abstract或者default换成static即可,带上方法体
}
}
说明:
- 不能通过接口实现类的对象来调用接口当中的静态方法
- 正确用法:通过接口名称直接调用
- 接口名称.静态方法名(参数)
接口的私有方法
从Java 9开始,接口中允许定义私有方法(实现类不能使用)
private的方法只有接口自己可以调用
分类:
- 普通私有方法,解决多个默认方法之间重复代码问题
- 静态私有方法,解决多个静态方法之间重复代码问题
private 返回值类型 方法名称(参数列表) {
//...
}
private static 返回值类型 方法名称(参数列表) {
//...
}
接口的常量(成员变量)
接口可以有静态字段的,并且静态字段必须为final类型
特点:
- 默认使用public static final修饰(可以省略)
- 不可改变
- 必须进行赋值
- 访问方式: 接口名.常量名
public static final int NUM_OF_MY_CLASS = 10;
抽象类名作为形参和返回值
- 方法的形参是抽象类名,需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,返回的是该抽象类的子类对象
接口名作为形参和返回值
接口
public interface Jumpping {
void jump();
}
接口操作类
public class JumppingOperator {
//方法里的形参就是接口
public void useJumpping(Jumpping j) { //Jumpping j = new Cat();
j.jump();
}
public Jumpping getJumpping() {
Jumpping j = new Cat();
return j;
}
}
接口的实现类
public class Cat implements Jumpping {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
测试类
public class JumppingDemo {
public static void main(String[] args) {
//创建操作类对象并调用方法
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.useJumpping(j);
Jumpping j2 = jo.getJumpping(); //new Cat()
j2.jump();
}
}
- 方法的形参是接口名,需要的是该接口的实现类对象
- 方法的返回值是接口名,返回的是该接口的实现类对象