中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

你不知道Java的10件事

2018-07-20    來源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬Linux鏡像隨意使用

  你從一開始就在使用Java嗎?你是否還記得java被稱作為”Oak”的時(shí)期?那時(shí),面向?qū)ο笕匀皇且粋(gè)熱門的話題,使用C++的人們都認(rèn)為Java沒有任何機(jī)會(huì),Applets 也只是一件事情。

  我敢打賭你肯定不知道以下一半的事情,F(xiàn)在,讓我們開始一些Java內(nèi)部運(yùn)作的大驚喜。

  1. 并沒有所謂的檢查異常

  沒錯(cuò),Java虛擬機(jī)(JVM)不知道異常,只有Java語言自己知道.

  如今,每個(gè)人都同意檢查異常是一個(gè)錯(cuò)誤。正如Bruce Eckel 在Prague的 GeeCON 閉幕詞上所說,在Java之后沒有其他語言會(huì)約定使用檢查異常,甚至 Java 8  新的流API都不再包含這些(在lambdas表達(dá)式中使用IO 或者JDBC時(shí),是有點(diǎn)痛苦)。

 。ㄗg者注:Java8 引入了lambads表達(dá)式,使用它能夠使設(shè)計(jì)代碼更簡(jiǎn)潔)

  使用下面的代碼可以證明JVM并不知道這些:

  上面的代碼不僅能通過編譯,而且拋出了異常SQLException,你甚至不需要使用Lombok’s 的注解@SneakyThrows。

 。ㄗg者注:Lombok是一個(gè)使用注解簡(jiǎn)化Java代碼的庫)

  (譯者注:如果你在方法中沒有聲明throws子句,當(dāng)程序出現(xiàn)異常時(shí)Lomok 注解@SneakyThrows 會(huì)偷偷的拋出檢查異常)點(diǎn)這里獲取關(guān)于這篇文章的更多細(xì)節(jié),或 Stack Overflow。

  2. 重載僅返回類型不同的方法

  這不能通過編譯,不是嗎?

  是的。Java語言不允許在同一個(gè)類中存在"等價(jià)覆蓋" 的兩個(gè)方法.不管它們有不同的 throws 子句或是不同的返回類型。

  在 Javadoc  Class.getMethod(String,Class...)。上面有如下說明:

  注意:它在一個(gè)類中可能會(huì)匹配到多個(gè)方法,雖然Java語言禁止在一個(gè)類中聲明多個(gè)簽名相同而僅返回類型不同的方法,但是Java虛擬機(jī)不會(huì)如此。在Java虛擬機(jī)中,這種增強(qiáng) 的靈活性被用于實(shí)現(xiàn)多樣的語言特性。例如,協(xié)變返回值類型能通過橋接方法實(shí)現(xiàn);橋接方法和被覆蓋的方法將有相同的簽名,不同的返回類型。

  這很有意義,事實(shí)上,下面的語句所發(fā)生的幾乎就是這樣。

  查看生成的字節(jié)碼:

  因此,很好理解 T 在字節(jié)碼中就是一個(gè)對(duì)象。

  這個(gè)合成的橋接方法實(shí)際上是由編譯器生成的,因?yàn)镻arent.x()的返回類型簽名在某些調(diào)用位置可能會(huì)被期望成 Object。

  加入的泛型沒有這樣的橋接方法就不可能以一種二進(jìn)制的方式兼容。

  因此,改變JVM去支持這種特性只需很少的代價(jià)(同樣也允許協(xié)變性壓倒一切負(fù)效應(yīng))很聰明,不是嗎?

  你分析過語言的細(xì)節(jié)和內(nèi)幕嗎?點(diǎn)這里發(fā)現(xiàn)更多有趣的細(xì)節(jié)。

  3. 這些都是二維數(shù)組

  這是真的。你可能無法立刻理解上面方法的返回類型,但它們都是一樣的。類似于下面的方法:

  你肯定認(rèn)為這瘋了。想象一下,為上面的方法使用 JSR-308 / Java 8 的類型注解。句法的數(shù)量將會(huì)激增。

  4. 你不明白條件表達(dá)式

  你認(rèn)為你在使用條件表達(dá)式時(shí)明白一切嗎?讓我告訴你吧,你不明白。大多數(shù)人都會(huì)認(rèn)為下面兩個(gè)代碼片段是等價(jià)的:

  真的一樣嗎?

  不一樣。我們來驗(yàn)證一下:

  程序的輸出結(jié)果為:

1.0
1

  沒錯(cuò)!條件運(yùn)算符在必要的時(shí)候?qū)?shí)現(xiàn)數(shù)據(jù)類型的提升。下面的語句將會(huì)拋出一個(gè)NullPointException。

  點(diǎn)這里獲取更多細(xì)節(jié)。

  5. 你也不明白復(fù)合賦值運(yùn)算符

  看下面的代碼:

  乍一看它們應(yīng)該是等價(jià)的,但事實(shí)上不是。見 JSL(Java語言規(guī)范):

  復(fù)合賦值表達(dá)式 E1 op= E2 與 E1 = (T)((E1) op (E2)) 是等價(jià)的,T的類型與E1相同,此外 E1僅計(jì)算一次。

  這真是太美了,我想引用Peter Lawrey's 關(guān)于堆棧溢出問題的回答:

  6. 隨機(jī)整數(shù)

  這是一個(gè)難題。不要參看解答,你能獨(dú)立的解決問題嗎?

  運(yùn)行下面的代碼:

  我有時(shí)候會(huì)得到如下輸出:

92
221
45
48
236
183
39
193
33
84

  這怎么可能?

  答案在這。通過反射覆蓋 JDK's 的 Integercache,然后使用自動(dòng)裝箱和自動(dòng)拆箱機(jī)制。

  運(yùn)行上面的代碼,你就可以得到類似的結(jié)果了。

  7. GOTO

  在Java中編寫下列語句:

  程序會(huì)編譯失敗,錯(cuò)誤信息為:

  因?yàn)間oto是一個(gè)未使用的關(guān)鍵字。

  雖然無法在源碼中直接使用 goto 但是我們可以通過 break,continue 和 標(biāo)記塊實(shí)現(xiàn)。

  字節(jié)碼的 goto;

  向前跳轉(zhuǎn):

  它的字節(jié)碼為:

  向后跳轉(zhuǎn):

  它的字節(jié)碼為:

  看,是不是出現(xiàn)了goto

  8. Java 的類型別名

  在其他語言中可以很簡(jiǎn)單的使用類型別名,例如Ceylon:

  (譯者注:Ceylon是一種新興的計(jì)算機(jī)編程語言,號(hào)稱"Java殺手",它不是Java,而是一種受Java影響的新語言。)

  以這種方式構(gòu)造的 People 可以被 Set<Person> 替換:

  在Java中,我們無法在全局范圍上定義類型別名。由于存在 class 域或方法域,

  亦可以定義。考慮兩個(gè)我們很不喜歡的命名 Integer 和 Long,為它們?nèi)(gè)簡(jiǎn)短的名稱 I 和 L:

  上面的程序中,在 TestClass 域內(nèi) 定義 Integer 別名為 I,在 x() 方法域中定義Long

  別名為 L。我們可以這樣使用上面的方法:

  顯然這種技術(shù)不值得重視。在這個(gè)例子中,Integer 和 Long 都是 final 類型,也就意味著類型 I 和 L 是有效的別名(那樣的話,程序與類型兼容性也就無緣了)。如果我們使用的不是 final 類型,那么就應(yīng)該使用泛型。

  看夠了這些無聊的把戲了吧!來點(diǎn)厲害的。

  9. 一些不可判定的關(guān)系類型

  讓我們來點(diǎn)咖啡,集中你的注意力,這可是很時(shí)髦的東西。考慮下面兩個(gè)類型:

  現(xiàn)在,你知道 C 和 D 的類型嗎?

  它們包含了遞歸,Java、lang、Enum 也是遞歸的。這兩種方式有些相似,但略有不同。

  由上面的規(guī)范可知,Enum 實(shí)際上是由一種糖衣語法實(shí)現(xiàn)的。

 。ㄗg者注:糖衣語法,指計(jì)算機(jī)語言中添加的某種語法,這種語法對(duì)語言的功能并沒有影響,但是更方便程序員使用)

  考慮到這一點(diǎn),讓我們回到先前定義的兩個(gè)類型。下列代碼能編譯成功嗎?

  很難回答,Ross Tate 有個(gè)答案,不可判定:

  嘗試在你的Eclipse中編譯上面的代碼,崩潰了吧!

  看這句話:

  有些類型關(guān)系在Java中是不可判定的。

  如果你有興趣了解這個(gè)奇怪的Java特性更多細(xì)節(jié),就讀一讀 Ross Tate的論文"Taming Wildcards in Java's Type System"(與 Alan Leung 和 Sorin Lerner 合著),或者自己思考關(guān)聯(lián)子類型多態(tài)性與泛型多態(tài)性。

  10. 交集類型

  Java有一個(gè)很獨(dú)特的特性稱作交集類型(type intersections)。你可以聲明一個(gè)泛型,它由兩個(gè)類型的交集構(gòu)成。例如:

  要使用綁定的泛型參數(shù) T 去實(shí)例化Test 類,這個(gè)參數(shù)就必須同時(shí)實(shí)現(xiàn) Serializable 和 Cloneable。例如 String 不是,而 Date 是:

  為了讓你有一個(gè)專門的交集類型,這種特性在Java8中得到了重用。如何用它呢?幾乎沒用。但是,當(dāng)你在 lambda 表達(dá)式中強(qiáng)行應(yīng)用這樣的類型時(shí),就只有此種方法可行。

  假設(shè)你在方法中使用了這種瘋狂的類型約束:

  你需要一個(gè)實(shí)現(xiàn)了Runnable 和Serializable 的對(duì)象。為了讓你可以在某些地方執(zhí)行它,或是發(fā)送它,

  Lambads 可以被序列化:

  如果一個(gè)lambda 表達(dá)式的目標(biāo)類型和所需參數(shù)是可序列化的,那么這個(gè)表達(dá)式就能序列化。

  即使這是真的,那也不會(huì)自動(dòng)的實(shí)現(xiàn)序列化標(biāo)記接口,所以你必須自己動(dòng)手。

  現(xiàn)在你有一個(gè)可序列化的,但是它不能被執(zhí)行。

  所以你必須自己加上:

  英文:DZone,譯者:黑蔥

標(biāo)簽: 代碼

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:語言們都能干什么

下一篇:趣文:編程語言偽簡(jiǎn)史