接口概述

一方面,有时必须从几个类中派生一个子类,继承他们所有的属性和方法。但是Java不支持多重继承。有了接口,就可以得到多重继承的效果。

另一方面,有时必须从几个类抽取一些共同的行为特征,而他们之间又没有is-a的关系,仅仅是具有相同的行为特征而已。例如鼠标,键盘,摄像头都属于输入设备,使用USB连接。

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则必须能…”的思想。继承是一个是不是的关系,接口是一个能不能的关系。

接口的本质是契约,标准,规范,就像我们的法律一样。指定好后大家都要遵守。

举例

比如飞机、子弹、风筝、热气球都可以飞,但是子弹有攻击性。

我可以定义一个可以飞的接口和一个具有攻击性的接口。

飞机、风筝和热气球实现可以飞的接口,子弹实现这两个接口。

/**
 * 接口的使用:
 *      1.接口使用interface来定义
 *      2.Java中,接口和类是并列的两个结构
 *      3.如何定义接口:定义接口中的成员
 *      4.JDK7以前只能定义常量和抽象方法
 *      5.JDK8以后除了定义常量和抽象方法外还有静态方法和默认方法
 *      6.接口中不能定义构造器
 *      7.Java开发中,一般让类实现(implements)接口
 *      8.如果实现类重写了接口的所有抽象方法,就可以实例化
 *      9.Java类可以实现多个接口,弥补了Java无法多重继承
 *      10.接口与接口之间可以多继承
 *      11.接口的实现体现了多态性
 *      12.接口就是一种规范
 * 
 */
public class InterfaceTest {
    public static void main(String[] args) {
        // 全局变量可以直接调用
        System.out.println(Flyable.MAX_SPEED);

        // 实例化实现类Plane
        Plane plane = new Plane();
        plane.fly();
        plane.stop();

        // 实例化实现类Bullt
        Bullet bullet = new Bullet();
        bullet.fly();
        bullet.stop();
        bullet.att();
    }
}

// 飞接口
interface Flyable{

    // 全局常量
    public static final int MAX_SPEED = 7900;
    int MIN_SPEED = 1;

    // 抽象方法
    public abstract void fly();
    void stop();

}

// 攻击性接口
interface Attackable{

    // 抽象方法
    public abstract void att();

}


/**
 * 飞机实现类
 */
class Plane implements Flyable{
    @Override
    public void fly(){
        System.out.println("使用引擎起飞");
    }

    @Override
    public void stop(){
        System.out.println("驾驶员减速降落");
    }
}


/**
 * 风筝实现类
 */
class Kite implements Flyable{
    @Override
    public void fly(){
        System.out.println("乘风而飞");
    }

    @Override
    public void stop(){
        System.out.println("收线降落");
    }
}


/**
 * 子弹实现类
 */

 class Bullet implements Flyable,Attackable{
    @Override
    public void fly(){
        System.out.println("biubiubiu");
    }

    @Override
    public void stop(){
        System.out.println("papapa");
    }

    @Override
    public void att(){
        System.out.println("攻击性");
    }
 }

// 接口的多继承

interface A extends Flyable,Attackable{

}

如何体会接口是一种规范

我们定义一个电脑类,想要和电脑发生信息交互,就必须通过USB接口。

然后我们定义连接USB接口的规范是什么,首先要建立连接,传输完数据后要断开连接。

public class USBTest {
    public static void main(String[] args) {
        Computer com = new Computer();

        Flash flash = new Flash();

        com.transferData(flash);
    }
}

// 定义一个电脑类
class Computer{
    public void transferData(USB usb){
        usb.start();

        System.out.println("传输数据");

        usb.stop();
    }
}


// 这是一个USB接口
interface USB{
    void start();
    void stop();
}

// 我们可以接入U盘
class Flash implements USB{
    @Override
    public void start(){
        System.out.println("U盘开始工作");
    }

    @Override
    public void stop(){
        System.out.println("U盘结束工作");
    }
}

// 我们可以接入打印机
class Printer implements USB{
    @Override
    public void start(){
        System.out.println("打印机开始工作");
    }

    @Override
    public void stop(){
        System.out.println("打印机结束工作");
    }
}

接口匿名实现类

public class USBTest {
    public static void main(String[] args) {
        // 非匿名实现类
        Computer com = new Computer();
        Flash flash = new Flash();

        com.transferData(flash);

        // 匿名实现类
        com.transferData(new Printer());

        // 创建了接口的匿名实现类的非匿名对象
        USB phone = new USB(){
        
            @Override
            public void stop() {
                System.out.println("手机开始工作");
            }
        
            @Override
            public void start() {
                System.out.println("手机停止工作");
                
            }
        };

        com.transferData(phone);

        // 创建了接口的匿名实现类的匿名对象
        com.transferData(new USB(){
        
            @Override
            public void stop() {
                System.out.println("MP3开始工作");
            }
        
            @Override
            public void start() {
                System.out.println("MP3停止工作");
                
            }
        });
    }
}

// 定义一个电脑类
class Computer{
    public void transferData(USB usb){
        usb.start();

        System.out.println("传输数据");

        usb.stop();
    }
}


// 这是一个USB接口
interface USB{
    void start();
    void stop();
}

// 我们可以接入U盘
class Flash implements USB{
    @Override
    public void start(){
        System.out.println("U盘开始工作");
    }

    @Override
    public void stop(){
        System.out.println("U盘结束工作");
    }
}

// 我们可以接入打印机
class Printer implements USB{
    @Override
    public void start(){
        System.out.println("打印机开始工作");
    }

    @Override
    public void stop(){
        System.out.println("打印机结束工作");
    }
}

JDK8中的接口新特性

Java8中,你可以添加静态方法和默认方法。

静态方法:使用static关键字修饰。可以通过接口直接调用静态方法,并执行方法体。

默认方法:默认方法使用default关键字修饰。可以通过实现类对象来调用。

public class SubClassTest {
    public static void main(String[] args) {
        SubClass s = new SubClass();
        s.method2();
        s.method3();

        // 静态方法只能通过接口直接调用
        CompareA.method1();
    }
}

class SubClass implements CompareA{

}

----------
    


public interface CompareA {
    
    // 魔幻现实主义,接口里面有方法了
    public static void method1(){
        System.out.println("CompareA:北京");
    }

    // 上面的是静态方法,下面的是默认方法
    public default void method2(){
        System.out.println("CompareA:上海");
    }

    default void method3(){
        System.out.println("CompareA:广州");
    }
}

默认对象也可以重写。

public class SubClassTest {
    public static void main(String[] args) {
        SubClass s = new SubClass();
        s.method2();
        s.method3();

        // 静态方法只能通过接口直接调用
        CompareA.method1();
    }
}

class SubClass implements CompareA{
    public void method2(){
        System.out.println("subclass:上海");
    }
}

----------
    


public interface CompareA {
    
    // 魔幻现实主义,接口里面有方法了
    public static void method1(){
        System.out.println("CompareA:北京");
    }

    // 上面的是静态方法,下面的是默认方法
    public default void method2(){
        System.out.println("CompareA:上海");
    }

    default void method3(){
        System.out.println("CompareA:广州");
    }
}

问题:如果SubClass继承于父类SuperClass,SuperClass也有一个方法method3,那么SubClass的method3方法输出什么呢?

public class SubClassTest {
    public static void main(String[] args) {
        SubClass s = new SubClass();
        s.method2();
        s.method3();	// 执行父类的method3

        // 静态方法只能通过接口直接调用
        CompareA.method1();
    }
}

class SubClass extends SuperClass implements CompareA{
    public void method2(){
        System.out.println("subclass:上海");
    }
}

----------
    
public class SuperClass {
    public void method3(){
        System.out.println("SupClass:广州");
    }
}
    
    
----------


public interface CompareA {
    
    // 魔幻现实主义,接口里面有方法了
    public static void method1(){
        System.out.println("CompareA:北京");
    }

    // 上面的是静态方法,下面的是默认方法
    public default void method2(){
        System.out.println("CompareA:上海");
    }

    default void method3(){
        System.out.println("CompareA:广州");
    }
}

总结一下就是方法先找类本身的,再找父类的,再找接口的。

如果实现两个接口,然后两个接口的默认方法冲突了,那么就会报错。如果想要使用该方法,在实现类中必须要重写该方法。