目录
接口的特点
- Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔)
- Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化
- Java接口中只能包含public,static,final类型的成员变量和public,abstract类型的成员方法
- 接口中没有构造方法,不能被实例化
- 一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
- Java接口必须通过类来实现它的抽象方法
- 当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象类
- 不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例
- 一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
接口
- Java不支持多继承,因此引入了一个和类并列的结构接口,接口可以达到多继承的效果。继承的判断是“A is a B”则class A extends B,接口则不是is a关系,例如:键盘、鼠标、u盘都支持USB连接,但不能说他们is a USB连接
- 继承的是“是不是”关系,而接口实现的是“能不能”的关系
- 接口的本质是契约、标准、规范
接口定义
JDK7之前只能定义以下两个
public interface 接口名{
public static final 类型 属性 = XX;public static final可省
public abstract 返回值类型 方法(); abstract可省
}
解释:因为接口只有全局常量和抽象方法,所以可以省略
接口没有构造器,所以不能实例化
子接口可以用extends继承父接口
子类可以通过implements连接父接口
接口的继承
public interface 子接口 extends 父接口{
一些补充方法
}
可实例化的类,接口通过implements实现
public class 子类 implements 父接口名,父接口名,父接口名{
在这里面重写所有的父接口方法
}
只重写部分父接口方法,该类为抽象类
public abstract class 子类 implements 父接口名,父接口名,父接口名{
在这里面重写所有的父接口方法
}
同时继承类也继承接口
public class 子类 extend 父类 implements 父接口名,父接口名,父接口名{
在这里面重写所有的父接口方法and父类方法
缺一个没重写就是abstract类
}
先定义两个接口,两个接口规范了实现类的必要条件,
interface Flyable {
public static final int MAX_SPEED = 50 ;
int MIN_SPEED = 10;//省略了public static final
public abstract void fly();
}
interface Eatable {
void eat();//省略了public abstract
}
abstract class Bird implements Flyable{
public void fly(){
System.out.println("鸟会飞");
}
}
class Bird_EatBugs extends Bird implements Flyable{
public void eat(){
System.out.println("有一些鸟吃虫子");
}
}
class Eagle implements Flyable,Eatable {
public void fly(){
System.out.println("老鹰是大鸟,也能飞");
}
public void eat(){
System.out.println("老鹰吃肉");
}
}
public class FlyTest {
public static void main(String[] args) {
Bird B1 = new Bird_EatBugs();
// Bird_EatBugs.fly()不能调用,因为编译看左
B1.fly();//抽象类只是不能实例化,并不是不能编译
Bird_EatBugs B2 = new Bird_EatBugs();
B2.fly();
B2.eat();
Eagle E1 = new Eagle();
E1.fly();
E1.eat();
}
}
测试
接口多态性,接口的匿名子类
类可以有匿名子类,通过new 父类 {重写} 实现
接口也有匿名子类,通过 new 接口 {重写} 实现
1.有名对象,匿名子类
Flyable FFF = new Flyable(){//new一个名为FFF的对象
public void fly(){
System.out.println("不知名的可飞行生物");
}//匿名内部需要重写
};//此时本质上new的是重写后的子类,不过没有名字
FFF.fly();
2.无名对象,匿名子类
public static void Method(Object obj){
System.out.println("调用成功,接口的匿名子类也属于Object");
}
Method(new Flyable(){
public void fly(){
System.out.println("不知名的可飞行生物");
}
});
JDK8之后的接口
这个版本之后的接口可以定义4种内容
- public static 接口静态方法
- public static fianl 全局常量
- public default 接口默认方法
- public abstract 用于规范的抽象方法
这些结构一般能简化,但是开发中建议不要简化,只是应注意在面试中可能会遇到挖坑的情况
下面用一个例子来完整说明4个方法的用法,定义两个接口Bounceable和Rollable来规范一个可以弹也可以滚的东西,定义他们的实现类Ball,定义一个继承于Ball的Basketball类
interface Rollable {
public static final double PI = 3.1415926535;
public abstract void roll();// 抽象方法,等待重写
public static void tell() {//解释这个接口的目的
System.out.println("这个东西能够滚动");
}//
public default void check() {//检查能否滚动
System.out.println("能调用,这个类能滚动");
}
}
interface Bounceable {
int MIN_BOUNCE = 1;//省略public static final,表示最小能弹1下
void bounce();//省略public abstract,等待重写
public static void tell(){//静态方法可以由接口直接调用,所以重名不用重写
System.out.println("这个东西能弹起来");
}
public default void check() {//default方法由对象调用,重名需重写
//多接口情况下接口同名同参方法必须在实现类重写,否则接口冲突,报错
System.out.println("能调用,这个类能弹起来");
}
}
class Ball implements Bounceable,Rollable{
@Override
public void roll() {
System.out.println("ball可以roll");
}
public void bounce() {
System.out.println("ball可以bounce");
}
@Override
public void check() {//default方法只能定义在interface中
//通过如下重写,让check方法只能检测bounce功能
//格式就是 接口.super.重名的默认方法();
Bounceable.super.check();
}
}
class Basketball extends Ball{//继承了Ball类就继承了Ball的所有接口
public void roll(){
System.out.println("篮球滚的很远");
}
public void bounce(){
System.out.println("篮球弹性很好");
}
//因为父类已经重写过了check方法,所以子类可以不用重写check
public void check(){
// Rollable.super.check();
// Basketball没有直接implements两个接口,所以不能用这个方法调用
System.out.println("篮球是弹的又高,滚的又远");
}
}
public class InterTest {
public static void main(String[] args) {
System.out.println(Basketball.MIN_BOUNCE+"\t"+Basketball.PI);
//接口静态常量,只要跟他有关的下级都能直接调用
Rollable.tell();
Bounceable.tell();
//接口静态方法,只能用接口调用,与类类似
System.out.println("*******************");
Basketball bsk = new Basketball();
bsk.bounce();
bsk.roll();
//调用两个在实现类中重写的方法
bsk.check();
System.out.println("*******************");
Ball bo = new Ball();
bo.bounce();
bo.roll();
bo.check();
}
}
类优先原则
如果Ball定义为abstract,则可以删除Ball中重写的roll()和bounce()方法
如果Ball中重写了roll()和bounce()方法,则子类Basketball调用的是Ball中重写的