黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 告訴你在java中為什么要慎重使用繼承

告訴你在java中為什么要慎重使用繼承

更新時間:2019-09-18 10:43:04 來源:動力節點 瀏覽2528次

  

Java繼承是面向對象的最顯著的一個特征,今天動力節點java培訓機構小編告訴大家在java中為什么要慎重使用繼承,本文主要通過示例代碼介紹,希望通過此文大家能夠在使用java繼續時慎重選擇,避開可能遇到的坑。下面就隨小編一起來了解一下java中為什么要慎重使用繼承?


u=4195299513,2392537383&fm=11&gp=0.jpg


  JAVA中使用到繼承就會有兩個無法回避的缺點:


  (1)打破了封裝性,子類依賴于超類的實現細節,和超類耦合。


  (2)超類更新后可能會導致錯誤。


  繼承打破了封裝性


  關于這一點,下面是一個詳細的例子:


public class MyHashSet<E> extends HashSet<E> {

 private int addCount = 0;

 

 public int getAddCount() {

  return addCount;

 }

 

 @Override

 public boolean add(E e) {

  addCount++;

  return super.add(e);

 }

 

 @Override

 public boolean addAll(Collection<? extends E> c) {

  addCount += c.size();

  return super.addAll(c);

 }

}


  這里自定義了一個HashSet,重寫了兩個方法,它和超類唯一的區別是加入了一個計數器,用來統計添加過多少個元素。


  寫一個測試來測試這個新增的功能是否工作:


public class MyHashSetTest {

 private MyHashSet<Integer> myHashSet = new MyHashSet<Integer>();

 

 @Test

 public void test() {

  myHashSet.addAll(Arrays.asList(1,2,3));

   

  System.out.println(myHashSet.getAddCount());

 }

}


  運行后會發現,加入了3個元素之后,計數器輸出的值是6。


  進入到超類中的addAll()方法就會發現出錯的原因:它內部調用的是add()方法。所以在這個測試里,進入子類的addAll()方法時,數器加3,然后調用超類的addAll(),超類的addAll()又會調用子類的add()三次,這時計數器又會再加三。



  問題的根源


  將這種情況抽象一下,可以發現出錯是因為超類的可覆蓋的方法存在自用性(即超類里可覆蓋的方法調用了別的可覆蓋的方法),這時候如果子類覆蓋了其中的一些方法,就可能導致錯誤。


1568773743488424.png

  比如上圖這種情況,Father類里有可覆蓋的方法A和方法B,并且A調用了B。子類Son重寫了方法B,這時候如果子類調用繼承來的方法A,那么方法A調用的就不再是Father.B(),而是子類中的方法Son.B()。如果程序的正確性依賴于Father.B()中的一些操作,而Son.B()重寫了這些操作,那么就很可能導致錯誤產生。


  關鍵在于,子類的寫法很可能從表面上看來沒有問題,但是卻會出錯,這就迫使開發者去了解超類的實現細節,從而打破了面向對象的封裝性,因為封裝性是要求隱藏實現細節的。更危險的是,錯誤不一定能輕易地被測出來,如果開發者不了解超類的實現細節就進行重寫,那么可能就埋下了隱患。



  超類更新時可能產生錯誤,主要有以下幾種可能:


  1、超類更改了已有方法的簽名。會導致編譯錯誤。


  2、超類新增了方法:


  (1)和子類已有方法的簽名相同但返回類型不同,會導致編譯錯誤。


  (2)和子類的已有方法簽名相同,會導致子類無意中復寫,回到了第一種情況。


  (3)和子類無沖突,但可能會影響程序的正確性。比如子類中元素加入集合必須要滿足特定條件,這時候如果超類加入了一個無需檢測就可以直接將元素插入的方法,程序的正確性就受到了威脅。



  設計可以用來繼承的類時,應該注意:


  1、對于存在自用性的可覆蓋方法,應該用文檔精確描述調用細節。


  2、盡可能少的暴露受保護成員,否則會暴露太多實現細節。


    3、構造器不應該調用任何可覆蓋的方法。


  詳細解釋下第三點。它實際上和繼承打破了封裝性里討論的問題很相似,假設有以下代碼:


public class Father {

 public Father() {

  someMethod();

 }

 

 public void someMethod() {

 }

}


public class Son extends Father {

 private Date date;

 

 public Son() {

  this.date = new Date();

 }

 

 @Override

 public void someMethod() {

  System.out.println("Time = " + date.getTime());

 }

}


  上述代碼在運行測試時就會拋出NullPointerException :


public class SonTest {

 private Son  son = new Son();

 

 @Test

 public void test() {

  son.someMethod();

 }

}


  因為超類的構造函數會在子類的構造函數之前先運行,這里超類的構造函數對someMethod()有依賴,同時someMethod()被重寫,所以超類的構造函數里調用到的將是Son.someMethod(),而這時候子類還沒被初始化,于是在運行到date.getTime()時便拋出了空指針異常。


  因此,如果在超類的構造函數里對可覆蓋的方法有依賴,那么在繼承時就可能會出錯。



  結論


  繼承有很多優點,但使用繼承時應該慎重并多加考慮。同樣用來實現代碼復用的還有復合,如果使用繼承和復合皆可(這是前提),那么應該優先使用復合,因為復合可以保持超類對實現細節的屏蔽,上述關于繼承的缺點都可以用復合來避免。這也是所謂的復合優先于繼承。


  如果使用繼承,那么應該留意重寫超類中存在自用性的可覆蓋方法可能會出錯,即使不進行重寫,超類更新時也可能會引入錯誤。同時也應該精心設計超類,對任何相互調用的可覆蓋方法提供詳細文檔。


u=413209375,3586319870&fm=11&gp=0.jpg


以上就是動力節點java培訓機構小編介紹的“在java中為什么要慎重使用繼承”的內容,希望對大家有幫助,更多java最新資訊請繼續關注動力節點java培訓機構官網,每天會有精彩內容分享與你。


相關免費視頻教程推薦


JAVA繼承視頻教程下載——為什么使用繼承:http://www.ilovecolors.com.cn/xiazai/2616.html


提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 涩涩涩丁香色婷五月网视色 | 色婷婷综合久久久中文字幕 | 一区二区在线看 | 午夜影院污 | 高清成人综合 | 欧美色碰碰碰免费观看长视频 | 欧美福利 | 国产精品欧美亚洲 | 综合五月网 | 香蕉视频a级片 | 欧美成人性生活片 | 国产欧美日韩视频在线观看 | 国产精品亚洲一区二区在线观看 | 久久久亚洲欧洲日产国码二区 | 天堂中文在线乱码 | 国产女人的一级毛片视频 | 国产精品果贷一区二区借贷宝 | 国产又黄又湿又刺激不卡网站 | 欧美日韩影院 | 日本一本在线视频 | 欧美日本一区二区三区道 | 一本大道道无香蕉综合在线 | 天天好逼365| 小黄视频网站 | 欧美日韩亚洲国产 | 亚洲爱视频| 特级全黄一级毛片免费 | yiren22亚洲综合高清一区 | 特黄特黄aaaa级毛片免费看 | 97国产在线观看 | 亚洲欧美在线中文字幕不卡 | 视频精品一区二区三区 | 直接观看黄网站免费视频 | 国产成人免费手机在线观看视频 | 怡春院在线观看 | 天天射美女| 99中文字幕在线 | 欧美一级日韩在线观看 | 久久精品国产一区二区三区日韩 | 国产综合视频在线观看一区 | 又粗又黄又猛又爽大片免费 |