【Java接口也继承了Object吗?

2023年 10月 14日 81.7k 0

【Java】接口也继承了Object吗?

开篇先表明我的观点:没有继承。

分析问题

我个人在网上大家的观点不是很统一,有认为继承了的,也有认为没有继承的。

支持没有继承有以下观点

从接口的设计思想考虑

为了规避菱形问题Java采用了单一继承的原则,那么接口就诞生于解决单一继承的原则。若接口也继承了Object,某个类实现了某个接口,那么这个类即隐式继承了Object,接口也继承了Object,这就违背了Java的最初的单一继承原则。

支持继承有以下观点

实验代码

Interface A {
    
}
class verify implements A{
    void f(A a) {
        System.out.println(a.hashCode());
        System.out.println(a.toString());
    }
}

以上的代码是可以通过编译通过的,证明是接口a也继承了Object。

个人观点

在Java Language Specification里面找答案

原文和翻译(来自ChatGPT,个人校验,英文水平有限)放在文末了。

根据Java8的文档,如果一个接口没有父接口,那么接口会隐式声明一个public abstract方法 ,这个方法与Object中的public实例方法相对应(签名相同、返回值相同、抛出异常相同),除非接口中声明了具有相同签名,相同返回值和兼容的异常抛出的抽象方法。

这段话就可以解释下面这段代码为什么能够编译成功了。

Interface A {
    
}
class verify implements A{
    void f(A a) {
        System.out.println(a.hashCode());
        System.out.println(a.toString());
    }
}

我们还可以通过下面的代码来验证,让interface和class来对比一下。

通过获取A和B中的方法也可以看出interface A是没有继承Object的。

class Main {
    public static void main(String[] args) {
        HashSet setA = new HashSet();
        for (Method method : A.class.getMethods()) {
            setA.add(method.getName());
        }
        
        HashSet setB = new HashSet();
        for (Method method : B.class.getMethods()) {
            setB.add(method.getName());
        }
        System.out.println("interface A:" + setA); 
        // interface A:[]
        System.out.println("class     B:" + setB); 
        // class     B:[getClass, wait, hashCode, equals, notifyAll, toString, notify]

    }
}

interface A {

}
class B {

}

JSL文档中也提到可以声明Object中的方法,那么此时finalize就是interface A自己的方法了,提高了访问级别,和异常级别。

class Main {
    public static void main(String[] args) {
        HashSet setA = new HashSet();
        for (Method method : A.class.getMethods()) {
            setA.add(method.getName());
        }
        System.out.println("interface A:" + setA); // interface A:[finalize]

    }
}

interface A {
    void finalize() throws Exception;
}
class verify implements A{
    void f(A a) {
        System.out.println(a.hashCode());
        System.out.println(a.toString());
    }

    @Override
    public void finalize() {

    }
}

Java8、9、17关于接口成员的文档

docs.oracle.com/javase/spec…

docs.oracle.com/javase/spec…

docs.oracle.com/javase/spec…

一步一步来研究

Java8

The members of an interface type are:

  • Members declared in the body of the interface (§9.1.4).

  • Members inherited from any direct superinterfaces (§9.1.3).

  • If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.

    It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.

    It is a compile-time error if the interface explicitly declares a method with a signature that is override-equivalent (§8.4.2) to a public method of Object, but which has a different return type, or an incompatible throws clause, or is not abstract.

The interface inherits, from the interfaces it extends, all members of those interfaces, except for fields, classes, and interfaces that it hides; abstract or default methods that it overrides (§9.4.1); and static methods.

Fields, methods, and member types of an interface type may have the same name, since they are used in different contexts and are disambiguated by different lookup procedures (§6.5). However, this is discouraged as a matter of style.

接口类型的成员包括:

  • 在接口主体(§9.1.4)中声明的成员。

  • 从任何直接超级接口继承的成员(§9.1.3)。

  • 如果一个接口没有直接的超级接口,那么该接口会隐式声明一个公共抽象成员方法 m,其签名为 s,返回类型为 r,与 Object 中声明的每个公共实例方法 m 的签名 s、返回类型 r 和异常抛出声明 t 对应,除非接口明确声明了具有相同签名、相同返回类型和兼容的异常抛出声明的抽象方法。

​ 如果接口明确声明了在 Object 中被声明为 final 的这种方法 m,将导致编译时错误。

​ 如果接口明确声明了一个方法,其签名与 Object 的公共方法 override-equivalent(§8.4.2)相同,但返回类型不同、异常抛出声明 不兼容,或者不是抽象的,也会导致编译时错误。

接口从它所扩展的接口那里继承了这些接口的所有成员,除了隐藏的字段、类和接口;覆盖的抽象或默认方法(§9.4.1);以及静态方法。

接口类型的字段、方法和成员类型可以具有相同的名称,因为它们在不同的上下文中使用,通过不同的查找程序(§6.5)进行区分。然而,出于风格上的考虑,不鼓励这样做。

Java9

The members of an interface type are:

  • Members declared in the body of the interface (§9.1.4).

  • Members inherited from any direct superinterfaces (§9.1.3).

  • If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object (§4.3.2), unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.

    It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.

    It is a compile-time error if the interface explicitly declares a method with a signature that is override-equivalent (§8.4.2) to a public method of Object, but which has a different return type, or an incompatible throws clause, or is not abstract.

The interface inherits, from the interfaces it extends, all members of those interfaces, except for i) fields, classes, and interfaces that it hides, ii) abstract methods and default methods that it overrides (§9.4.1), iii) private methods, and iv) static methods.

Fields, methods, and member types of an interface type may have the same name, since they are used in different contexts and are disambiguated by different lookup procedures (§6.5). However, this is discouraged as a matter of style.

接口类型的成员包括:

  • 在接口声明的主体中声明的成员(§9.1.4)。

  • 从任何直接超级接口继承的成员(§9.1.3)。

  • 如果一个接口没有直接超级接口,那么该接口会隐式声明一个具有签名 s、返回类型 r 和异常抛出声明 t 的公共抽象成员方法 m,该方法对应于 Object(§4.3.2)中声明的每个公共实例方法 m 的签名 s、返回类型 r 和异常抛出声明 t,除非接口明确声明了具有相同签名、相同返回类型和兼容异常抛出声明的抽象方法。

​ 如果接口明确声明了一个在 Object 中被声明为 final 的方法 m,则这会导致编译时错误。

​ 如果接口明确声明了一个方法,其签名与 Object 的公共方法 override-equivalent(§8.4.2)相同,但返回类型不同、异常抛出声明 不兼容,或者不是抽象的,也会导致编译时错误。

接口从它扩展的接口那里继承了这些接口的所有成员,除了(i)隐藏的字段、类和接口,(ii)覆盖的抽象方法和默认方法(§9.4.1),(iii)私有方法,以及(iv)静态方法。

接口类型的字段、方法和成员类型可以具有相同的名称,因为它们在不同的上下文中使用,通过不同的查找过程(§6.5)进行区分。然而,出于风格的考虑,不鼓励这样做。

Java17

The members of an interface are:

  • Members declared in the body of the interface declaration (§9.1.5).

  • Members inherited from any direct superinterface types (§9.1.3).

  • If an interface has no direct superinterface types, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object (§4.3.2), unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.

    It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.

    It is a compile-time error if the interface explicitly declares a method with a signature that is override-equivalent (§8.4.2) to a public method of Object, but which has a different return type, or an incompatible throws clause, or is not abstract.

The interface inherits, from the interfaces it extends, all members of those interfaces, except for (i) fields, classes, and interfaces that it hides, (ii) abstract methods and default methods that it overrides (§9.4.1), (iii) private methods, and (iv) static methods.

Fields, methods, member classes, and member interfaces of an interface may have the same name, since they are used in different contexts and are disambiguated by different lookup procedures (§6.5). However, this is discouraged as a matter of style.

接口的成员包括:

  • 在接口声明的主体中声明的成员(§9.1.5)。

  • 从任何直接超级接口类型继承的成员(§9.1.3)。

  • 如果一个接口没有直接的超级接口类型,那么该接口会隐式声明一个公共抽象成员方法 m,其签名为 s,返回类型为 r,以及与 Object(§4.3.2)中声明的每个公共实例方法 m 的签名 s、返回类型 r 和异常抛出声明 t 对应,除非接口明确声明了具有相同签名、相同返回类型和兼容的异常抛出声明的抽象方法。

​ 如果接口明确声明了在 Object 中被声明为 final 的这种方法 m,则这会导致编译时错误。

​ 如果接口明确声明了一个方法,它的签名与 Object 的公共方法 override-equivalent(§8.4.2)相同,但返回类型不同、异常抛出声 明不兼容,或者不是抽象的,也会导致编译时错误。

接口从它扩展的接口那里继承了这些接口的所有成员,除了(i)隐藏的字段、类和接口,(ii)覆盖的抽象方法和默认方法(§9.4.1),(iii)私有方法,以及(iv)静态方法。

接口的字段、方法、成员类和成员接口可以具有相同的名称,因为它们在不同的上下文中使用,通过不同的查找过程(§6.5)进行区分。然而,出于风格的考虑,不鼓励这样做。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论