1. 什么是接口
我们知道抽象类里面可以有普通方法也可以有抽象方法,子类继承抽象类必须要实现父类的抽象方法。
而接口
是一种特殊的抽象类
,特殊在哪里?特殊在它比较头铁,只出售抽象方法。
接口就像一些加盟店,你要想加盟,必须挂我的招牌,装修风格必须按我的来,说一不二。
2. 接口的定义
接口是一种“引用数据类型”。
java 中接口使用 interface
关键字定义,例如:
[修饰符列表] interface 接口名{}
复制代码
// 定义一个学生接口
public interface StudentService {
}
复制代码
普通类和抽象类可以被子类继承,继承的关键字是 extends。而接口没有继承这一说,只有“实现”。
实现就是实现接口中声明的的方法,说白了就是接口中只声明个方法,而接口的实现类必须重写这个方法。
接口中的方法只能通过类来实现,类实现接口的关键字是 implements
,例如:
// StudentService 接口的实现类
public class StudentServiceImpl implements StudentService{
}
复制代码
3. 接口的使用
3.1 接口中的变量必须初始化
因为接口中的变量是 public static final 类型的,final 修饰的变量不能更改,所以必须初始化。

修改之后:
// 定义一个学生接口
public interface StudentService {
String name ="哈哈哈";
public static void main(String[] args) {
System.out.println(StudentService.name);
}
}
复制代码
运行结果:
3.2 接口中的方法默认都是 public abstract 修饰,不能更改
也就是说方法前面你即便不写 public abstract ,接口默认也会给方法加上这两个修饰符。
3.3 接口不能创建对象
接口是一种特殊的抽象类,只能定义抽象方法和变量,不能创建对象,也没有构造方法。
这时候你可能该喷我了,之前讲抽象类的时候不是说抽象类有构造方法吗?接口即便是一种特殊的抽象类那它也是抽象类啊,为什么没有构造方法?
前面我在讲抽象类的时候说过,抽象类的构造方法是为了创建子类对象的时候初始化属性用的。
但是接口的属性都是 public static final 类型的,是不可更改的,已经做过初始化的。那还有必要用构造方法去初始化属性吗?
所以接口不能创建对象,也没有构造方法。
你或许还会反驳我:“那之前讲继承的时候,创建子类对象不是要先调用父类构造方法吗?接口没了构造方法,接口实现类不是就不能创建对象了?”
你可以把接口的实现理解成继承,但是实现接口不是继承父类,只有继承才有子类,而实现接口方法的叫接口实现类,所以创建接口实现类不需要用到接口的构造方法。
实现接口主要是实现接口声明的方法,核心是什么?是多态。
3.4 接口实现类必须实现接口的所有方法
因为接口是一种特殊的抽象类,所以如果一个类实现了该接口,必须实现该类中所有的抽象方法,例如:
public interface StudentService {
void add();
void sub();
void divide();
}
复制代码
// StudentService 接口的实现类
public class StudentServiceImpl implements StudentService{
@Override
public void add() {
System.out.println("add");
}
@Override
public void sub() {
System.out.println("sub");
}
@Override
public void divide() {
System.out.println("divide");
}
}
复制代码
3.5 接口之间可以继承,但接口之间不能实现
接口继承接口其实是为了程序的扩展,但是接口的实现必须由类实现,例如:
// 老师接口
public interface TeacherService {
String school = "雷布斯大学";
}
复制代码
// 定义一个学生接口
public interface StudentService extends TeacherService {
static void main(String[] args) {
System.out.println(StudentService.school);
}
}
复制代码
运行结果:
结果分析:
- 因为学生接口继承了老师接口,所以学生接口也拥有了 school 属性。
- 因为接口中所有属性都是 public static final 类型的,所以可以直接用
接口名.属性名
获取。 - 因为接口中所有的方法默认都是 public abstract 修饰的,所以上面例子中的main 方法可以去掉 public。
3.6 一个类可以实现多个接口
而接口的多实现其实就相当于多继承,解决了单一继承的缺陷。
实现多个接口,采用逗号隔开。例如:
public interface TeacherService {
String school = "雷布斯大学";
void add();
}
复制代码
// 定义一个学生接口
public interface StudentService {
void sub();
}
复制代码
// StudentService 接口的实现类
public class StudentServiceImpl implements StudentService,TeacherService{
@Override
public void sub() {
}
@Override
public void add() {
}
}
复制代码
4. 接口和抽象类的区别
-
- 抽象类中可以包含非抽象的方法,而接口中声明的方法全部都是抽象的。
-
- 抽象类和接口都不能实例化对象,抽象类的主要作用是抽取公共的代码。
-
- 接口解决了单继承问题
5. 理解接口
其实我们的现实生活中到处都是接口的例子。
-
- 电脑有 USB 接口,可以插键盘、插鼠标、插音箱等。
-
- 你可以用普通充电器、快充、充电宝给你的手机充电。
-
- 银行柜员可以服务全国各地的客户。
这些都是关于接口的例子,从上面你可以看出接口有什么好处?可扩展性。
用专业的话来说面向接口编程
可以降低程序的耦合度、提高程序的可扩展性。
方法的调用者只用面向接口,调用接口的方法。而接口的实现者面向接口实现其中的方法。
接口将方法的调用者和方法的实现者解耦,这不就是多态
吗?
6. 接口案例
- 新建 USB 接口
// USB接口
public interface UsbService {
// 设备开始工作了
void work();
}
复制代码
- 新建键盘实现类
// 键盘实现类
public class KeyboardServiceImpl implements UsbService {
public static final String NAME = "键盘";
@Override
public void work() {
System.out.println("键盘开始工作了");
}
}
复制代码
- 新建鼠标实现类
// 鼠标实现类
public class MouseServiceImpl implements UsbService {
public static final String NAME = "鼠标";
@Override
public void work() {
System.out.println("鼠标开始工作了");
}
}
复制代码
- 新建电脑类
// 电脑类
public class Computer {
// 连接外部设备
public void connect(UsbService usbService){
if(usbService instanceof KeyboardServiceImpl){
System.out.println("电脑连接上了"+KeyboardServiceImpl.NAME);
}
if (usbService instanceof MouseServiceImpl){
System.out.println("电脑连接上了"+MouseServiceImpl.NAME);
}
// 面向接口编程,方法的调用者面向接口调用
usbService.work();
}
}
复制代码
- 测试类
public class InterfaceTest {
public static void main(String[] args) {
Computer computer = new Computer();
UsbService usbService1 = new KeyboardServiceImpl();
computer.connect(usbService1);
System.out.println("----------------");
UsbService usbService2 = new MouseServiceImpl();
computer.connect(usbService2);
}
}
复制代码
运行结果: