2012-10-08 115 views
8

下面的程序分別打印「假」與「真」:不需要自動裝箱魔術

Number n = true ? new Long(1) : new Double(2.0); 
System.out.println(n instanceof Long); 
System.out.println(n instanceof Double); 

所以不會是一個長期的,但一個雙。然而,它的工作如預期正常類: 有

class B {} 
class D1 extends B {} 
class D2 extends B {} 

會打印出「真」:

B b = true ? new D1() : new D2(); 
System.out.println(b instanceof D1); 

這意味着它不工作一樣像上面的例子。

我確定有一些與自動裝箱有關的東西,但它真的是它的工作方式?爲什麼她使用裝箱,當Number類是Long和Double的超類,以便可以將表達式評估爲Number?

這真的很痛苦,因爲當打印n時,它會打印爲雙值。 (我知道這是很容易的解決方法,但讓我抓狂)

+0

的':'取型最後一個表達式。如果你使它成爲'null',那將是'Long':P。 –

+0

不,它不需要最後一個表達式的類型,只需看第二個例子即可。當然,代碼僅僅是一個例子,但想象一下,真實的布爾信息在現在的'真實'站在了最前面。 – poroszd

+2

爲何選擇近距離投票?這對我來說看起來像個很好的問題。 –

回答

2

它只是 放眼字節代碼,你會看到(簡單地修改你的例子)

Number n = true ? new Long(166666) : new Double(24444.0); 
System.out.println(Boolean.toString(n instanceof Long)); 
System.out.println(Boolean.toString(n instanceof Double)); 

字節碼

_new '爪哇/郎/龍'

dup 
ldc 166666 
invokespecial 'java/lang/Long.<init>','(J)V' 
invokevirtual 'java/lang/Long.longValue','()J' 
l2d 
invokestatic 'java/lang/Double.valueOf','(D)Ljava/lang/Double;' 
astore 1 

主要點是l2d它使下一步

從堆棧中彈出一個長整數,將其轉換爲雙精度浮點數,並將雙精度值推回堆棧。 請注意,這可能會導致精度損失(雙精度型中的有效位數爲54位,與長度爲64位相比),儘管不會造成損失 (因爲雙精度的範圍大於範圍 長)。舍入是使用IEEE 754輪到模式完成的。

畢竟這是很好的,所以你必須實例,但與long值!如果你在調試模式下看看,你會看到我們的數字是雙但從長期價值,它上面描述中,字節碼

我們可以看到它在字節碼

getstatic 'java/lang/System.out','Ljava/io/PrintStream;' 
aload 1 
_instanceof 'java/lang/Long' 
invokestatic 'java/lang/Boolean.toString','(Z)Ljava/lang/String;' 
invokevirtual 'java/io/PrintStream.println','(Ljava/lang/String;)V' 
getstatic 'java/lang/System.out','Ljava/io/PrintStream;' 
aload 1 
_instanceof 'java/lang/Double' 
invokestatic 'java/lang/Boolean.toString','(Z)Ljava/lang/String;' 
invokevirtual 'java/io/PrintStream.println','(Ljava/lang/String;)V' 
return 
+0

甜,很高興知道(即使這回答如何,而不是爲什麼) 。 – poroszd