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

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

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

分析问题

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

支持没有继承有以下观点

从接口的设计思想考虑

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

支持继承有以下观点

实验代码

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实例方法相对应(签名相同、返回值相同、抛出异常相同),除非接口中声明了具有相同签名,相同返回值和兼容的异常抛出的抽象方法。

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

java 复制代码
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的。

java 复制代码
class Main {
    public static void main(String[] args) {
        HashSet<String> setA = new HashSet<>();
        for (Method method : A.class.getMethods()) {
            setA.add(method.getName());
        }
        
        HashSet<String> 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自己的方法了,提高了访问级别,和异常级别。

java 复制代码
class Main {
    public static void main(String[] args) {
        HashSet<String> 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)进行区分。然而,出于风格的考虑,不鼓励这样做。

相关推荐
人活一口气21 小时前
Spring Boot与AIGC的完美结合:从零搭建智能内容生成平台
java·spring boot·aigc
像我这样帅的人丶你还1 天前
Java 后端详解(三):全局异常处理与 JPA 数据库映射
java·后端
NE_STOP1 天前
vibe Coding -- 小项目实战
java
未秃头的程序猿1 天前
Java 26正式发布!这3个新特性,让代码量直接减半
java·后端·面试
用户298698530141 天前
Word 文档文本查找与替换的 Java 实现方案
java·后端
阿哉1 天前
Nacos 服务发现源码:藏在背后的两套事件机制,90%的人只讲了一半
java
咖啡八杯1 天前
GoF设计模式——命令模式
java·设计模式·架构
AI人工智能_电脑小能手1 天前
【大白话说Java面试题 第125题】【并发篇】第25题:说说 Java 线程的中断机制
java·后端·面试
Java内核笔记1 天前
Spring Security 源码解析(六)无状态 JWT 实践:Session 共享与自定义过滤器
java·后端
荣码1 天前
LangGraph多Agent协作:3个Agent干活比1个强,但我踩了4个坑
java·python