日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java 8 默認方法和多繼承深入解析

以前經(jīng)常談論的Java對比c++的一個優(yōu)勢是Java中沒有多繼承的問題。 因為Java中子類只能繼承(extends)單個父類, 盡管可以實現(xiàn)(implements)多個接口,但是接口中只有抽象方法,方法體是空的,沒有具體的方法實現(xiàn),不會有方法沖突的問題。

創(chuàng)新互聯(lián)建站長期為上千多家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為泰州企業(yè)提供專業(yè)的成都網(wǎng)站建設、網(wǎng)站制作,泰州網(wǎng)站改版等技術服務。擁有十載豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

這些都是久遠的說法了,自從今年Java 8發(fā)布后, 接口中也可以定義方法了(default method)。 之所以打破以前的設計在接口中
增加具體的方法, 是為了既有的成千上萬的Java類庫的類增加新的功能, 且不必對這些類重新進行設計。 比如, 只需在Collection接口中
增加default Stream stream(), 相應的SetList接口以及它們的子類都包含此的方法, 不必為每個子類都重新copy這個方法。

這是一個折衷的設計,帶來的問題就是為Java引入了多繼承的問題。 我們知道, 接口可以繼承接口, 類可以繼承類和實現(xiàn)接口。 一旦繼承的類和實現(xiàn)的接口中有相同簽名的方法, 會出現(xiàn)什么樣的狀況呢? 本文將探討各種情況的多繼承, 以便能清楚的理解Java多繼承的規(guī)則。

接口繼承多個父接口

假定有三個接口Interface A, Interface B, Interface C, 繼承關系如下:

 
 
  1. +---------------+         +------------+ 
  2. |  Interface A  |         |Interface B | 
  3. +-----------^---+         +---^--------+ 
  4.             |                 |         
  5.             |                 |         
  6.             |                 |         
  7.             +-+------------+--+         
  8.               | Interface C|            
  9.               +------------+ 

A,B擁有相同簽名的默認方法default String say(String name), 如果接口C沒有override這個方法, 則編譯出錯。

 
 
  1.  interface A { 
  2. default String say(String name) { 
  3.   return "hello " + name; 
  4. interface B { 
  5. default String say(String name) { 
  6.   return "hi " + name; 
  7. interface C extends A,B{ 
  8.  

錯誤信息:

 
 
  1. C:/Lambda/src>javac -J-Duser.country=US com/colobu/lambda/chap 
  2. ter3/MultipleInheritance1.java 
  3. com/colobu/lambda/chapter3/MultipleInheritance1.java:17: error: interface C inherits unrelated defaults for say(String) from types A and B 
  4.         static interface C extends A,B{ 
  5.                ^ 
  6. 1 error 

我們可以在子接口C中覆蓋override這個方法, 這樣編譯就不會出錯了:

 
 
  1. interface C extends A,B{ 
  2. default String say(String name) { 
  3.   return "greet " + name; 

注意方法簽名不包括方法的返回值, 也就是僅僅返回值不同的兩個方法的簽名也是相同的。下面的代碼編譯不會出錯,因為AB的默認方法不同, C隱式繼承了兩個默認方法。

 
 
  1. interface A { 
  2. default void say(int name) { 
  3.  
  4. interface B { 
  5. default void say(String name) { 
  6.  
  7. interface C extends A,B{ 
  8.  

但是有的情況下即使是不同簽名的方法也是很難分辨的:

 
 
  1. interface A { 
  2. default void say(int a) { 
  3.   System.out.println("A"); 
  4. interface B { 
  5. default void say(short a) { 
  6.   System.out.println("B"); 
  7. interface C extends A,B{ 
  8.  
  9. static class D implements C { 
  10.  
  11. public static void main(String[] args) { 
  12. D d = new D(); 
  13. byte a = 1; 
  14. d.say(a); //B 

Java會選擇最適合的方法, 請參看Java規(guī)范 15.12.2.5

接口多層繼承

下面看一下多層繼承的問題。 繼承關系如下圖, A2繼承A1, C繼承A2。

 
 
  1. +---------------+ 
  2. |  Interface A1 | 
  3. +--------+------+ 
  4.          |        
  5.          |        
  6.          |        
  7. +--------+------+ 
  8. |  Interface A2 | 
  9. +-------+-------+ 
  10.         |         
  11.         |         
  12.         |         
  13. +-------+--------+ 
  14. |   Interface C  | 
  15. +----------------+ 

基于我們以前對類繼承的認識, 很容易知道C會繼承A2的默認方法,包括直接定義的默認方法, 覆蓋的默認方法,以及隱式繼承于A1接口的默認方法。

 
 
  1. interface A { 
  2. default void say(int a) { 
  3.   System.out.println("A"); 
  4.  
  5. default void run() { 
  6.   System.out.println("A.run"); 
  7. interface B extends A{ 
  8. default void say(int a) { 
  9.   System.out.println("B"); 
  10.  
  11. default void play() { 
  12.   System.out.println("B.play"); 
  13. interface C extends A,B{ 
  14.  

多層多繼承

上面一個例子還是單繼承的例子, 如果如下圖的多繼承呢?

 
 
  1. 10 
  2. 11 
  3. 12 
  4. 13 
  5. 14 
  6. 15 
  7. +---------------+                          
  8. |  Interface A1 |                          
  9. +--------+------+                          
  10.          |                                 
  11.          |                                 
  12.          |                                 
  13. +--------+------+         +---------------+ 
  14. |  Interface A2 |         |  Interface B  | 
  15. +-------+-------+         +---------+-----+ 
  16.         |       +---------+---------^      
  17.         |       |                          
  18.         |       |                          
  19. +-------+-------++                         
  20. |   Interface C  |                         
  21. +----------------+ 

如果A2和B擁有相同簽名的方法,這和***個例子一樣。 如果不想編譯出錯,可以覆蓋父接口的默認方法,還可以調(diào)用指定父接口的默認方法:

 
 
  1. interface A1 { 
  2.   default void say(int a) { 
  3.    System.out.println("A1"); 
  4.   } 
  5.  
  6. interface A2 extends A1 { 
  7.  
  8.  
  9. interface B { 
  10.   default void say(int a) { 
  11.    System.out.println("B"); 
  12.   } 
  13. interface C extends A2,B{ 
  14.   default void say(int a) { 
  15.    B.super.say(a); 
  16.   } 

更復雜的多層多繼承

 
 
  1. +--------------+              
  2. | Interface A1 |              
  3. +------+------++              
  4.         |      ^+-------+      
  5.         |               |      
  6. +-------+-------+       |      
  7. |  Interface A2 |       |      
  8. +------------+--+       |      
  9.              ^--++      |      
  10.                  |      |      
  11.               +--+------+-----+ 
  12.               |  Interface C  | 
  13.               +---------------+ 

接口A2繼承A1, 接口C繼承A2和A1。 代碼如下,

 
 
  1. interface A1 { 
  2. default void say() { 
  3.   System.out.println("A1"); 
  4. interface A2 extends A1 { 
  5. default void say() { 
  6.   System.out.println("A2"); 
  7. interface C extends A2,A1{ 
  8.  
  9. static class D implements C { 
  10.  
  11. public static void main(String[] args) { 
  12. D d = new D(); 
  13. d.say(); 

以上代碼不會編譯出錯,運行輸出A2

可以看到接口C會隱式繼承子接口的方法, 也就是子接口A2的默認方法。

類繼承

如果繼承關系類型全部是類, 那么由于類依然是單繼承的, 不會有多繼承的問題。

類和接口混雜

我們把***個例子中的其中一個接口換成類,會出現(xiàn)什么現(xiàn)象呢。

 
 
  1. +-------------+       +-----------+ 
  2. | Interface A |       |  Class B  | 
  3. +-----------+-+       +-----+-----+ 
  4.             ^-+    +--+-----^      
  5.               |    |               
  6.           +---+----+-+             
  7.           |  Class C |             
  8.           +----------+ 

以下代碼不會編譯出錯:

 
 
  1. interface A { 
  2. default void say() { 
  3.   System.out.println("A"); 
  4. static class B { 
  5. public void say() { 
  6.   System.out.println("B"); 
  7. static class C extends B implements A{ 
  8.  
  9. public static void main(String[] args) { 
  10. C c = new C(); 
  11. c.say(); //B 

結果輸出B。

可以看出, 子類優(yōu)先繼承父類的方法, 如果父類沒有相同簽名的方法,才繼承接口的默認方法。

結論

更復雜的繼承關系可以簡化成以上的繼承關系。
根據(jù)以上的例子, 可以得出以下的結論:

  • 類優(yōu)先于接口。 如果一個子類繼承的父類和接口有相同的方法實現(xiàn)。 那么子類繼承父類的方法

  • 子類型中的方法優(yōu)先于父類型中的方法。

  • 如果以上條件都不滿足, 則必須顯示覆蓋/實現(xiàn)其方法,或者聲明成abstract。


新聞標題:Java 8 默認方法和多繼承深入解析
URL鏈接:http://m.5511xx.com/article/cooschh.html