接口的定义
接口可以理解成统一的协议, 而接口中的属性也属于协议中的内容。但是接口的属性都是公共的,静态的,最终的。
接口的成员特点:
- 成员变量只能是常量,默认修饰符
public static final
- 成员方法只能是抽象方法。默认修饰符
public abstract
所以,Java 接口中,变量必须给出初始值,且绝对不会被修改,因为隐藏的修饰符为 public static final。
//接口成员变量和成员方法
public interface People {
int age=10;
String name="输出名字"; // 默认 public static final 修饰
void eat(); //默认 public abstract 修饰
boolean play(int account) throws AccountNotFoundException;
}
- JDK1.8以前接口中只能有常量和抽象方法。
- JDK1.8开始后,出现了3种方法形式:
- 默认方法用default修饰,默认用public修饰,由实现类对象调用;
- 静态方法用static修饰,默认用public修饰,必须接口名调用。
- 私有方法JDK9开始,用private修饰,只能在接口内部调用。
public interface Inter {
void test1();//抽象方法,需要在实现类中被重写
public default void test2(){
System.out.println("默认方法被实现了");}//默认方法可以直接使用实现类的对象进行调用,也可以在实现类中对其进行覆盖重写。
public static void test3() {
System.out.println("静态方法被实现了");}//静态方法,接口中的静态方法不能被实现类继承和子接口继承
public static void main(String[] args) {}//接口可以有主函数
}
注意事项:
- 接口不能创建对象
- 一个类实现了多个接口,多个接口中有同样的静态方法不冲突,因为static修饰必须由接口名调用
- 一个类继承了父类,同时又实现了接口,父类和接口中有同名方法,默认用父类的。
- 一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可,但是不可以调用。
- 一个接口继承多个接口没问题,但是存在规范冲突则不能多继承,比如下面这种情况
//AAA,BBB中相同方法定义的返回值规范不一样
interface AAA {int run();}
interface BBB {void run();}
interface CCC extends AAA, BBB{}
接口的重写
先让我们简单复习下重写的规则(可以用@Override注解进行判断):
- 私有方法不可以被重写,本质上只有继承到子类的可访问到的方法才需要被覆盖重写。
- 静态方法也不可以被重写,原因是静态方法是属于父类对象的。
- 子类重写父类方法,
访问权限>=父类,返回值类型<=父类,异常类型<=父类
,可以简单理解为,如果子类重写了父类方法,在编译阶段检查参数的引用类型,然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行该对象的方法。
public interface Inter {
void test1();//抽象方法,需要在实现类中被重写
public default void test2(){
System.out.println("默认方法被实现了");}//默认方法可以直接使用实现类的对象进行调用,也可以在实现类中对其进行覆盖重写。
public static void test3() {
System.out.println("静态方法被实现了");}//静态方法,接口中的静态方法不能被实现类继承和子接口继承
public static void main(String[] args) {}//接口可以有主函数
}
//实现类为class
public class Interlmpl implements Inter {
@Override
public void test1() {
System.out.println("实现test1抽象方法"); }
@Override
public void test2(){}//重写默认函数,也可以不重写,重写时去掉default关键字
}
//实现类为abstarct class
abstract class Interlmpl2 implements Inter {
}
//定义测试类
public class InterDemo {
public static void main(String[] args) {
Inter i = new Interlmpl();
i.test1(); //抽象方法强制被重写
i.test2(); //默认方法不强制被重写,但可以被重写
Inter.test3(); //静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
}
}