查看原文
其他

Java 接口的演变史

康熙 终码一生 2022-09-22

点击“终码一生”,关注,置顶公众号

每日技术干货,第一时间送达!



1

发展史


Java 编程语言已经发展了二十多年。没有其他编程语言在如此长的时间内发展得如此之快,同时还保持对其遗留代码库的支持。Java 始终尽可能地提供向后兼容性,同时与大多数当前编程语言中可用的新功能保持同步。


Java 编程语言主要是关于开发四种类型——接口枚举注解。枚举和注解从 Java 5 开始出现。在这篇文章中,我想谈谈Java编程语言中接口类型的演变。


Java 中的接口最初设计为抽象类型,可用于类型的多重继承。在 Java 1.0 中,接口定义只能包含两种成员静态常量和抽象方法:


public interface SomeInterface {
    int SOME_CONSTANT = 35; // variable declaration
    int abstractMethod(int x, int y); // method declaration
}


接口中的所有变量声明始终是 public staticfinal 的,并且需要赋值。除此之外,接口中的所有方法都是公共的和抽象的。


接口中只有抽象方法,没有方法实现,这使得它可以用于类型的多重继承,同时仍然避免了多重继承的菱形问题。


类可以继承接口的抽象方法或提供实现。当相同的方法签名出现在超类和它正在实现的接口中时,则该方法是从超类继承的,而不是从接口继承的。


Java 1.1 引入了内部类的概念,其中类可以是类的成员。从 Java 2 开始,我们有了静态嵌套类和接口,这些也可以在接口内部使用。因此,从 Java 2 开始,我们在接口中有四种成员:静态常量抽象方法嵌套类嵌套接口


public interface SomeInterface {

    int SOME_CONSTANT = 35; // variable declaration
    int abstractMethod(int x, int y); // method declaration

  // nested class definition
    class NestedClass {
        // members of a class
    }

   // nested interface definition
    interface NestedInterface {
        // member of an interface
    }
}


在接口中定义的所有嵌套类和接口始终是公共的和静态的。


后来,Java 5 发布了许多新功能。它介绍了泛型以及新的枚举和注释类型。


Java 5 中引入的泛型是关于类型参数的。我们有泛型类、泛型接口和泛型方法,即。可以使用类型参数定义的类、接口和方法。因此,从 Java 5 开始,我们可以在接口中有六种类型的成员,使用静态常量、抽象方法、嵌套类、嵌套接口、嵌套枚举和嵌套注释。


// generic interface with one type parameter T
public interface SomeInterface<T> {

    int SOME_CONSTANT = 35; // variable declaration
    int abstractMethod(int x, int y); // method declaration

    T abstractMethodUsingGenericType(T[] array, int i); // method using type parameter

  // nested class definition
    class NestedClass {
        // members of a class
    }

     // nested interface definition
    interface NestedInterface {
        // member of an interface
    }

  // nested enum definition
    enum NestedEnum {
        OBJECT1,
        OBJECT2,
        ;
        // methods, variables and constructors
    }

  // nested annotation definition
    @interface NestedAnnotation {
        String attrib1();
    }
}


接口定义中的类型参数 T 只能用于抽象方法的返回类型和抽象方法的参数。它不能与静态成员一起使用。嵌套的枚举和注释始终是公共的和静态的。


Java 的一个重要特性一直是它的向后兼容性。尽管该语言多年来一直在发展,但仍非常注意支持遗留代码库。所有较新的 Java 版本始终能够编译和运行较旧的源代码——无需对代码进行任何更改。这种支持通常是有代价的。接口就是一个例子。接口的关键特性是它只能有抽象方法。为了实现向后兼容性,这种行为不能轻易更改,因此几乎不可能使用更新的方法来增强 API 中的现有接口。考虑自 Java 2 以来就存在的 List<E> 接口。最好为 List<E> 引入一个排序方法,为了解决这个问题,Java 8 在接口中添加了默认方法作为成员。这允许使用新方法增强接口,为新方法提供默认实现。


Java 8 还允许接口包含静态方法。因此,从 Java 8 开始,接口的成员可以是静态常量、抽象方法、默认方法、静态方法、嵌套类、嵌套接口、嵌套枚举和嵌套注解:


// generic interface with one type parameter T
public interface SomeInterface<T> {

    int SOME_CONSTANT = 35; // variable declaration
    int abstractMethod(int x, int y); // method declaration

    T abstractMethodUsingGenericType(T[] array, int i); // method using type parameter

    default int defaultMethod(int x, int y) {
        // implementation of method
    }

    static void main(String[] args) {
        // any static method, including main can be included in interface
    }

     // nested class definition
    class NestedClass {
        // members of a class
    }

    // nested interface definition
    interface NestedInterface {
        // member of an interface
    }

  // nested enum definition
    enum NestedEnum {
        OBJECT1,
        OBJECT2,
        ;
        // methods, variables and constructors
    }

     // nested annotation definition
    @interface NestedAnnotation {
        String attrib1();
    }
}


接口中的默认方法和静态方法始终是公共的。现在,由于我们有默认方法,即实现,这意味着,在 Java 中,我们现在也有行为的多重继承,而不仅仅是类型。


现在,我们遇到了 Java 中多重继承的钻石问题。由于我们可以通过默认方法实现行为,我们现在可以拥有重复的通用代码,可以在同一接口内的多个默认方法中复制。为了避免这种情况,我们通常会将方法的实现分解为更小的方法。而且,由于这些方法可能并不真正需要在接口之外可用,因此理想情况下它们应该是私有的。这现在可以通过 Java 9 来完成,Java 9 在接口中引入了私有方法。


从 Java 9 开始,接口中支持的成员是静态常量、抽象方法、默认方法、静态方法、私有方法、嵌套类、嵌套接口、嵌套枚举和嵌套注解:


// generic interface with one type parameter T
public interface SomeInterface<T> {

    int SOME_CONSTANT = 35; // variable declaration
    int abstractMethod(int x, int y); // method declaration

    T abstractMethodUsingGenericType(T[] array, int i); // method using type parameter

    default int defaultMethod(int x, int y) {
        // implementation of method
        // can call the privateMethod and privateStaticMethod here
    }

    static void main(String[] args) {
        // any static method, including main can be included in interface
        // can call privateStatic method here
    }

    private int privateMethod(int x, int y) {
        // private method implementation
    }

    private static void privateStaticMethod(int x, int y) {
        // private method implementation
    }

// nested class definition
    class NestedClass {
        // members of a class
    }

  // nested interface definition
    interface NestedInterface {
        // member of an interface
    }

// nested enum definition
    enum NestedEnum {
        OBJECT1,
        OBJECT2,
        ;
        // methods, variables and constructors
    }

  // nested annotation definition
    @interface NestedAnnotation {
        String attrib1();
    }
}



2

结论


有趣的是,接口的性质多年来是如何演变的,同时保持向后兼容性。在 Java 8 之前,接口的核心原则是它只能具有公共和抽象方法。但是,从 Java 8 开始,接口也可以有非抽象方法,而 Java 9 以后的接口也可以有私有方法。


PS:防止找不到本篇文章,可以收藏点赞,方便翻阅查找哦。


往期推荐



Nginx 对俄罗斯动手了!!

MySQL夺命15问,你能坚持到第几问?

避免重复造轮子,Java 程序员必备!!

CTO说了,谁在用select * 就走人!!

IDEA 与 VsCode

JDK 18 / Java 18 正式发布:九项 JDK 增强


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存