文章目录
十六.接口
接口就是一种规则,是对行为的抽象
接口是一种能力,一种约束
jdk7以前:接口中只能定义抽象方法
jdk8新特性:接口中可以定义有方法体的方法,该方法一种是默认方法,一种是静态方法。
jdk9新特性:接口中可以定义私有方法
私有方法分为两种,一种是普通的私有方法,服务于默认方法,另一种时静态的私有方法,服务于静态方法。
16.1接口的定义和使用
-
接口用关键字
interface
来定义//接口名称:首字母大写,满足“驼峰模式” public interface 接口名{ // 方法... }
-
接口不能实例化(即 不能创建对象)
-
接口和类之间是实现关系,通过
implements
关键字表示public class 类名 implements 接口名1,接口名2{}
-
接口的子类(实现类)
要么必须重写接口中的所有抽象方法
要么自己是抽象类
-
在Java中接口是被实现的,实现接口的类称为实现类。
注意事项:
- 接口和类的实现关系,可以单实现,可以多实现
public class 类名 implements 接口名1,接口名2{}
- 实现类还可以继承一个类的同时实现多个接口
public class 类名 extends 父类 implements 接口名1,接口名2{}
- 调用一个方法时,如果方法的形参是一个接口,那么我们要传递这个接口的实现类对象
16.2类实现接口的要求和意义
- 必须重写实现的全部接口中所有抽象方法。
- 如果一个类实现了接口,但是没有重写完全部接口的全部抽象方法,这个类也必须定义成抽象类。
- 意义:接口体现的是一种规范,接口对实现类是一种强制性的约束,要么全部完成接口申明的功能,要么自己也定义成抽象类。这正是一种强制性的规范。
接口应用案例:
青蛙frog 属性:名字、年龄; 行为:吃虫子,蛙泳
狗Dog 属性:名字、年龄; 行为:吃骨头,狗刨
兔子 属性:名字、年龄; 行为:吃胡萝卜
//父类
public abstract class Animal {
private String name;
private int age;
public Animal() {}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name;}
public void setName(String name) { this.name = name;}
public int getAge() {return age;}
public void setAge(int age) { this.age = age;}
// 抽象方法
public abstract void eat();
}
==========================================================
//接口
public interface Swim {
public abstract void swim();
}
==========================================================
//子类Dog
public class Dog extends Animal implements Swim{
public Dog() { }
public Dog(String name, int age) {super(name, age);}
//重写父类中的抽象方法
@Override
public void eat() {
System.out.println("狗在吃骨头");
}
//重写接口中的所有方法
@Override
public void swim() {
System.out.println("狗在狗刨...");
}
}
==========================================================
//子类 Frog
public class Frog extends Animal implements Swim{
public Frog() {}
public Frog(String name, int age) {super(name, age);}
//重写父类中的抽象方法
@Override
public void eat() {
System.out.println("青蛙在吃虫子...");
}
//重写接口中的所有方法
@Override
public void swim() {
System.out.println("青蛙在蛙泳...");
}
}
==========================================================
//子类Rabbit
public class Rabbit extends Animal{
public Rabbit() {}
public Rabbit(String name, int age) {super(name, age);}
//重写父类中的抽象方法
@Override
public void eat() {
System.out.println("兔子在吃胡萝卜....");
}
}
==========================================================
//测试类
public class Test {
public static void main(String[] args) {
Dog dog = new Dog("小黑",1);
dog.eat();
dog.swim();
System.out.println(dog.getName()+","+dog.getAge());
}
}
16.3 接口中成员的特点
-
成员变量:
只能是常量
默认修饰符:public static final
-
构造方法:
没有
-
成员方法:
只能是抽象方法(jdk7以前)
默认修饰符:public abstract
16.4 接口和类之间的关系
类和类的关系
- 继承关系,只能单继承,不能多继承,但是可以多层继承
类和接口的关系
- 实现关系,可以单实现,也可以多实现,还可以继承一个类的同时实现多个接口
- 在这个实现类中实现了多个接口,需要将所有的抽象方法重写。
- 如果实现的这多个接口中有重名 的抽象方法,只需要将重名的抽象方法重写一次即可。
//接口1
public interface Inter1 {
public abstract void method1();
}
============================================================
//接口2
public interface Inter2 {
public abstract void method1();
public abstract void method2();
}
============================================================
//实现类
public class InterImpl implements Inter1,Inter2{
// 重写一次method1即可,代表即重写了Inter1里面的,又重写了Inter2里面的
@Override
public void method1() {
System.out.println("method1....");
}
@Override
public void method2() {
System.out.println("method2....");
}
}
接口和接口的关系
-
继承关系,可以单继承,也可以多继承;
-
如果实现类实现了最下面的子接口,就需要重写所有的抽象方法。
//接口1
public interface Inter1 {
public abstract void method1();
}
============================================================
//接口2
public interface Inter2 {
public abstract void method2();
}
============================================================
//接口3,接口3同时继承接口1,接口2
public interface Inter3 extends Inter1,Inter2{
public abstract void method3();
}
==========================================================
//实行类,实现接口3,则需要重写整个接口体系中所有的抽象方法
public class InterImpl implements Inter3{
@Override
public void method1() {}
@Override
public void method2() {}
@Override
public void method3() {}
}
16.6JDK8接口中的方法
jdk8新特性:接口中可以定义有方法体的方法,该方法一种是默认方法,一种是静态方法。
16.6.1默认方法
jdk8新增接口特性
-
允许在接口中定义默认方法,需要关键字
default
修饰作用:解决接口升级问题
接口中默认方法的定义格式:
public default 返回值类型 方法名(参数列表){ }
范例:public default void show(){ }
接口中默认方法的注意事项:
- 默认方法不是抽象方法,所以不强制被重写;但如果被强写,重写的时候去掉default
- public 可以省略,default 不能被省略
- 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类必须对该默认方法进行重写(将重名的默方法,重写一次即可)
//接口
public interface Inter {
//接口中的抽象方法
public abstract void method();
//接口中的默认方法
public default void show(){
System.out.println("接口中的默认方法show...");
}
}
========================================================
//实现类
public class InterImpl implements Inter{
//接口中的抽象方法的重写
@Override
public void method() {
System.out.println("重写接口中的方法...");
}
//接口中抽默认方法重写,需要去掉default
@Override
public void show() {
System.out.println("重写接口中的默认方法show...");
}
}
========================================================
//测试类
public class Test {
public static void main(String[] args) {
InterImpl li = new InterImpl();
// 实现类里的方法
li.method();//重写接口中的方法...
// 实现类里不重写接口中的默认方法
li.show();//不重写时:接口中的默认方法show...
// 实现类里重写接口中的默认方法
li.show();//重写时:重写接口中的默认方法show...
}
}
16.6.2静态方法
jdk8新增接口特性
- 允许在接口中定义静态方法,需要用
static
修饰
接种的静态方法的定义格式:
public static 返回值类型 方法名(参数列表){ }
范例:public static void show(){ }
调用静态方法:
- 接口名.方法名();
- 类名.方法名();
接口中静态方法的注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public 可以省略,static不能省略
- 静态方法不需要重写
//接口
public interface Inter {
//接口中抽象方法
public abstract void method();
//接口中静态方法,不用被重写
public static void show(){
System.out.println("接口中的静态方法...");
}
}
========================================================
//实现类
public class InterImpl implements Inter{
//重写了接口的抽象方法
@Override
public void method() {
System.out.println("重写了接口的抽象方法");
}
// 注意:此静态方法不是重写接口中的静态方法
//只是恰好实现类中也有个静态方法,名字与接口中的静态方法一样
public static void show(){
System.out.println("实现类里的静态方法...");
}
}
===============================================
//测试类
public class Test {
public static void main(String[] args) {
InterImpl li = new InterImpl();
// 实现类里的方法
li.method();//重写了接口的抽象方法...
// 调用接口中的静态方法
Inter.show();//接口中的静态方法...
// 调用实现类的静态方法
InterImpl.show();//实现类里的静态方法...
}
}
16.7JDK9接口中的私有方法
jdk9新特性:接口中可以定义私有方法,
接口中普通私有方法:给接口中默认方法服务的
格式1:private 返回值类型 方法名(参数列表) { }
范例1:private void show() { }
public interface InterA {
public default void show1(){
System.out.println("show1方法开始执行..");
show4();
}
public default void show2(){
System.out.println("show2方法开始执行..");
show4();
}
// 接口中普通私有方法:给接口中默认方法服务的
private void show4(){
System.out.println("100行代码...");
}
}
接口中静态的私有方法:给静态方法服务的
格式2:private static 返回值类型 方法名(参数列表) { }
范例2:private static void method() { }
public interface InterA {
public static void show1(){
System.out.println("show1方法开始执行..");
show4();
}
public static void show2(){
System.out.println("show2方法开始执行..");
show4();
}
// 接口中静态的私有方法:给静态方法服务的
private static void show4(){
System.out.println("100行代码...");
}
}