Java:如果A扩展B和B扩展对象,是多重继承

2022-09-01 05:55:28

我刚刚接受了一次采访,有人问我一个问题。

采访者 - Java是否支持多重继承?

- 否

采访者 - Java中的每个类都扩展类对象(除了类对象),如果我们从外部扩展一个类,例如

Class A extends B{
  // some code here
}

那么你可以说类A扩展了类B和类Object,这意味着它是多重继承。那么你怎么能说Java不支持多重继承呢?

Me - 实际上类 B 扩展了类 Object,因此当您在类 A 中扩展类 B 时,类 A 会间接扩展类 Object。这是多级继承,而不是多重继承。

但我的回答并没有让他满意。

我的答案正确吗?或者我错在哪里?内部到底发生了什么?


答案 1

我的答案是正确的吗?

是的,主要是,当然在你描述的上下文中。这不是多重继承:

Object ^- ClassA ^- ClassB

这就是你说的,具有多个级别的单继承。

这是多重继承:从两个或多个彼此没有任何“是”关系的基继承;这将从不相关的行继承,或者从以前发散的行继承(在Java中,由于始终是一个基础,因此它将是后者):Object

Object ^- ClassA, Object ^- ClassB, ClassA ^- ClassC, ClassB ^- ClassC

(图片来源:http://yuml.me 在“邋遢”模式下)

内部到底发生了什么?

正如你所说:有多个层次。当编译器解析实例上的成员时:

obj.member

...它查看的类型(在本例中是类,例如)是否具有 ,要么是因为它直接提供它,要么是通过继承具有它。在运行时,JVM 使用对象实际具有的。objClassBmembermember


我上面说“大部分”的原因是Java有接口,从Java 8开始,它在接口上有“默认方法”。这让事情变得有点复杂,但是你关于水平的答案在你描述面试官所说的、、和的上下文中是正确的。ObjectClassAClassB

在Java中,接口总是使某些东西与两种不同类型的“is a”关系成为可能:它继承的类类型,以及它实现的几种接口类型中的任何一种。没有默认方法的接口实际上不是多重继承(类必须提供实现),但它们确实使类有可能具有来自不相关类型树的多个“is a”关系。(我不是学者,学者可能会争辩说他们以学术方式提供了多重继承。

在Java 8中,接口可以提供它们定义的方法的默认实现,即使在实际层面上,这确实模糊了界限。让我们更深入地看一下:

假设我们有:ClassA

class ClassA {
    void doSomething() {
        // Code here
    }
}

和:Interface1

interface Interface1 {
    default void doSomethingElse() { // Requires Java 8
        // Code here
    }
}

最后:ClassB

class ClassB extends ClassA implements Interface1 {
}

ClassB继承自 的实现。但它也从 中获取的“默认”版本。我们没有在 中实现它,但不是抽象的:它确实具有 .它从界面获取它。我在那里使用了“gets”这个词而不是“inherits”,但这看起来很像继承默认方法。doSomethingClassAdoSomethingElseInterface1ClassBClassBdoSomethingElse

这基本上是多重继承的“轻”(如“淡啤酒”)。它解决了真正多重继承的棘手问题,例如:

  • 应该是什么类型?(Java 8的答案:superClassA)
  • 您以什么顺序运行构造函数?(Java 8的答案是:单系构造函数链接,接口没有构造函数。
  • 您是否运行了多次、多次继承的构造函数?(Java 8的答案是:你不能多次继承构造函数,接口没有构造函数。
  • 如果继承具有相同签名的多个方法,会发生什么情况?(Java 8的答案:如果其中一个来自基类,那就是使用的基类;基类的实现可以覆盖多个接口的默认方法。如果在编译时有多个默认方法具有来自不同接口的相同签名,则这是编译时错误。如果在未重新编译类的情况下更改了接口,并且这种情况在运行时出现,则它是运行时异常,列出了冲突的默认方法。IncompatibleClassChangeError

答案 2

你是对的

首先,Object 类是每个类(包括用户定义的类)的超级/基/父类。

因此,即使我们没有明确提及它,用户定义的类也会默认扩展 Object 类。

它像

class A 
class B extends A

 but compiler read it as 
class A extends Object
class B extends A

证明

有关更多详细信息,请查看此 Java 文档以进行继承