Java 類型推導(dǎo)的不確定性

本文是讀完oopsla16的一些心得

Figure 1

上面這個測試例運行的結(jié)果是茧痒,main函數(shù)中拋出一個ClassCastException,異常信息為 “java.lang.Integer cannot be cast to java.lang.String”。原因簡單說就是因為JVM運行時檢查出了類型問題谎柄,發(fā)現(xiàn)代碼企圖將一個Integer類型的對象轉(zhuǎn)化為String類型觉鼻,這種轉(zhuǎn)換是不允許的。

但是棋凳,這種類型問題本應(yīng)該是在編譯期檢查出來的拦坠。這里是什么導(dǎo)致編譯器檢查不出這個類型錯誤?

我們模擬一下Java類型推導(dǎo)的過程剩岳。類型推導(dǎo)總是先假設(shè)程序類型是對的贞滨,然后在這個前提下得出一些條件,最后驗證這些條件是否成立拍棕。用類型Z代替Constrain<U, ? super T>中的晓铆?,可以得到Figure 2中的信息绰播。

Figure 2

a)和b)是顯而易見的骄噪。c)是因為upcast函數(shù)的第一個參數(shù)的類型是Constrain<A, B>, 而這里傳入了一個合法的參數(shù)蠢箩,參數(shù)類型為Constrain<U, ? super T>链蕊。由于將U作為Bind的類型構(gòu)造符事甜,所以得到Z==B。upcast第二個參數(shù)的類型為T滔韵,而聲明的類型為B逻谦,因此得到T<:B,因為B<:A奏属,這里A已經(jīng)因為Bind<U>而變?yōu)閁跨跨,因此B<:U。

對于c), d), e)3個條件囱皿,F(xiàn)igure-1的例子中c)是滿足的勇婴,因為upcast接受了一個合法的Constrain<U, Z>類型的參數(shù)。由于c)條件滿足嘱腥,所以d)和e)也滿足了耕渴。
但是, Figure-1的正確僅僅是一個巧合齿兔。原因是Java類型推導(dǎo)驗證條件的順序是不確定的橱脸。如果順序的驗證條件c), d), e),那么條件滿足分苇。如果先驗證d),e)添诉,再驗證c),那么T<:U這個條件就不能滿足了医寿。所以不同編譯器在編譯Figure-1時結(jié)果是不同的栏赴。

不過我個人認為,造成這種類型推導(dǎo)結(jié)果不一致的原因并不能完全歸結(jié)于條件的驗證順序靖秩。如果Java像Ocaml一樣嚴格的區(qū)分Some和None须眷,那么對于Figure-1的例子,我們就不可能向upcast函數(shù)傳一個合法的Constrain<U, ? super T>類型的對象沟突。

oopsla16中還給出了一些其他例子花颗,用于說明Java類型推導(dǎo)的不一致性。

Ocaml 實現(xiàn)

type ('a, 'b) eq = Refl : ('a, 'a) eq



let cast (type a) (type b) (eq: (a, b) eq) (x : a) : b =
  match eq with
  | Refl -> x

let lies : (int, string)eq = Obj.magic 0;;

cast lies 42

上面的Ocaml也實現(xiàn)了一個與Figure-1一樣的問題的例子惠拭。執(zhí)行后內(nèi)存錯直接導(dǎo)致ocaml解釋器崩潰扩劝。不過與Java不同的是,構(gòu)造(int ,string)eq類型需要使用Obj.magic作為hack手段求橄,而Java直接使用null就可以今野。

結(jié)論

  1. Java的類型推導(dǎo)是難以捉摸的,因此使用時應(yīng)該盡可能的給出類型參數(shù)信息罐农。
  2. 強類型語言的確更安全一些。

參考文獻:
[1] Java and Scala’s Type Systems are Unsound
[2] Java's unsoundness (from an ML-ish point of view)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末催什,一起剝皮案震驚了整個濱河市涵亏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖气筋,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拆内,死亡現(xiàn)場離奇詭異,居然都是意外死亡宠默,警方通過查閱死者的電腦和手機麸恍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搀矫,“玉大人抹沪,你說我怎么就攤上這事∪壳颍” “怎么了融欧?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卦羡。 經(jīng)常有香客問我噪馏,道長,這世上最難降的妖魔是什么绿饵? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任欠肾,我火速辦了婚禮,結(jié)果婚禮上拟赊,老公的妹妹穿的比我還像新娘刺桃。我一直安慰自己,他們只是感情好要门,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布虏肾。 她就那樣靜靜地躺著,像睡著了一般欢搜。 火紅的嫁衣襯著肌膚如雪封豪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天炒瘟,我揣著相機與錄音吹埠,去河邊找鬼。 笑死疮装,一個胖子當(dāng)著我的面吹牛缘琅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播廓推,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼刷袍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了樊展?” 一聲冷哼從身側(cè)響起呻纹,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤堆生,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后雷酪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淑仆,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年哥力,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔗怠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡吩跋,死狀恐怖寞射,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钞澳,我是刑警寧澤怠惶,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站轧粟,受9級特大地震影響策治,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兰吟,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一通惫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧混蔼,春花似錦履腋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晚吞,卻和暖如春延旧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背槽地。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工迁沫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捌蚊。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓集畅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缅糟。 傳聞我的和親對象是個殘疾皇子挺智,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)窗宦,斷路器逃贝,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 《裕語言》速成開發(fā)手冊3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 10...
    葉染柒丶閱讀 26,268評論 5 19
  • “叮鈴鈴——” “啊——幾點了—嗯—” 我睜開眼睛谣辞,啊迫摔,八點了沐扳。估計現(xiàn)在去學(xué)校肯定會被老太婆罵一頓句占,不去了沪摄,請個假...
    蘇梓妤閱讀 226評論 4 5
  • 1、平平淡淡是真沒錯纱烘,只是在強勁撕裂和極度分化的社會發(fā)展進程中杨拐,你的低風(fēng)險承受和應(yīng)對的能力、你的低掌控自己命運的能...
    黑麥的光影部落閱讀 228評論 0 0