1.接口的概念
在Java程序设计语言中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式定义。
接口中所有的方法自动地属于public,接口可能包含多个方法;接口中还可以定义常量,接口中的域自动地被设为public static final。虽然很多人喜欢写全修饰符,便于理解,但是Java语言规范并不推荐写全多余的关键字。
然而,更重要的是要知道接口不能提供哪些功能。接口绝不能含有实例域,在Java SE8之前,也不能在接口中实现方法。提供实例域和方法实现的任务应该由实现接口的那个类完成。
实现接口需要2个步骤:
1)用implements关键字声明类实现接口
2)必须对接口所有抽象方法进行定义重写
package 接口;
public class Employee implements Comparable<Employee>{
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
@Override
public int compareTo(Employee other) {
return Double.compare(salary, other.salary);
}
}
2.接口的特性
接口不是类,尤其不能使用new运算实例化一个接口:
x = new Comparable(...); //ERROR
然而,尽管不能构造接口的对象,却能声明接口的变量:
Comparable x; //OK
一个类只能有一个父类,但却可以实现多个接口
3.静态方法
目前为止,通常的做法都是将静态方法放在伴随类中。在标准库中,你会看到成对出现的接口和实用工具类,如Collection/Collections或Path/Paths。不过从Java SE8之后,可以直接将静态方法写在接口中,不需要再添加一个伴随类。
4.默认方法
在Java SE8之前,接口里面的方法只能是抽象方法,这样有一个问题,比如下面这个接口:
public interface Chess{
void forward();
void back();
void left();
void right();
}
如果棋子“卒”实现了这个接口,虽然它只能前进,向左或者向右,但是出于接口的特性,它在实现这些方法的同时还必须实现back方法,这就很尴尬了,明明“卒”没有后退功能,却还得去实现方法,不符合实际。
在Java SE8中,可以为接口方法提供一个默认实现。必须用default修饰符标记这样一个方法。大多数情况下,实现一个接口只是关注其中的某一些方法,这个时候把方法全部声明为默认方法,这些默认方法什么也不做,在类中重写你需要的方法。
``` public interface Chess{ default void forward(){}; default void back(){}; default void left(){}; default void right(){}; } ```默认方法还有一个好处是“源代码兼容”,比如Student类已经实现People接口,重写了其中的study方法,这时候,又要新建个Teacher类,也要实现Human接口,Teacher类要新增teach方法,如果直接在Human中添加以前那样的抽象方法,Student类也得跟着改,而如果添加为default方法,则以前的代码完全不用动,只要关注新增的Teacher类即可。
5.默认方法解决冲突的规则
1)超类优先。如果超类提供了一个具体的方法,接口中同方法签名的默认方法将被忽略。
//接口
public interface Name {
default String getName(){
return "影流之主";
}
}
//超类
public class People {
public String getName(){
return "疾风剑豪";
};
}
//子类继承超类实现接口
public class Employee extends People implements Name{
public static void main(String[] args) {
Employee e = new Employee();
String name =e.getName();
System.out.println(name); //疾风剑豪
}
}
当然,子类重写了一定执行的是子类重写的方法,类优先规则确保了与Java SE7的兼容性。
2)接口冲突。如果一个接口提供了一个默认方法,另一个接口提供了一个同方法签名的默认方法,必须重写来解决冲突。
public class Employee implements Name,Human{
public static void main(String[] args) {
Employee e = new Employee();
String name =e.getName();
System.out.println(name); //无极剑圣
}
//这里不重写会报错,无法编译
@Override
public String getName() {
return "无极剑圣";
}
}