在Java中,接口(Interface)是一种引用类型,类似于类,但只能包含抽象方法、默认方法、静态方法、常量和嵌套类型。接口的主要作用是定义一组方法规范,供类实现,从而实现多重继承的效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// A 接口
public interface AInterface {
void sayHello();
}
// B 接口
public interface BInterface {
void sayHello();
}
public class Main implements AInterface, BInterface {
/**
* 实现了sayHello方法
* 因为实现只有一份,因此避免了C++中多重继承带来的问题
*/
@Override
public void sayHello() {
System.out.println("Hello World");
}
public static void main(String[] args) {
new Main().sayHello(); // 调用sayHello方法
}
}
|
- 抽象类不能被实例化,可以包含抽象方法(非private/static),可以包含普通类的任何东西
- 抽象方法必须被覆盖,抽象方法必须在抽象类中,一个方法被抽象,那么这个类也必须抽象
- 一个抽象类里如果所有方法都是抽象方法,那么它就可以用接口表示
- 接口中方法都是抽象的
- 接口中不能有实例变量
- 接口用来描述一套功能
- 接口能继承另一个接口
- 要实现一个接口必须实现这个接口中的所有方法
- 一个类可以同时实现多个接口,这侧面解决了C++中多继承调用方法歧义的问题 因为接口中没有方法体,具体的实现是在实现了这些接口的类中的,实现只有一份,不会产生歧义
- 接口中的方法默认是public的
- 接口中的成员默认是public static final的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* 接口有一个非常大的弊端
* 就是当你一个接口发布之后,就不能再改了.
* 因为我们知道,一个类要实现一个接口,就必须实现它的所有方法
* 如果这个接口后期又添加了一个方法,那么所有实现了这个接口的类都必须重新实现
* 这在软件开发中是非常不能忍的事情.
*/
public interface AInterface {
void sayHello();
void sayWorld(); // A 接口新增了一个方法
}
/* 这个类就报错了,因为它没有实现sayWorld方法 */
public class Main implements AInterface {
@Override
public void sayHello() {
System.out.println("Hello World");
}
public static void main(String[] args) {
new Main().sayHello(); // 调用sayHello方法
}
}
|
因此Java8后引入了default修饰符来给接口增加默认实现的功能,使得所有没有实现这个方法的类也能正常工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public interface AInterface {
void sayHello();
default void sayWorld() {
System.out.println("World");
}
}
public class Main implements AInterface {
public static void main(String[] args) {
Main main = new Main();
main.sayHello();
main.sayWorld(); // 没有实现sayWorld方法也能正常运行
}
@Override
public void sayHello() {
System.out.println("Hello World");
}
}
|
- Comparable 接口(可比较性接口)
- Collections.sort() 方法
- Predicate 接口(判断接口)
- FileVisitor 接口(文件过滤接口)
- Consumer 接口(消费者接口)
- Files.walkFileTree 方法
当你所有的方法都不需要具体实现时用接口,反之则用抽象类