qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          Java不為人知的10個(gè)真相

          你是不是一開始就用Java來編程的呢?還記得當(dāng)年它還被稱為"Oak",OO還是熱門的話題,C++的用戶覺得Java沒有前景,applets還只是個(gè)小玩意,菊花也還是一種花的時(shí)候嗎?
            我敢打賭下面至少有一半是你不清楚的。這周我們來看一下跟Java的內(nèi)部實(shí)現(xiàn)相關(guān)的一些神奇的事情。
            1. 其實(shí)根本沒有受檢查異常這回事
            沒錯(cuò)!JVM壓根兒就不知道有這個(gè)東西,它只存在于Java語言里。
            如今大家都承認(rèn)受檢查異常就是個(gè)錯(cuò)誤。正如Bruce Eckel最近在布拉格的的GeeCON會(huì)議上所說的,除了Java外沒有別的語言會(huì)使用受檢查異常這種東西,即使是Java 8的新的Streams API中也不再使用這一異常了(不然當(dāng)你的lambda表達(dá)式中用到IO或者JDBC的話就得痛苦死了)。
            如何能證實(shí)JVM確實(shí)不知道這個(gè)異常?看下下面這段代碼:
          public class Test {
          // No throws clause here
          public static void main(String[] args) {
          doThrow(new SQLException());
          }
          static void doThrow(Exception e) {
          Test.<RuntimeException> doThrow0(e);
          }
          @SuppressWarnings("unchecked")
          static <E extends Exception>
          void doThrow0(Exception e) throws E {
          throw (E) e;
          }
          }
            這不僅能通過編譯,而且也的確會(huì)拋出SQLException異常,并且完全不需要用到Lombok的@SneakyThrows注解。
            更進(jìn)一步的分析可以看下這篇文章,或者Stack Overflow上的這個(gè)問題。
            2. 不同的返回類型也可以進(jìn)行方法重載
            這個(gè)應(yīng)該是編譯不了的吧?
            class Test {
            Object x() { return "abc"; }
            String x() { return "123"; }
            }
            是的。Java語言并不允許同一個(gè)類中出現(xiàn)兩個(gè)重寫等價(jià)("override-equivalent")的方法,不管它們的throws子句和返回類型是不是不同的。
            不過等等。看下Java文檔中的 Class.getMethod(String, Class...)是怎么說的。里面寫道:
            盡管Java語言不允許一個(gè)類中的多個(gè)相同簽名的方法返回不同的類型,但是JVM并不禁止,所以一個(gè)類中可能會(huì)存在多個(gè)相同簽名的方法。這添加了虛擬機(jī)的靈活性,可以用來實(shí)現(xiàn)許多語言特性。比如說,可以通過bridge方法來實(shí)現(xiàn)協(xié)變返回(covariant return,即虛方法可以返回子類而不一定得是基類),bridge方法和被重寫的方法擁有相同的簽名,但卻返回不同的類型。
            哇,這倒有點(diǎn)意思。事實(shí)上,下面這段代碼就會(huì)觸發(fā)這種情況:
            abstract class Parent<T> {
            abstract T x();
            }
            class Child extends Parent<String> {
            @Override
            String x() { return "abc"; }
            }
            看一下Child類所生成的字節(jié)碼:
          // Method descriptor #15 ()Ljava/lang/String;
          // Stack: 1, Locals: 1
          java.lang.String x();
          0  ldc <String "abc"> [16]
          2  areturn
          Line numbers:
          [pc: 0, line: 7]
          Local variable table:
          [pc: 0, pc: 3] local: this index: 0 type: Child
          // Method descriptor #18 ()Ljava/lang/Object;
          // Stack: 1, Locals: 1
          bridge synthetic java.lang.Object x();
          0  aload_0 [this]
          1  invokevirtual Child.x() : java.lang.String [19]
          4  areturn
          Line numbers:
          [pc: 0, line: 1
            在字節(jié)碼里T其實(shí)就是Object而已。這理解起來就容易多了。
            synthetic bridge方法是由編譯器生成的,因?yàn)樵谔囟ǖ恼{(diào)用點(diǎn)Parent.x()簽名的返回類型應(yīng)當(dāng)是Object類型。如果使用了泛型卻沒有這個(gè)bridge方法的話,代碼的二進(jìn)制形式就無法兼容了。因此,修改JVM以支持這個(gè)特性貌似更容易一些(這順便還實(shí)現(xiàn)了協(xié)變返回),看起來還挺不錯(cuò) 的吧?
            你有深入了解過Java語言的規(guī)范和內(nèi)部實(shí)現(xiàn)嗎?這里有許多很有意思的東西。

          posted on 2014-12-05 12:16 順其自然EVO 閱讀(206) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2014年12月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 隆林| 宁陕县| 定兴县| 泸州市| 二连浩特市| 德格县| 乐昌市| 资兴市| 长子县| 启东市| 郧西县| 祁东县| 伊宁市| 新和县| 仁怀市| 都江堰市| 犍为县| 咸宁市| 南乐县| 喀喇沁旗| 稷山县| 华容县| 乌海市| 错那县| 儋州市| 全椒县| 青海省| 陆川县| 灵石县| 新干县| 囊谦县| 马鞍山市| 兴仁县| 津南区| 仪征市| 星子县| 四会市| 灵山县| 资中县| 平乐县| 洪湖市|