接口
接口的概念
-
接口就是一种比抽象类还抽象的类,体现在所有方法都为抽象方法。
-
定义类的关键字是class,而定义接口的关键字是interface。
-
接口比抽象类还抽象主要体现在两点:1、只能有常量;2、里面只能由抽象方法(新特性除外);
package com.lagou.module02.task04; /** * @author hhc19 * @date 2021/12/31 22:12 * @description */ public interface InterfaceTest { // private int cnt; // Modifier 'private' not allowed here 这里不允许使用private关键字 // int a; // Variable 'a' might not have been initialized 说明它是一个final关键字修饰的变量,必须初始化且不能更改 // int a = 0; 默认加上了public static final 关键字,即默认它是一个常量 如果我们不主动写上public static final的话,JVM会隐式加上了public static final /*public static final */int CNT = 1; // 接口是个比抽象类还要抽象的类,不能new对象,所以使用接口就不得不使用多态 // 不能new对象说明我们不能通过对象.去访问,只能通过类名.来访问,所以还要加上static关键字 // 既然public static final共同修饰这个变量,就说明它是个常量,变量名就得是全部大写 // public static final 可以省略,接口跟抽象类比果然更抽象,因为里面只能有常量 // private void show() {} // 从jdk1.9(Java9)开始允许接口中出现私有方法(新特性) // public void show() {} Interface abstract methods cannot have body 接口中的抽象方法不能有方法体 /*public abstract */void show(); // 里面只能有抽象方法(新特性除外) public abstract可以省略 注释中的关键字可以省略,但建议写上,提高代码可读性 // protected 也不可写在这里 }
-
如:金属接口 货币接口 黄金类 => 弥补了Java中不支持多继承的不足,不可以同时继承金属类和货币类,但可以同时实现金属接口和货币接口。
实际意义
-
弥补了不能多继承的不足
-
使用implements 关键字表达实现的关系,支持多实现,多个接口之间使用,隔开
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:01 * @description 金属接口 */ public interface Metal { // 自定义抽象方法描述发光的行为 public abstract void shine(); }
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:03 * @description 货币接口 */ public interface Money { // 自定义抽象方法描述购物的行为 public abstract void buy(); }
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:05 * @description 黄金类 * 使用implements 关键字表达实现的关系,支持多实现,多个接口之间使用,隔开 */ public class Gold implements Metal, Money { @Override public void shine() { System.out.println("发出了金黄色的光芒..."); } @Override public void buy() { System.out.println("买了好多好吃的..."); } public static void main(String[] args) { // 1、声明接口类型的引用指向实现类的对象,形成了多态 Metal mt = new Gold(); mt.shine(); Money mn = new Gold(); mn.buy(); } }
练习题目
-
编程实现Runner接口,提供一个描述奔跑行为的抽象方法。
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:20 * @description */ public interface Runner { // 自定义抽象方法描述奔跑行为 public abstract void run(); }
-
编程实现Hunter接口继承Runner接口,并提供一个描述捕猎行为的抽象方法。=>接口和接口之间的关系是继承
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:21 * @description * 接口只能继承接口,不能继承类 */ public interface Hunter extends Runner { // 自定义抽象方法实现捕猎行为 public abstract void hunt(); }
-
编程实现Man类实现Hunter接口并重写抽象方法,在main方法中使用多态方式测试
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:26 * @description 编程实现Man类实现Hunter接口并重写抽象方法,在main方法中使用多态方式测试 */ public class Man implements Hunter { @Override public void hunt() { System.out.println("正在追赶一只小白兔..."); } @Override public void run() { System.out.println("正在被一只大熊追赶,玩命奔跑中..."); } public static void main(String[] args) { // 1、声明接口类型的引用指向实现类类型的对象,形成了多态 Runner r = new Man(); // 提高代码的可读性 r.run(); Hunter h = new Man(); h.hunt(); h.run(); } } 接口中私有方法的作用----------------------------------- /* 问题描述: 我们需要抽取一个共有方法,用来解决两个默认方法之间的重复代码的问题。 但是这个共有方法不应该让实现类使用,应该是私有化的。 解决方案: 从java 9开始,接口当中允许定义私有方法。 1.普通私有方法,解决多个默认方法之间代码重复问题 格式: private 返回值类型 方法名称 (参数列表){ 方法体 } 2.静态私有方法,解决多个静态方法之间重复代码的问题 private static 返回值类型 方法名称(参数列表){ 方法体 } */
类和接口之间的关系(只要涉及到接口的都是多继承多实现,如果是类和类之间就是单继承)
接口和抽象类的主要区别
-
定义抽象类的关键字是abstract class,而定义接口的关键字是 interface。
-
继承抽象类的关键字是extends,而实现接口的关键字是implements。
-
继承抽象类只支持单继承,而实现接口支持多实现。
-
抽象类中可以有构造方法,而接口中不可以有构造方法(因为接口中只有抽象方法)。
-
抽象类中可以有成员变量,而接口中只能有常量(public static final共同修饰)。
-
抽象类中可以有成员方法,而接口中只能有抽象方法(public abstract共同修饰,新特性不考虑)。
-
抽象类中增加方法时子类可以不用重写,而接口中增加方法时实现类需要重写(Java8以前的版本,Java9新特性允许出现private的带方法体的方法)。
-
从Java8中开始增加新特性,接口中允许出现非抽象方法和静态方法,但非抽象方法需要使用default关键字修饰。
-
在Java9开始增加新特性,接口中允许出现私有方法(为了实现代码的复用,静态方法中有重复代码,就写一个静态的私有方法即可)。
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:21 * @description * 接口只能继承接口,不能继承类 */ public interface Hunter extends Runner { // 自定义抽象方法实现捕猎行为 public abstract void hunt(); // 将两个默认方法中重复的代码可以提取出来打包成一个方法然后在下面的两个方法中分别调用即可,该方法只是让show2和show3使用的,不需要实现类重写,不需要在类外使用 private void show() { System.out.println("在以后的开发中尽量减少重复的代码,也就是减少代码的冗余!"); } // 增加一个抽象方法 // public abstract void show1(); // 牵一发而动全身,接口中写一个抽象方法,数以万计的实现类都得实现这个方法,可能那些实现类并不需要 // java8以后,既可以往接口中增加抽象方法,也可以往接口中增加非抽象方法 // 可以增加非抽象方法,但是为了不违背之前的语法规则,需要增加一个关键字default public default void show2() { // System.out.println("在以后的开发中尽量减少重复的代码,也就是减少代码的冗余!"); show(); System.out.println("show2方法中:这里仅仅是接口中的默认功能,实现类可以自由选择是否重写!"); } public default void show3() { // System.out.println("在以后的开发中尽量减少重复的代码,也就是减少代码的冗余!"); show(); System.out.println("show3方法中:这里仅仅是接口中的默认功能,实现类可以自由选择是否重写!"); } // 除了增加默认方法之外,还可以增加静态方法,隶属于类层级,也就是接口层级 // 为了不违背以前不能new对象的原则,我们增加静态方法,也就是接口层级,可以直接使用接口名.的方式调用 // 用static修饰的方法除了可以省略创建对象之外,一般描述功能的方法才会使用static关键字修饰,描述一个功能的封装、打包、或者是把它当作是一个描述功能的工具类,或者工具方法来用的时候 public static void test() { System.out.println("这里是静态方法,可以直接通过接口名.的方式调用,省略对象的创建"); // 对于接口来说,本来就不能创建对象,就更完美了 } }
package com.lagou.module02.task04; /** * @author hhc19 * @date 2022/1/1 9:26 * @description 编程实现Man类实现Hunter接口并重写抽象方法,在main方法中使用多态方式测试 */ public class Man implements Hunter { // Class 'Man' must either be declared(声明) abstract or implement abstract method 'show1()' in 'Hunter' @Override public void hunt() { System.out.println("正在追赶一只小白兔..."); } @Override public void run() { System.out.println("正在被一只大熊追赶,玩命奔跑中..."); } @Override public void show2() { System.out.println("为了给你几分薄面,我决定重写一下!"); } public static void main(String[] args) { // 1、声明接口类型的引用指向实现类类型的对象,形成了多态 Runner r = new Man(); // 提高代码的可读性 r.run(); Hunter h = new Man(); h.hunt(); h.run(); System.out.println("---------------------------------"); // 2、可以使用接口名.的方式调用接口中的静法 Hunter.test(); } }