接口基础

Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

接口声明格式为:

[访问修饰符] interface 接口名 [extends 父接口1, 父接口2…]{
    常量定义;   
    方法定义;
}

接口的作用:定义规则,跟抽象类不同的地方在于它是接口不是类。接口定义好规则之后,实现类负责实现即可。

以下面的代码为例:

public interface Test1 {
    /*public static final*/ int NUM = 10;
    //抽象方法:
    /*public abstract*/ void a();
    /*public abstract*/ void b(int num);
    /*public abstract*/ int c(String name);
}
interface Test2{
    void e();
    void f();
}

class Student extends Person implements Test1,Test2 {
    @Override
    public void a() {
        System.out.println("---1");
    }
    @Override
    public void b(int num) {
        System.out.println("---2");
    }
    @Override
    public int c(String name) {
        return 100;
    }
    @Override
    public void e() {
        System.out.println("---3");
    }
    @Override
    public void f() {
        System.out.println("---4");
    }
}

class Test{
    public static void main(String[] args) {
        //Test2 t = new Test2();
        Test2 t = new Student();
        System.out.println(Test1.NUM);
        System.out.println(Student.NUM);
        Student s = new Student();
        System.out.println(s.NUM);
        Test1 t2 = new Student();
        System.out.println(t2.NUM);
    }
}

注意事项如下:

  • 类是类,接口是接口,它们是同一层次的概念

  • 接口中没有构造器

  • 在JDK1.8之前,接口中只有两部分内容:

    • 常量,固定修饰符为 public static final
    • 抽象方法,固定修饰符为 public abstract

    修饰符可以省略不写,编译器会自动补全

  • 类和接口是实现关系 ,类实现接口

  • 一旦实现一个接口,那么实现类要重写接口中的全部的抽象方法

  • 如果没有全部重写抽象方法,那么这个类变成一个抽象类

  • 在Java中只有单继承,但有多实现。即一个类继承其他类,只能直接继承一个父类,但是类实现接口的话,可以实现多个接口

  • 继承和实现同时出现的写法是先继承,再实现,例如:extends Person implements Test1,Test2

  • 接口不能创建对象,例如:Test2 t = new Test2();

  • 接口可以指向实现类的对象,例如:Test2 t = new Student();

  • 访问接口中常量的办法:接口名.常量名实现类名.常量名实现类对象.常量名

多态的应用场合:

  • 父类当做方法的形参,传入具体的子类的对象
  • 父类当做方法的返回值,返回的是具体的子类的对象
  • 接口当做方法的形参,传入具体的实现类的对象
  • 接口当做方法的返回值,返回的是具体的实现类的对象

JDK1.8后接口新增内容

在JDK1.8之前,接口中只有两部分内容:

  • 常量,固定修饰符为 public static final
  • 抽象方法,固定修饰符为 public abstract

在JDK1.8之后,新增了非抽象方法:

  • public default 修饰的非抽象方法

    public interface TestInterface {
        public static final int NUM= 10;
        public abstract void a();
    
        public default void b(){
            System.out.println("TestInterface---b()");
        }
    }
    class Test implements TestInterface{
        public void c(){
            b(); // Test---b()
            // super.b();不可以
            TestInterface.super.b(); // TestInterface---b()
        }
        @Override
        public void a() {
            System.out.println("重写了a方法");
        }
        @Override
        public void b() {
            Test---b();
        }
    }
    

    注意事项为:

    • 非抽象方法的 default 修饰符必须要加上,否则出错
    • 实现类中要是想重写接口中的非抽象方法,那么 default 修饰符必须不能加,否则出错
  • 静态方法

    public interface TestInterface {
        public static final int NUM = 10;
        public abstract void a();
        public default void b(){
            System.out.println("TestInterface---b()");
        }
        public static void c(){
            System.out.println("TestInterface中的静态方法");
        }
    }
    class Demo implements TestInterface{
        @Override
        public void a() {
            System.out.println("重写了a方法");
        }
        public static void c(){
            System.out.println("Demo中的静态方法");
        }
    }
    class A {
        public static void main(String[] args) {
            Demo d = new Demo();
            d.c(); // Demo中的静态方法
            Demo.c();  // Demo中的静态方法
            TestInterface.c(); // TestInterface中的静态方法
        }
    }
    

    注意事项如下:

    • static 不可以省略不写
    • 静态方法不能重写

Question:为什么要在接口中加入非抽象方法?

Answer:如果接口中只能定义抽象方法的话,那么要是修改接口中的内容,对实现类的影响太大了,所有实现类都会受到影响。而在接口中加入非抽象方法,对实现类没有影响,想调用就调用。