為什麼Java類不支持多繼承而接口可以?

2020-09-22 低調的乾貨君

每個用Java的人都知道java不支持多繼承,但為什麼呢?無論從抽象還是多態等層面思考,感覺都是行得通的,那麼為什麼不支持呢?

很多人都是分析一旦一個類繼承了多個父類,那麼父類中如果有相同的成員變量和方法,就不好處理,如下圖,這就是Diamond問題

GrandParent f() / \ / \Parent1 f() Parent2 f() \ / \ / Son f()

那麼此時子類如果我們只引用 f(),編譯器將無法決定它應該調用哪個 f()方法,但此說明不足以讓人信服,比如可以強制要求子類必須覆寫f()方法。

Java之父,James Gosling在1995年的一份白皮書中給出了關於為什麼不支持多繼承

JAVA omits many rarely used, poorly understood, confusing features of C++ that in our experience bring more grief than benefit. This primarily consists of operator overloading (although it does have method overloading), multiple inheritance, and extensive automatic coercions.

主要就是說,Gosling認為,多繼承是一種很少使用,並且很容易混淆的特性,所以Java語言就像刪除操作符重載特性一樣刪除了多繼承這種特性。

也就是說java為了便於程式設計師理解和使用,去除了一些不容易理解的特性,例如類的多繼承。並非不能實現。

那為什麼接口可以呢?

針對於Diamond(鑽石)問題,接口由於本身都是抽象方法,繼承誰都無所謂,都是需要其實現類去實現的,故不存在此問題。

此時有人問了,jdk1.8以後,java接口被賦予了一個新的功能,可以通過default關鍵字定義非抽象方法,那如果出現一個接口繼承的父接口有相同的非抽象方法怎麼辦呢?

下面我們看看jdk1.8中如何處理

public interface Aservice { void say(); default void bye(){ System.out.println(&34;); }}public interface Bservice { void say(); default void bye(){ System.out.println(&34;); }}

此時我們定義接口去繼承,如下圖,發現被強制要求覆寫相同的非抽象方法,以保證編譯器知道具體執行哪個方法。


因此接口是可以的多繼承的,即使jdk1.8中添加了非抽象方法。

相關焦點

  • Java為什麼不支持類多繼承
    一、前言我們都知道,Java裡邊有一個特殊的特性的,就是支持類(注意是類,接口是可以多繼承的)都單繼承,那究竟是為什麼,多繼承不行嗎?有什麼原因,下面通過一個反例,來論證下。二、反證法如下圖,B、C都相同都方法 doSomething,並皆為D類所繼承。這時,D所繼承的方法中,就出現二義性問題了,即調用父類的方法 doSomething,不知道具體執行那個父類的方法。
  • 淺析java繼承與多態,抽象類與接口的區別
    二、繼承層級上面的例子只講了一層繼承關係,當然也可以進行多次繼承。A 繼承 B,B 繼承 C,C 繼承 D 理論上可以一直繼續,但是肯定不建議嵌套太多繼承關係,這會讓程序變得複雜且性能降低。Java 可以有多個繼承層次,一個類也可以有多條繼承鏈路,M 繼承 A,N 繼承 A。
  • java動態代理為什麼需要基於接口
    那麼jdk的動態代理為什麼要基於接口呢?那麼問題來了,jdk動態代理要求代理類實現InvocationHandler接口,重寫invoke方法就可以實現動態代理,且構造函數注入Object即可,並無要求Object必須基於接口,而且重本質上說getProxy()獲取代理類(Object的原類),完全可以通過繼承對象的方式。
  • jdk動態代理為什麼要使用接口,而不是使用繼承
    最近面試當時問到了Spring AOP的實現方式,然後就問到了jdk動態代理為什麼使用接口而不是使用繼承,當時一時沒轉過彎來,後來自己回來看了一下原來如此,面試有時就是這樣問題不難,但就是可能想不到這個點去回答。
  • Java為什麼要使用接口_java接口怎麼使用
    另外,在Java中,接口類型可用來宣告一個變量,他們可以成為一個空指針,或是被綁定在一個以此接口實現的對象。   其中一個使用接口的優勢是,可以利用他們模擬多重繼承,類在JAVA中不允許多重繼承,所有在JAVA中的類必須而且僅能有一個父類,而java.lang.Object(JAVA類型系統中最頂層的類型)是唯一一個例外。
  • Java抽象類與接口的區別
    如果一個類實現了某個接口,那麼它就繼承了這個接口的抽象方法。這就像契約模式,如果實現了這個接口,那麼就必須確保使用這些方法。接口只是一種形式,接口自身不能做任何事情。它根本不存在方法的實現實現子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有聲明的方法的實現。子類使用關鍵字implements來實現接口。
  • Java接口的作用與意義
    ,所以類的特徵也同樣適用於接口:一個java文件中可以定義多個接口,但是最多只能有一個公開接口公開接口的接口名必須和java文件的文件名完全相同一個接口編譯後會生成一個class文件2.類與接口的關係定義一個實現類實現AI接口,因為接口中都是抽象方法,所以在implements時需要實現抽象方法
  • Java之接口之間的多繼承
    各位小夥伴們大家好,這次小編要介紹的是Java當中,接口的多繼承。具體如下:1.類與類之間是單繼承的,直接父類只有一個。2.類與接口之間是多實現的,一個類可以實現多個接口。3.接口與接口之間是多繼承的。注意事項:1.多個父接口之間的抽象方法可以重複。
  • Java面向對象之繼承
    為什麼要使用繼承?在java中類與類之間的關係只允許單繼承,不允許多繼承,也就是說一個類它只能有一個之間的父類,不能出現一個類直接同時繼承於多個父類,就像這樣 【class Employee extends
  • Java學習(十一): 抽象類和接口
    一個類實現多個接口時,若接口有默認方法,不能出現同名的默認方法接口可以繼承多個接口(以前接口不行)都可以不需要實現類或者繼承者去實現所有方法。抽象類不可以多重繼承,接口可以(無論是多重類型繼承還是多重行為繼承)
  • Java類與類之間的繼承關係
    對於面向對象的程序設計語言來說,類毫無疑問是其最重要的基礎。抽象、封裝、繼承、多態這四大特性都離不開類,只有存在類,才能體現面向對象編程的特點,今天我們就來了解一些類與繼承的相關知識。首先,我們講述一下與類的初始化相關的東西,然後再從幾個方面闡述繼承這一大特性。以下是本文的目錄大綱:  一.你了解類嗎?  二.你了解繼承嗎?
  • Java中的函數式接口
    什麼是函數式接口java中函數式接口中的定義如下:函數式接口(Functional Interface)就是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的接口。需要注意以下幾點:JDK1.8中接口支持默認方法,默認方法和靜態方法都不屬於抽象方法,因此,函數式接口可以包含默認方法和抽象方法;接口默認繼承java.lang.Object,如果接口顯示聲明覆蓋了Object中方法,也不算抽象方法,例如,toString(),equals()等。
  • EffectiveJava-3-類和接口
    ;複合優先於繼承繼承是實現代碼重用的有力手段,但並非永遠是最佳方案(跨包邊界的繼承,可能處於不同程式設計師的控制下,是非常危險的,父類隨著發行版本的不同可能發生變化,子類就有可能遭到破壞),例如下面代碼中所提到的問題:只有當A,B兩個類之間存在"B is A"關係,且A類本身不存在缺陷時,才應該使用繼承;要麼為繼承而設計,提供文檔說明,要麼就禁止繼承
  • Java 8 有多牛逼?打破一切你對接口的認知
    ,那所有的接口實現類都要去實現這個方法,不然就會編譯錯誤,而某些實現類根本就不需要實現這個方法也被迫要寫一個空實現,改動會非常大。,所有的實現類就自動繼承,不需要改動任何實現類,也不會影響業務,爽歪歪。
  • java封裝和繼承多態一些簡答題及答案
    8、java對標識符命名有什麼規定?9、方法的重載和方法的覆蓋有什麼不同?10、簡述在類的繼承關係中,子類可以繼承父類的哪些成員,不能繼承的有哪些成員?答案:1、從本質上講,接口是一種特殊的抽象類,然而它們又有區別: ①接口只包含常量,而抽象類則不一定。 ②接口中不能有非抽象的方法,但抽象類中可以有。 ③一個類能實現多個接口,但只能有一個父類。
  • java入門避坑必讀,通過Thread類創建java多線程
    欲善編程,多看、敲、討論;動眼、手、大腦。1 為什麼要用多線程平常我們做crud的時候,用到多線程的機會不多。但當我們要處理一些複雜的業務時,或者提高程序處理效率時,就繞不開多線程的使用。也有些時候,我們需要對某個接口進行並發測試,也可以通過多線程來做一個性能測試小程序。2 創建一個java線程類我們先創建一個ThreadDemo類,並在裡面創建一個MyThread內部類,MyThread繼承Thread類。繼承之後,MyThread就是一個線程類了,具備了線程類的所有屬性。可以被主程序反覆調用執行,不會導致主程序的堵塞。MyThread類代碼如下圖。
  • 面試官:java接口的意義,程序汪:我知道怎麼用,意義不知道
    程式設計師、編程、Java語言、後端開發、軟體開發Java疑問為什麼要使用接口interface?(好抽象的感覺)接口的作用是什麼?(人家習慣寫類)為什麼不直接在實例類中進行方法實現,而是需要首先進行接口的定義?是不是多此一舉了?
  • JAVA:接口中的靜態方法及默認方法
    01接口中的靜態方法在java中接口設計的初衷是作為抽象的規範,接口不是類,而是對類的一組需求描述。在java SE8之前,靜態方法通常都是放在工具類中,如Collecation接口對應的工具類是Collecations。
  • JavaSE基礎知識學習---抽象類和接口
    什麼叫抽象類在java中,因為繼承,使得類越來越具體化,類的設計使得父類越來越通用,在類的設計裡應該保證父類和子類能夠共享特徵,有時候就把父類設計的非常抽象,讓它沒有具體的實例。這樣的類就叫抽象類,例如人可以說話,但是不同的人可能說的話不一樣,所以讓說話的內容由子類自己決定。1.抽象類不可以被實例化,實例化應該是它的子類來完成.
  • 一篇文章快速了解Java中的抽象類,接口和內部類
    不能用abstract修飾私有方法、靜態方法、final的方法、final的類。但是可以有靜態方法,靜態方法的好處是不實例化就可由抽象類或子類類名直接調用可以定義一個抽象類的對象變量,但是他只能引用非抽象類的對象。