孫悟空的七十二變是那般?–java類型的七十二變揭秘

  • 2019 年 10 月 5 日
  • 筆記

故事背景

  在《西遊記》原著第六回,孫悟空大鬧天宮反下界,玉帝派十萬天兵圍剿,卻被打得落花流水。玉帝不得不放下架子,請自己外甥二郎神回來支援。孫悟空與二郎神本事差不多,兩人斗得不分勝負,但二郎神有梅山六兄弟助陣,而孫的陣營只是烏合之眾。兩人戰鬥正酣時,孫悟空聞後方陣營攻破,猴子被打散,心中發慌敗下陣來。

孫悟空的七十二變是那般?--java類型的七十二變揭秘

 

  為了逃脫梅山六兄弟的圍追堵截,孫悟空搖身一變,變作一個麻雀,飛在樹桃頭釘住。這個變化太low了,二郎神一眼就識破假象,立即變成餓鷹撲了過來。孫悟空只得又變成大鶿老衝天而起,二郎神則變成大海鶴,鑽上雲宵來嗛……

孫悟空的七十二變是那般?--java類型的七十二變揭秘

 

  幾經鬥法,孫悟空最後變成一座土地廟,牙齒作門扇,舌頭變菩薩,眼睛變窗欞,但尾巴卻不好收拾,只得豎在後面,變成一根旗竿。這個變化迷惑性很大,一般神仙還真看不破。不料二郎神趕到,見一根旗竿立在後面,頓時笑了:“是這猢猻了!他今又在那裡哄我。我也曾見廟宇,更不曾見一個旗竿豎在後面的。斷是這畜生弄誼!他若哄我進去,他便一口咬住。我怎肯進去?等我掣拳先搗窗欞,後踢門扇!”孫悟空一聽,媽媽呀,這二郎神好狠!“門扇是我牙齒,窗欞是我眼睛;若打了牙,搗了眼,卻怎麼是好?”於是趕緊收了法相,逃命去了。

孫悟空的七十二變是那般?--java類型的七十二變揭秘

 

  這七十二變的最大缺陷是:若是變飛禽、走獸、花木、器皿、昆蟲之類,可以連身子一起變;但如果變人物,卻只是頭臉變了,身子變不過來,還有一身黃毛,兩塊紅股,一條尾巴。原因:七十二變化本身就是人研製出來的,也是為人量身打造的,故孫悟空學會後會存在缺陷。

java中的七十二變

我們看一下,java的七十二般變化吧!

public class Multicast{  public static void main (String[] args){  System.out.println((int)(char)(byte) -1);  }  }

上面的程式以int 數值-1 開始,然後從int轉型為byte,之後轉型為char,最後轉型回int。第一個轉型將數值從32 位窄化到了8 位,第二個轉型將數值從8 位拓寬到了16 位,最後一個轉型又將數值從16 位拓寬回了32 位。這個數值最終是回到了起點嗎?

是不是想起了《看我七十二變》:

  看我七十二變

  今天新鮮改變再見

  美麗極限愛漂亮沒有終點

  追求完美的境界

  人不愛美天誅地滅

  彆氣餒舊觀念拋到一邊

  現在就開始改變

  麻雀也能飛上青天

運行看結果吧

65535

為什麼會這樣呢?我們將程式一步步分開來看:

    public static void main (String[] args){          int i=-1;          byte b=(byte)-1; //1          char c=(char)b; //2          int r=(int)c; //3          System.out.println(r);          }

第一步:int轉byte

  byte b=-1 窄化後沒有改變值

第二步:byte轉char

  從byte 到char 的轉型稍微麻煩一點,因為byte 是一個有符號類型,而char是一個無符號類型。在將一個整數類型轉換成另一個寬度更寬的整數類型時,通常是可以保持其數值的,但是卻不可能將一個負的byte 數值表示成一個char。因此,從byte 到char 的轉換被認為不是一個拓寬原始類型的轉換,而是一個拓寬並窄化原始類型的轉換(widening and narrowing primitive conversion):byte 被轉換成了int,而這個int 又被轉換成了char

char c=65535//符號擴展

第三步:char轉int

  int r=65535//零擴展

因為byte 是一個有符號的類型,所以在將byte 數值-1 轉換成char 時,會發生符號擴展。作為結果的char 數值的16 個位就都被置位了,因此它等於2的16次方-1,即65535。

從char 到int 的轉型也是一個拓寬原始類型轉換,它將執行零擴展而不是符號擴展。作為結果的int 數值也就成了65535,

這正是程式列印出的結果。

深入:java如何七十二變?

jls-5強制類型轉換,定義標識如下:

– 表示不運行任何強制類型轉換

≈ 表示標識抓獲(§5.1.1)

ω 表示拓寬基本類型轉換 (§5.1.2)

η 表示窄化基本類型轉換 (§5.1.3)

ωη 表示拓寬和窄化類型轉換 (§5.1.4)

⇑ 表示拓寬引用類型轉換 (§5.1.5)

⇓ 表示窄化引用類型轉換(§5.1.6)

⊕ 表示裝箱轉換 (§5.1.7)

⊗表示拆卸類型轉換 (§5.1.8)

孫悟空的七十二變是那般?--java類型的七十二變揭秘

到基本類型的強制類型轉換

孫悟空的七十二變是那般?--java類型的七十二變揭秘

到引用類型的強制類型轉換

更詳細的資料請參照JSL5描述,鏈接地址見參考資料【3】

參考資料

【1】https://baike.baidu.com/tashuo/browse/content?id=1275b5b5f23ff153017f164c&fr=qingtian&lemmaId=11061

【2】https://baike.baidu.com/item/%E4%B8%83%E5%8D%81%E4%BA%8C%E5%8F%98/11061?fr=aladdin#2_2

【3】https://docs.oracle.com/javase/specs/jls/se12/html/jls-5.html

【4】java解惑