接口的概述:
- 接口是描述一个类有什么功能,而并不需要去实现具体功能(给出一些空的方法去描述所提供的功能)
如果类遵从某个特定接口,那么就履行这项服务。(摘自java核心技术卷一)
- 接口中所有方法都属于public,不需要显示提供
- 接口没有实例,所以方法不能包含实例,成员变量只能是静态常量(public static修饰,同样不需要显示提供)
- 接口的声明是用interface,实现接口用implements
- 接口也可以继承一个超接口,以此来进行拓展
- 接口不能实例化一个对象,或者说不能new一个对象,但是可以声明一个变量
- 类只能继承一个超类,但是可以实现多个接口,这样可以得到大部分多继承的好处,同时也避免了大部分多继承带来的麻烦,接口之间用逗号(,)连接
- jdk 8 中接口可以增加静态方法,public static修饰
- 接口中还可以提供默认方法,用default修饰,可以同时提供多个默认方法,默认方法不必强制覆盖,可以提高代码的一个重用性
下面从例子中再去深入理解接口的特性:
- java中有一个Comparable接口,下面是他的代码:
public interface Comparable<T>{
int campareTo(Object other);
}
Arrays类中有一个sort方法可以对对象数组进行排序,但是必须满足一个条件,该对象所属的类必须实现了Comparable接口,因为sort方法里面调用了对象的campareTo方法,所以只要实现了Comparable接口,对象就一定包含并且实现了campareTo方法。 再代入到一个雇员管理系统中去实现,下面是他的代码:
package 雇员管理系统;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
public class Employee implements Comparable<Employee>{
private final String name;
private double salary;
private final LocalDate hireDay;
private static int nextId;
private final int id;
//静态初始化块,类加载时就会执行
static{
Random n = new Random();
nextId = n.nextInt(10000);
}
//初始化块,构造器调用时,根据类中数据域声明的顺序,依次执行
{
id = nextId;
nextId++;
}
public Employee(String name,double salary,int year,int month,int day){
this.name=name;
this.salary=salary;
hireDay = LocalDate.of(year,month,day);
}
public String getName(){
return name;
}
public double getSalary(){
return salary;
}
public LocalDate getHireDay(){
return hireDay;
}
public void raiseSalary(double raise){
salary = salary*raise/100+salary;
}
public int getId(){
return id;
}
public int compareTo(Employee other){
//如果第一个参数小于第二个参数返回一个负值,如果相等返回0,否则返回一个正值
return Double.compare(salary,other.salary);
}
我在该类中实现了Comparable接口,所有我可以使用Araays.sort()对Employee对象进行排序,下面是测试代码:
package 薪金管理系统;
import java.util.ArrayList;
import java.util.Arrays;
public class EmployeeTest {
public static void main(String... args){
//创建一个Employee类型的数组
Employee[] staff= new Employee[3];
staff[0] = (new Employee("Gay",75000,1987,12,05));
staff[1] = (new Employee("Ling",8000,1995,12,12));
staff[2] = (new Employee("Tao",95000,1996,10,15));
for(Employee e:staff){
e.raiseSalary(5);
}
//对staff数组进行排序
Arrays.sort(staff);
for(Employee e:staff){
System.out.println("name:"+e.getName()+" salary:"+e.getSalary()+" hireday:"+e.getHireDay()+"id:"+e.getId());
}
}
}
注释:如果Employee类没有实现Comparable接口,仅仅只是增加了一个compareTo方法,时候会报错,因为java是个强类型语言,sort方法中包含了类型转换会把staff变量强制转换为Comparable类型。
运行结果:

package java接口;
public interface Mouseable {
default void mouseClick(){
//可以调用任何方法
mousePrint();
}
default public void mousePressed(){}
public static void mousePrint(){
System.out.println("this is a mouse!");
}
}
package java接口;
public class MouseTest implements Mouseable {
}
默认方法不必强制覆盖,并且可以调用任何方法。
默认方法会遇到冲突问题,遵循俩大原则:
- 类优先原则,继承的一个超类,和实现的一个接口中,如果包含同名而且参数类型相同的方法,会优先使用超类中的方法
- 实现的俩个接口中如果包含同名而且参数类型相同的方法,必须覆盖这个方法来解决冲突 举个例子:
package java接口;
public interface Person {
default String getName(){
return getClass().getName();
}
}
package java接口;
public interface Named {
default String getName(){
return getClass().getName();
}
}
package java接口;
public class Student implements Person,Named {
public String getName(){
return Person.super.getName();
}
}
以上就是俩个接口默认方法冲突的情况,需要覆盖getName来解决二义性,否则就会报错。
java接口在lambda表达式中也有应用,还有很多很多地方,需要了解的可以上网查询。