学科分类
目录
Java基础

接口

如果一个抽象类中的所有方法都是抽象的,则可以将这个类定义为Java中的另一种形式——接口。接口是一种特殊的抽象类,它不能包含普通方法,其内部的所有方法都是抽象方法,它将抽象进行的更为彻底。

在JDK 8中,对接口进行了重新定义,接口中除了抽象方法外,还可以有默认方法和静态方法(也叫类方法),默认方法使用default修饰,静态方法使用static修改,并且这两种方法都允许有方法体。

与定义类不同的是,在定义接口时,不再使用class关键字,而是使用interface关键字来声明。接口定义的基本语法格式如下:

[修饰符] interface 接口名 [extends 父接口1,父接口2,...] {
    [public] [static] [final] 常量类型 常量名 = 常量值;
    [public] [abstract] 方法返回值类型 方法名([参数列表]);
    [public] default 方法返回值类型 方法名([参数列表]){
        // 默认方法的方法体
    }
     [public] static 方法返回值类型 方法名([参数列表]){
        // 类方法的方法体
    }
}

在上述语法格式中,“[]”中的内容都是可选的,修饰符可以使用public或直接省略(省略时默认采用包权限访问控制符);“extends 父接口1,父接口2,...”表示定义一个接口时,可以同时继承多个父接口,这也是为了解决类的单继承的限制;在接口内部可以定义多个常量和抽象方法,定义常量时必须进行初始化赋值,定义默认方法和静态方法时,可以有方法体。

小提示:

在接口中定义常量时,可以省略“public static final”修饰符,此时,接口会默认为常量添加“public static final”修饰符。与此类似,在接口中定义抽象方法时,也可以省略“public abstract”修饰符,定义default默认方法和static静态方法时,可以省略“public”修饰符,这些修饰符系统都会默认进行添加。

从接口定义的语法格式可以看出,接口中可以包含三类方法,抽象方法、默认方法、静态方法,其中静态方法可以通过“接口名.方法名”的形式来调用,而抽象方法和默认方法只能通过接口实现类的实例对象来调用,因此,需要定义一个接口的实现类,该类通过implements关键字实现当前接口,并实现接口中的所有抽象方法。需要注意的是,一个类可以在继承另一个类的同时实现多个接口,并且多个接口之间需要使用英文逗号(,)分隔。

定义接口的实现类语法格式如下:

[修饰符] class 类名 [extends 父类名] [implements 接口1,接口2,...] {
  ...
}

了解了接口及其方法的定义方式后,接下来通过一个案例来学习接口的实现与方法调用,如文件1所示。

文件1 Example13.java

 1    // 定义了Animal接口
 2    interface Animal {
 3        int ID = 1;       // 定义全局常量
 4        void breathe();  // 定义抽象方法breathe()
 5        // 定义一个默认方法
 6        default void getType(String type){
 7            System.out.println("该动物属于:"+type);
 8        }
 9        // 定义一个静态方法
 10        static int getID(){
 11            return Animal.ID;
 12        }
 13    }
 14    // Dog类实现了Animal接口
 15    class Dog implements Animal {
 16        // 实现breathe()方法
 17        public void breathe() {
 18            System.out.println("狗在呼吸");
 19        }
 20    }
 21    // 定义测试类
 22    public class Example13 {
 23        public static void main(String args[]) {
 24            System.out.println(Animal.getID()); // 通过接口名调用类方法
 25            Dog dog = new Dog();          // 创建Dog类的实例对象
 26            System.out.println(dog.ID); // 在实现类中获取接口全局常量
 27            dog.breathe();                 // 调用dog对象的breathe()方法
 28            dog.getType("犬科"); // 通过接口实现类Dog的实例化对象,调用接口默认方法
 29        }
 30    }

运行结果如图1所示。

图1 运行结果

文件1中,Dog类通过implements关键字实现了Animal接口,并实现了接口中的抽象方法breathe()。从图4-15可以看出,通过接口实现类Dog的实例化对象可以访问接口中的常量、接口实现方法以及默认方法,而接口中的静态方法则可以直接使用接口名调用。需要注意的是,接口的实现类,必须实现接口中的所有抽象方法,否则程序编译报错。

文件1中,演示的是类与接口之间的实现关系,其实,接口与接口之间还可以是继承关系,接口中的继承同样使用extends关键字来实现,接下来对文件1稍加修改,演示接口之间的继承关系,修改后的代码如文件2所示。

文件2 Example14.java

 1    // 定义了Animal接口
 2    interface Animal {
 3        int ID = 1;       // 定义全局常量
 4        void breathe();  // 定义抽象方法breathe()
 5        // 定义一个默认方法
 6        default void getType(String type){
 7            System.out.println("该动物属于:"+type);
 8        }
 9        // 定义一个静态方法
 10        static int getID(){
 11            return Animal.ID;
 12        }
 13    }
 14    // 定义了LandAnimal接口,并继承了Animal接口
 15    interface LandAnimal extends Animal { 
 16        void run();      // 定义抽象方法run()
 17    }
 18    // Dog类实现了LandAnimal接口
 19    class Dog implements LandAnimal {
 20        // 实现breathe()方法
 21        public void breathe() {
 22            System.out.println("狗在呼吸");
 23        }
 24        // 实现run()方法
 25        public void run() {
 26            System.out.println("狗在陆地上跑");
 27        }
 28    }
 29    // 定义测试类
 30    public class Example14 {
 31        public static void main(String args[]) {
 32            System.out.println(Animal.getID()); // 通过接口名调用类方法
 33            Dog dog = new Dog();          // 创建Dog类的实例对象
 34            System.out.println(dog.ID); // 在实现类中获取接口全局常量
 35            dog.breathe();                 // 调用dog对象的breathe()方法
 36            dog.getType("犬科");          // 通过dog对象,调用接口默认方法
 37            dog.run();                     // 调用dog对象的run()方法
 38        }
 39    }

运行结果如图2所示。

图2 运行结果

文件2中,定义了两个接口,其中LandAnimal接口继承了Animal接口,因此LandAnimal接口包含了2个抽象方法。当Dog类实现LandAnimal接口时,就需要实现这2个抽象方法。从图2可以看出,接口实现类Dog的实例化对象可以调用接口中的成员。

为了加深初学者对接口的认识,接下来对接口的特点进行归纳,具体如下:

(1)在JDK 8之前,接口中的方法都必须是抽象的,并且方法不能包含方法体。在调用抽象方法时,必须通过接口的实现类的对象才能调用实现方法;从JDK 8开始,接口中的方法除了包含抽象方法外,还包含默认方法和静态方法,默认方法和静态方法都可以有方法体,并且静态方法可以直接通过“接口.方法名”来调用。

(2)当一个类实现接口时,如果这个类是抽象类,只需实现接口中的部分抽象方法即可,否则需要实现接口中的所有抽象方法。

(3)一个类可以通过implements关键字同时实现多个接口,被实现的多个接口之间要用英文逗号(,)隔开。

(4)接口之间可以通过extends关键字实现继承,并且一个接口可以同时继承多个接口,接口之间用英文逗号(,)隔开。

(5)一个类在继承一个类的同时还可以实现接口,此时,extends关键字必须位于implements关键字之前。具体示例如下:

class A extends B implements C { // 先继承,再实现
...
}
点击此处
隐藏目录