目录
3.接口
3.1.接口概述与生活举例
- 计算机中,接口是多个类的公共规范,接口是引用数据类型
3.2.接口的定义和使用
- 接口的定义:接口就是多个类的公共规范。接口是一种引用数据类型,最重要的内容就是其中的抽象方法
- public interface 接口名称{ //接口内容 }
- 备注:换成关键字interface后,编译生成的字节码文件仍然是java-->.class
- 接口使用步骤:
- 1.接口不能直接使用,必须有一个实现类实现接口.public class 实现类名称 implements 接口名称{ }
- 2.接口实现类必须重写接口中所有抽象方法。重写:去掉abstract关键字,加上方法体大括号。如果实现类并没有重写接口中所有抽象方法,则实现类必须是抽象类
- 3.主类中创建接口实现类对象并使用
3.3.接口中可以定义的方法
- 若是java7 那么接口中可以包含的内容有:
- 1.常量
- 2.抽象方法
- 若是java8 还可以额外包含:
- 3.默认方法
- 4.静态方法
- 若是java9 还可以包含
- 5.私有方法
3.4.接口中抽象方法定义和使用
- 在任何版本的Java中,接口都能定义抽象方法。
- 格式: public abstract 返回类型 方法名称(参数列表);
- 注意事项:
- 1.接口中的抽象方法,修饰符必须是两个固定关键字:public abstract
- 2.这两个关键字修饰符,可以选择性省略(刚学建议写上)
- 3.方法的三要素(返回类型、方法名、参数类型)可以随意定义
package demo15_interface; public interface MyInterfaceAbstract { //这是一个抽象方法 public abstract void methodAbs1(int a); //这也是一个抽象方法 public void methodAbs2(); //这也是一个抽象方法 abstract void methodAbs3(); } package demo15_interface; //接口实现类,alt+enter快捷键重写接口中所有抽象方法 public class MyInterfaceAbstractImpl implements MyInterfaceAbstract { @Override public void methodAbs1(int a) { System.out.println("这是第一个抽象方法的重写"); } @Override public void methodAbs2() { System.out.println("这是第二个抽象方法的重写"); } @Override public void methodAbs3() { System.out.println("这是第三个抽象方法的重写"); } } package demo15_interface; public class Demo01Interface { public static void main(String[] args) { //创建接口实现类对象 MyInterfaceAbstractImpl abs = new MyInterfaceAbstractImpl(); abs.methodAbs1(10); abs.methodAbs2(); } }
3.5.接口中默认方法的使用和解决的问题
- java8开始,接口中允许定义默认方法
- 格式: public default 返回类型 方法名称(参数列表){方法体}
- 作用:接口当中的默认方法,可以解决接口升级问题。
- 比如接口A的实现类有B、C,当接口A需要加入新的抽象方法时,为了避免实现类跟着变动,可在接口中设置该方法为默认方法。
- 接口中默认方法可被子类(实现类)继承,若无需要,不需重写默认方法。
- 默认方法使用:
- 1.接口默认方法,可以通过接口实现类对象,直接调用。
- 2.接口默认方法,可以被接口实现类进行覆盖重写。
- 3.接口中默认方法可以省略关键字public,抽象方法可以省略public abstract
package demo16_interface; public interface MyInterfaceDefault { //抽象方法,public abstract是灰色表示可以省略,仍表示抽象方法 public abstract void methodAbs(); //现进行接口升级,新添加一个抽象方法public abstract void methodAbs(); //为了不变动该接口已有的实现类(即在实现类中再实现该新抽象方法)。 //需要将新添加的方法改为默认方法。 public default void methodDefault(){ //public关键字是灰色,可以省略 System.out.println("这是接口中新添加的默认方法"); } } package demo16_interface; //接口实现类 public class MyInterfaceDefaultA implements MyInterfaceDefault { @Override public void methodAbs() { System.out.println("实现了抽象方法,AAA"); } } package demo16_interface; //接口实现类 public class MyInterfaceDefaultB implements MyInterfaceDefault { @Override public void methodAbs() { System.out.println("实现了抽象方法,BBB"); } @Override public void methodDefault() { System.out.println("实现类B重写了接口中默认方法"); } } package demo16_interface; public class Demo01 { public static void main(String[] args) { //创建接口实现类对象 MyInterfaceDefaultA a = new MyInterfaceDefaultA(); a.methodAbs();//调用抽象方法,实际运行的是右侧实现类MyInterfaceDefaultA //调用默认方法,实现类中若没有,则向上找接口 a.methodDefault(); MyInterfaceDefaultB b = new MyInterfaceDefaultB(); b.methodAbs();//抽象方法 b.methodDefault();//默认方法 } }
3.6.接口中静态方法使用
- 从java8开始,接口当中允许定义静态方法。
- 格式:public static 返回类型 方法名称(参数列表){方法体}
- 提示:就是将abstract或default换成static即可,带上方法体。
- 使用:
- 1.通过接口名称直接调用其中的静态方法。
- 2.不能通过实现类对象调用接口中静态方法。
- 3.静态方法属于类,不属于对象,
package demo17_interface; public interface MyInterfaceStatic { public static void methodStatic(){ System.out.println("这是接口中的静态方法"); } } package demo17_interface; public class MyInterfaceStaticImpl implements MyInterfaceStatic { } package demo17_interface; public class Demo01 { public static void main(String[] args) { //直接通过接口名称调用静态方法 MyInterfaceStatic.methodStatic(); } }
3.7.接口中私有方法使用及解决的问题
- 问题描述:
- 接口中我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码问题。
- 但是这个共有方法不应该让实现类使用,应该是私有化的,只供本类中方法调用。
- 解决方案:
- 从java9开始,接口当中允许定义私有方法
- 1.普通私有方法,解决多个默认方法之间重复代码问题。
- 格式: private 返回类型 方法名称(参数列表){方法体}
- 2.静态私有方法,解决多个静态方法之间重复代码问题。
- 格式:private static 返回类型 方法名称(参数列表){方法体}
- 若属性和方法只供在本类/接口中使用,使用private修饰将属性和方法具体实现封装,并提供对应的方法供其他类访问。
package demo18_interface; public interface MyInterfacePrivateA { public default void methodDefault(){ System.out.println("默认方法1"); //System.out.println("aaa"); //System.out.println("bbb"); methodCommon(); } public default void methodDefault2(){ System.out.println("默认方法2"); //System.out.println("aaa"); //System.out.println("bbb"); methodCommon(); } //抽取共有方法,解决两个默认方法之间重复代码问题 //有问题:这样抽取的共有方法能被实现类单独使用,这是不恰当的, // 默认方法中抽取的共有方法应该被接口中默认方法调用, // 而不是被实现类对象单独调用,即方法设置成私有, // 只供本类中方法调用(本类被抽取的方法来调用)。 /* public default void methodCommon(){ System.out.println("aaa"); System.out.println("bbb"); } */ private void methodCommon(){ System.out.println("aaa"); System.out.println("bbb"); } } package demo18_interface; public class MyInerfacePrivateAImpI implements MyInterfacePrivateA{} package demo18_interface; import demo16_interface.MyInterfaceDefaultA; public class DemoA { public static void main(String[] args) { MyInerfacePrivateAImpI p = new MyInerfacePrivateAImpI(); p.methodDefault();//调用接口中默认方法(默认方法可在实现类中重写) //实现类对象调用接口中抽取的共有方法是不合适的,抽取的方法 //应该定义成私有,只供本类中方法调用(本类被抽取的方法来调用)。 p.methodDefault2(); //p.methodCommon();私有方法无法调用 } }
3.8.接口中常量定义和注意事项
- 接口中也可以定义“成员变量”,但必须使用public static final关键字修饰,从效果上看,这其实就是接口的【常量】
- 格式: public static final 数据类型 常量名称=数据值
- 备注: 一旦使用final关键字,说明变量值不可以改变
- 注意事项:
- 1.接口当中的常量,可以省略public static final
- 2.接口当中的常量,必须进行赋值(否则默认值为0还是常量不能更改,这个常量也没有意义)
- 3.接口中常量的名称,使用完全大写的字母,用下划线进行分割.
- 4.接口中常量通过接口调用
package demo19_interface; public interface MyInterfaceConst { public static final int NUM_OF_MY_CLASS=10; //接口中定义常量 } package demo19_interface; public class Demo01 implements MyInterfaceConst { public static void main(String[] args) { //访问接口中常量 System.out.println("接口中访问常量:"+MyInterfaceConst.NUM_OF_MY_CLASS); } }
3.9.Java9+版本中接口内容
3.10.继承父类并实现多个接口时产生的方法冲突
- 使用接口时候需要注意:
- 1.接口是没有静态代码块或者构造方法的。
- 2.一个类的直接父类是唯一的(单继承),但可同时实现多个接口(多实现)
- 3.如果实现类所实现的多个接口中,存在重复的抽象方法,只需覆盖重写一次即可。
- 4.如果实现类没有覆盖重写所有接口当中所有抽象方法,那么实现类必须是抽象类。
- 5.如果实现类实现的多个接口当中,存在重复的默认方法,则需要重写有冲突的默认方法。
- 6.一个类如果直接父类当中的方法和接口当中默认方法产生冲突,系统优先父类中方法(继承优先于接口实现)
package demo20_interface; public interface MyInterfaceA { public abstract void methodAbs();//抽象方法 public default void methodDef(){ System.out.println("接口A的默认方法methodDef()"); } } package demo20_interface; public interface MyInterfaceB { public abstract void methodAbs();//抽象方法 public default void methodDef(){ System.out.println("接口B的默认方法"); } } package demo20_interface; public class Fu { public void methodDef(){ System.out.println("这是父类methodDef()方法,与接口中默认方法冲突,优先使用父类的"); } } package demo20_interface; public class Zi extends Fu implements MyInterfaceA,MyInterfaceB { @Override public void methodAbs() { //两个接口中抽象方法冲突(重名),只需重写一次 System.out.println("实现类重写接口的抽象方法"); } @Override public void methodDef(){ //两个接口中默认方法冲突,需重写默认方法 System.out.println("实现类重写接口A,B中默认方法"); } } package demo20_interface; public class DemoMain { public static void main(String[] args) { Zi zi = new Zi(); zi.methodAbs();//调用抽象方法 zi.methodDef();//父类与接口中方法冲突,系统优先使用父类方法 } }
3.12.接口之间多继承产生的方法冲突
- 1.类与类之间是单继承,直接父类只有一个。
- 2.类与接口之间是多实现的,一个类可以实现多个接口。
- 3.接口与接口之间是多继承的。
- 注意事项:
- 1.多个父接口当中的抽象方法如果重复,子接口可以不重写该抽象方法。【接口的继承不需要重写父接口的抽象方法,实现类中才需要】
- 2.多个父接口当中的默认方法如果重复,子接口必须进行默认方法的重写。必须带着default关键字(因为是在接口中不能省略)】【因为默认方法是可以通过接口直接调用的,如果子接口实现类中直接通过子接口调用默认方法(此时子接口未重写父接口默认方法),那么该调用父接口A还是B中的同名默认方法呢?所以要重写】
package demo21_interface; public interface MyInterfaceA { public abstract void methodA();//接口的抽象方法 public abstract void methodCommon(); public default void methodDef(){ System.out.println("这是父接口A的默认方法"); } } package demo21_interface; public interface MyInterfaceB { public abstract void methodB();//接口的抽象方法 public abstract void methodCommon(); public default void methodDef(){ System.out.println("这是父接口B的默认方法"); } } package demo21_interface; /**接口之间的多继承: * 这个子接口当中有几个方法?4个 * methodA来源于接口A * methodB来源于接口B * methodCommon同时来源于接口A,B * method来源于自身 */ public interface MyInterface extends MyInterfaceA,MyInterfaceB { public abstract void method();//子接口本身的抽象方法 //1.接口的继承不需要重写父接口的抽象方法,实现类中才需要 public abstract void methodCommon();//子接口可以不重写多个父接口中重复的抽象方法 @Override default void methodDef() { //2.子接口需要重写多个父接口中同名的默认方法 System.out.println("子接口重写父接口们中重名的默认方法"); } } package demo21_interface; //子接口拥有以下4个抽象方法,子接口实现类需要重写这些抽象方法 public class MyInterfaceImpI implements MyInterface { @Override public void method() { } @Override public void methodA() { } @Override public void methodB() { } @Override public void methodCommon() { } }