青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

chenglong7997

java重載重寫陷阱

  看《重構(注釋版)》中“封裝集合(Encapsulate Collection)”一節時,由于該重構手法對于不同的 Java 版本會有相對應不同的處理方式,于是注釋者在旁邊給出提示:Java 2 中的新 Collections API 主要是由《Java 解惑》、《Effective Java》這兩本書的作者開發改進的。我想,這可真是一個大消息,Java 類庫的開發者所寫的書一定得看,開發者肯定深入探尋過 Java 內部機制,說不定能從書中獲得未知的知識點呢。

好在我記得自己電腦里下載過《Java 解惑(中文版)》的清晰電子版,于是改變路線,看起這本書來了。真是不看不知道,一看嚇一跳!里面有 95 個 Java 謎題,一點點地看了之后,我是既慚愧又興奮,因為里面的題真的是“莫名其妙”,直白點就是:十有八九是想都想不出來的,⊙﹏⊙b…想要真正掌握 Java ,我覺得《Java 解惑》是不得不看的。大多謎題可謂是前所未見的炸彈,一不小心就 over 了。

快點切入正題,如文章標題所示,我從《Java 解惑》中似乎認識到了幾個名詞,之所以用似乎修飾,因為重載、重寫、隱藏這幾個接觸過了,而遮蔽、遮掩或許是見過但也就忘光了。就整理一下文中的一些與此相關的 Java 謎題用自己的理解描述一下吧。

重載(overload):同一個類中名字相同但參數列表不同的多個方法之間的關系。

關于重載,是我們比較熟悉的了,最常見的就是運用在類的多個構造函數中,看一下 Java 幫助文檔,就可以明白這一情況了。而在《Java 解惑》中,作者給出了下面一個謎題:

  1. public class Confusing {   
  2.       
  3.     private Confusing(Object o) {   
  4.         System.out.println("Object");   
  5.     }   
  6.       
  7.     private Confusing(double[] dArray) {   
  8.         System.out.println("double array");   
  9.     }   
  10.       
  11.     public static void main(String[] args) {   
  12.         new Confusing(null);   
  13.     }   
  14. }  

問此時 main() 中將會輸出什么?初初一看,并沒有多分析就覺得應該是輸出“Object”,雖然Java中的數組實際上也是引用類型,但畢竟Object 是所有類的最終父類,而且目前 JDK 就連參數中的基本數據類型變量也可以被自動想上轉型成包裝類而成為 Object 的子類。于是我保守一點地就認為參數 null 應該是匹配到 Object 那個重載方法去了。

可是這答案是錯的,JVM 對于重載方法的解析是這樣的:先找出方法名匹配的所有可能的方法;然后根據傳進來的形參再次篩選出可能的重載方法;最后才是在這些方法中匹配到一個最精確的一個方法。于是,上面的那個謎題就變成確定哪一個才是最精確這一點子上了。

而關于如何判斷最精確,有這樣的機制:如果某個重載方法能夠接收所有傳遞給另一個重載方法的實參類型,那么對于參數列表來看,顯然后者至少是前者的子集,當然也就更精確了。

回到謎題上來,Confusing(Object)可以接受任何傳遞給 Confusing(double[ ])的參數(任何數組引用最終能夠都是 Object 對象),因此 main() 中的 null 應該是被 JVM 匹配到 Confusing(double[ ]) 中,也就有了與我所認為的結果相反的輸出了。

小結:這個謎題表明了我們在寫重載方法時,最好是明確地區分出各個方法中的參數列表,不要讓彼此之間有互相包含、模糊不清的關系。雖然重載是為了在相同名字的方法中傳入實參,由 JVM 動態解析選擇合適的方法,但有時也很容易陷入這種方便背后所帶來的地雷區當中。其中一種可行的辦法就是,提供不同的方法名。但是構造函數的名字一定得相同的啊?

實際上,在《重構與模式》第六章中,作者用他自身的項目經驗對“創建”這一話題展開了講解,就算是構造函數,也有很好的重構手法將其清晰地區分開來,不使用重載而是用不同名稱的方法,將原本需要重載的構造函數委托給具有最大完整參數列表的私有構造函數中。又是一本經典,值得看哦…

 

重寫(override):父類中的實例方法被其子類重新實現。既然是實例方法,那就是非 static 修飾的了,否則就是 static 靜態方法了,那叫做類方法。在我看來,正是重寫這一機制的存在,才為多態機制提供了基礎。或許 implements (實現)一個 interface (接口)中所聲明的方法也能成為重寫,因為 interface 的一部分存在原因也是為了多態。

對于重寫,在《Java 解惑》中有下面這個謎題讓我明白:絕對不能在構造函數中調用可能會被子類重寫的方法。

  1. class Point {  
  2.     protected final int x, y;  
  3.     private final String name;  
  4.       
  5.     Point(int x, int y) {  
  6.         this.x = x;  
  7.         this.y = y;  
  8.         name = makeName();  
  9.     }  
  10.  
  11.     protected String makeName() {  
  12.         return "[" + x + "," + y + "]";  
  13.     }  
  14.       
  15.     public final String toString() {  
  16.         return name;  
  17.     }  
  18. }  
  19.  
  20. public class ColorPoint extends Point {  
  21.     private final String color;  
  22.       
  23.     ColorPoint(int x, int y, String color) {  
  24.         super(x, y);  
  25.         this.color = color;  
  26.     }  
  27.       
  28.     protected String makeName() {  
  29.        return super.makeName() + ":" + color;  
  30.     }  
  31.       
  32.     public static void main(String[] args) {  
  33.         System.out.println(new ColorPoint(4, 2, "purple"));  
  34.     }  

此時程序運行結果并不是我們所想的 [4,2]:purple ,而是 [4,2]:null 。為什么會這樣?看看下面用流程標號注釋過的代碼,就能理解了。

  1. class Point {  
  2.     protected final int x, y;  
  3.     private final String name;  
  4.  
  5.     Point(int x, int y) {  
  6.         this.x = x;  
  7.         this.y = y;  
  8.         name = makeName();// 3. 由于被子類重寫過的makeName()  
  9.     }  
  10.  
  11.     protected String makeName() {  
  12.         return "[" + x + "," + y + "]";  
  13.     }  
  14.       
  15.     public final String toString() {  
  16.         return name;  
  17.     }  
  18. }  
  19.  
  20. public class ColorPoint extends Point {  
  21.     private final String color;  
  22.  
  23.     ColorPoint(int x, int y, String color) {  
  24.         super(x, y); // 2. 調用Point父類構造函數  
  25.         this.color = color; // 5. 初始化 color ,可是已經太晚了...  
  26.     }  
  27.  
  28.     protected String makeName() {  
  29.         // 4. 問題來了:它在子類構造函數之前調用了  
  30.         // 而此時的 color 是 null 的啊!!!  
  31.         return super.makeName() + ":" + color;  
  32.     }  
  33.  
  34.     public static void main(String[] args) {  
  35.         // 1. 調用ColorPoint子類構造函數  
  36.         System.out.println(new ColorPoint(4, 2, "purple"));  
  37.     }  

思路很清晰了,ColorPoint 子類中的構造函數中的 this.color = color; 還未被執行到就將 null 作為 String color 的值了。正是因為這種來來回回的調用使得程序變得不正常了,在我看來,有那么一點類似于“回調”的意思。

要去除這種代碼結構的不合理,最好還是把 Point 父類構造函數中調用 makeName() 方法一句去掉,然后在 toString  中判斷并調用 makeName() 來為 name 初始化,如下:

小結:重寫對于多態固然重要,但是設計出不正確的代碼結構的話,原本想要的多態就會被扭曲甚至造成反效果。于是,絕對不要在構造函數中調用可能會被子類重寫的方法。

 好像文字太多的文章看了容易使人暈乎乎的,啰啰嗦嗦、模模糊糊地才寫了兩個詞兒,還是分開來寫吧。其實,看了一部分《Java 解惑》才明白還有好多好多 Java 里面該注意的要點。要想在適當的時候辨清各種語法上、機制上的知識點,難啊!

記得高中語文課上讀過一片抒情的散文,標題為“哦——香雪!”而我看了《Java 解惑》,想說“噢——Java!”~~~~(>_<)~~~~

總結:

1、在我們編程領域,好書真的是一大把,就看自己有沒時間、有沒策略地去吸收了;

2、有時候看好書時留意作者對其他書籍的“友情鏈接”,或者出版社推薦的相關書籍,這樣就能夠免去自己慢慢搜尋好書的過程了,O(∩_∩)O哈!

本文出自 “螞蟻” 博客,請務必保留此出處http://haolloyin.blog.51cto.com/1177454/372691

posted on 2012-04-11 13:59 Snape 閱讀(318) 評論(0)  編輯 收藏 引用 所屬分類: Java

導航

<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

統計

常用鏈接

留言簿

隨筆分類

隨筆檔案

文章分類

文章檔案

my

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精选在线| 欧美三级资源在线| 91久久精品久久国产性色也91 | 激情校园亚洲| 国产亚洲欧美色| 在线观看一区二区精品视频| 国内精品免费午夜毛片| 亚洲高清一区二区三区| 一区二区三区久久精品| 亚洲欧美成人一区二区在线电影 | 亚洲激情影视| 亚洲一级一区| 美日韩免费视频| 亚洲精品综合久久中文字幕| 亚洲欧美日韩精品久久久久| 久久一区二区三区四区| 欧美视频在线观看 亚洲欧| 国产亚洲成精品久久| 亚洲欧洲日夜超级视频| 午夜精品久久久久久久99水蜜桃 | 久久精品中文字幕一区| 欧美黄色视屏| 国产欧美一区二区三区久久| 亚洲精品久久久久久久久| 午夜国产精品视频| 亚洲人成在线观看一区二区| 先锋资源久久| 欧美色一级片| 亚洲卡通欧美制服中文| 久久亚洲精品欧美| 亚洲天堂免费在线观看视频| 免费观看在线综合| 国产一区二区三区无遮挡| 亚洲图片欧美一区| 欧美成人国产| 久久久7777| 国产日韩免费| 亚洲综合精品一区二区| 91久久久久久| 美女诱惑一区| 亚洲第一福利视频| 久久天天躁狠狠躁夜夜av| 亚洲图片在线观看| 欧美日韩在线视频首页| 亚洲欧洲日产国产网站| 另类尿喷潮videofree| 亚洲一区二区影院| 欧美日韩在线播| av成人激情| 亚洲黄色一区| 黄色工厂这里只有精品| 亚洲国产一区在线| 久久久久久久久久码影片| 国产精品免费看久久久香蕉| 亚洲网站在线| 亚洲精品极品| 欧美久久久久久久久久| 日韩视频永久免费观看| 亚洲高清免费| 欧美精品二区| 99精品国产99久久久久久福利| 亚洲国产成人tv| 欧美劲爆第一页| 中文在线不卡视频| 在线综合亚洲欧美在线视频| 欧美性开放视频| 性欧美激情精品| 欧美有码视频| 在线看国产一区| 欧美激情免费在线| 欧美激情综合在线| 亚洲欧美日本视频在线观看| 亚洲综合第一页| 国产自产精品| 欧美黑人国产人伦爽爽爽| 欧美国产精品日韩| 亚洲天堂网在线观看| 亚洲女女女同性video| 狠狠色伊人亚洲综合成人| 欧美激情一区二区在线| 欧美色道久久88综合亚洲精品| 午夜精品久久久久久久99热浪潮 | 欧美国产视频日韩| 亚洲午夜精品在线| 欧美在线亚洲在线| 91久久精品日日躁夜夜躁国产| 亚洲免费观看在线观看| 国产日韩在线一区二区三区| 欧美成人激情在线| 欧美色欧美亚洲高清在线视频| 欧美专区18| 欧美精品一区三区| 久久久久九九九九| 欧美精品久久一区二区| 欧美综合激情网| 欧美激情综合网| 久久亚洲一区| 欧美视频免费在线| 美女被久久久| 国产精品天天看| 亚洲黄色片网站| 国产永久精品大片wwwapp| 91久久精品国产91久久性色| 国产一区二区精品在线观看| 亚洲免费av网站| 尤物99国产成人精品视频| 亚洲亚洲精品在线观看 | 亚洲激情中文1区| 亚洲精品国久久99热| 一区二区电影免费观看| 国产精品扒开腿做爽爽爽软件 | 亚洲日本va午夜在线电影| 欧美精品亚洲精品| 亚洲精品美女久久7777777| 午夜精品久久久99热福利| 久久不射中文字幕| 欧美激情一区二区三区四区| 久久久亚洲高清| 亚洲免费观看高清在线观看 | 国产欧美一区二区三区久久| 亚洲福利视频二区| 国产人久久人人人人爽| 亚洲日韩视频| ●精品国产综合乱码久久久久| 一区二区三区四区五区精品视频| 亚洲承认在线| 欧美一区二区日韩一区二区| 亚洲午夜激情| 欧美日韩高清在线播放| 免费日韩精品中文字幕视频在线| 国产一区91| 翔田千里一区二区| 欧美一乱一性一交一视频| 国产精品视频免费在线观看| 一二三区精品福利视频| 亚洲视频在线一区| 欧美日韩中文字幕在线| 一区二区高清视频| 亚洲一二区在线| 国产精品久久久久久久久免费| 一区二区三区欧美在线观看| 亚洲欧美中日韩| 国产欧美日韩另类视频免费观看| 亚洲欧美综合另类中字| 久久久99久久精品女同性| 国产一区二三区| 久久久久免费视频| 欧美a级大片| 亚洲美女精品成人在线视频| 欧美日韩不卡视频| 亚洲影视在线| 久久人体大胆视频| 久久久精品一品道一区| 在线免费观看日本一区| 美女成人午夜| 99国产精品久久久久老师| 午夜在线不卡| 一区在线播放视频| 欧美激情aaaa| 亚洲专区在线| 欧美成人首页| 亚洲一区视频在线| 国产一区二区三区黄视频| 久久五月激情| a4yy欧美一区二区三区| 久久成人免费网| 91久久久久久久久久久久久| 欧美日韩在线视频一区二区| 性感少妇一区| 亚洲日本欧美| 久久久久久久999精品视频| 亚洲人成精品久久久久| 欧美午夜不卡在线观看免费 | 激情文学综合丁香| 欧美精品在线观看播放| 亚洲欧美日韩国产| 欧美高清在线精品一区| 亚洲在线观看免费| 亚洲成人自拍视频| 国产精品久久国产三级国电话系列| 西西人体一区二区| 亚洲精品国产精品乱码不99按摩| 久久国产成人| 亚洲视频在线免费观看| 亚洲国产电影| 国产一区二区电影在线观看 | 一本大道av伊人久久综合| 久久在线视频| 欧美一区二区成人6969| 中日韩高清电影网| 亚洲二区精品| 国内精品久久久久影院色 | 亚洲视频在线二区| 亚洲国产欧美一区二区三区久久 | 韩国三级在线一区| 欧美视频你懂的| 欧美激情一区二区三区四区| 久久综合给合久久狠狠色| 久久精品日产第一区二区| 亚洲欧美国内爽妇网|