【Java学习笔记】接口——基于Java SE8

来源:互联网 发布:企业彩铃录音软件 编辑:程序博客网 时间:2024/04/26 07:45

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/CollectionsPath/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 "无极剑圣";    }}