Java基础之接口

662 阅读5分钟

1. 什么是接口

接口是多个类的公共规范。

2. 接口的定义

public interface 接口名称 {
    // 接口内容
    // jdk1.7可以包含常量,抽象方法
    // jdk1.8可以包含默认方法,静态方法
    // jdk1.9可以包含私有方法
}

3. 接口的使用

接口的使用主要包含三部分

(1) 首先需要定义接口和接口中的抽象方法。

(2) 新建一个类,实现接口并重写接口中的所有抽象方法,此处需要注意,如果只部分重写了接口的抽象方法,那么该类需要定义为抽象类。

(3) 创建上述类对象,即可使用接口。

// 1. 定义接口和接口中的抽象方法
public interface MyInterface {
    
    public abstract void method1();
    public abstract void method2();
}

// 2. 新建一个类,实现接口并重写接口中的所有抽象方法
public class MyInterfaceImpl implements MyInterface {
    
    @Override
    public void method1() {
        System.out.println("实现抽象方法1");
    }
    @Override
    public void method2() {
		System.out.println("实现抽象方法2");
    }
}

// 3. 创建类对象,即可使用接口中的内容

4. 接口中的默认方法

现在假设接口的实现类MyInterfaceImpl已经投入使用了,但是现在要给接口加一个功能,比如加一个抽象方法,那么MyInterfaceImpl也需要重写新增的抽象方法,会造成一定的麻烦,而使用接口中的默认方法,则可以减少接口升级的麻烦。比如,我们现在接口中添加一个默认方法method3()MyInterfaceImpl中不需要做任何改动,就可以用它的对象访问到method3(),实现了无感升级。当然,我们也可以在实现类中做对应的升级,即重写method3()

public interface MyInterface {

    public abstract void method1();

    public abstract void method2();
	
    public default void method3() {
        System.out.println("接口中的默认方法");
    }
}

public class InterfaceTest {
    public static void main(String[] args) {
        MyInterfaceImpl myInterface = new MyInterfaceImpl();
        myInterface.method3(); // 输出"接口中的默认方法"
    }
}

5. 接口中的静态方法

接口中静态方法的访问是直接通过接口来访问的,而不是通过实现类或者实现类的对象。另外一点需要注意的是,虽然接口中的静态方法不能被实现类重写,但是在实现类中可以存在一个完全同名同参的静态方法。

// 接口中静态方法定义
public interface MyInterface {

    public static void method4() {
        System.out.println("接口中的静态方法");
    }
}

// 实现类中的同名同参静态方法
public class MyInterfaceImpl implements MyInterface {

    public static void method4() {
        System.out.println("实现类中的静态方法");
    }
}

// 接口中静态方法使用
public class InterfaceTest {
    public static void main(String[] args) {
        MyInterface.method4(); // 输出"接口中的静态方法"
        MyInterfaceImpl.method4(); // 输出"实现类中的静态方法"
    }
}

6. 接口中的常量

接口中的变量只能是public static final修饰的,所以其实是常量,当然,public static final不写也没关系,默认被修饰为常量。此外,我们还需要注意,接口中的常量在定义的时候要赋值,并且一经赋值不可更改。

public interface MyInterface {
	public static final int NUM = 10;
}

7. 一个类继承父类并实现多个接口

一个类只可以继承一个父类,但可以实现多个接口。比如,在下面的代码中,实现类继承了父类Father,并实现了接口A和接口B。在这种情况下,有可能会涉及到接口 - 接口,接口 - 父类之间同名方法的冲突。

(1) 第一种冲突是接口间抽象方法的冲突,可以看到在接口A和接口B中都抽象方法methodA(),此时实现类只需要重写一次methodA()

(2) 第二种冲突是接口间默认方法的冲突,默认方法即使不重写,也可以通过实现类对象进行访问,但是当两个接口默认方法重名时,会出现不知道访问哪一个的情况,因此同名的默认方法必须要在实现类中重写。

(3) 第三种冲突是接口默认方法和父类普通方法的冲突,可以选择不重写,通过实现类对象访问的时候,优先调用父类中的方法;也可以重写,则调用重写后的方法。

// 接口A
public interface InterfaceA {

    public abstract void methodA();

    public abstract void methodB();

    public default void methodC() {
        System.out.println("接口A的默认方法C");
    }

}

// 接口B
public interface InterfaceB {

    public abstract void methodA();

    public default void methodC() {
        System.out.println("接口B的默认方法C");
    }

    public default void methodD() {
        System.out.println("接口B的默认方法D");
    }
}

// 父类
public class Father {

    public void methodD() {
        System.out.println("父类中的普通方法D");
    }
}

// 实现类
public class InterfaceABImpl extends Father implements InterfaceA, InterfaceB {
    @Override
    public void methodA() {
		 System.out.println("同名抽象方法的重写");
    }

    @Override
    public void methodB() {

    }

    @Override
    public void methodC() {
        System.out.println("实现类的默认方法C");
    }

}

8. 接口和接口间的多重继承

之前提到了类 - 类之间只可以单继承,类 - 接口之间可以多实现,那接口 - 接口之间呢,其实是支持多重继承的。但是在多继承时有几点需要注意:

(1) 被继承的两个接口,比如接口A和接口B拥有同名抽象方法methodAbstract(),此时在继承的接口C中,不需要重写,只需要在接口C的实现类中进行抽象方法的重写即可。

(2) 被继承的两个接口,比如接口A和接口B拥有同名默认方法methodDefault(),此时在继承的接口C中,一定要重写该方法。

// 接口A
public interface InterfaceA {

    public abstract void methodA();

    public abstract void methodAbstract();

    public default void methodDefault() {
        System.out.println("接口A的默认方法");
    }
}

// 接口B
public interface InterfaceB {

    public abstract void methodB();

    public abstract void methodAbstract();

    public default void methodDefault() {
        System.out.println("接口B的默认方法");
    }
}

// 继承了接口A和接口B的接口C
public interface InterfaceC extends InterfaceA, InterfaceB {

    public abstract void methodC();

    @Override
    default void methodDefault() {
        System.out.println("接口C的默认方法");
    }
}