2013-12-13 93 views
5

我在Eclipse中寫了下面的代碼:java中的位運算符只用於整數和長整型?

byte b = 10; 
/* some other operations */ 
b = ~b; 

的Eclipse想強制轉換爲字節按比特補線。它說:「類型不匹配:不能從int轉換爲字節」。我也嘗試過使用其他按位運算和其他整型。它是短而且相同。只有long和integer才能使用按位操作。

是否有什麼原因呢?

+1

也許是因爲計算機必須對至少32位長的整個寄存器執行操作? – user2573153

+0

是啊!這可能是原因。 –

回答

11

一元(如~)和二元運算它們的操作數,以"unary numeric promotion" (JLS, Section 5.6.1)"binary numeric promotion" (JLS, Section 5.6.2)分別花式的條款「促進事情至少int第一」。

具體而言,一元數值升級,引述JLS部上面鏈接:

一些運營商採用一元數值升級到一個單個操作數,其必須產生一個數字式的值:

...如果操作數是編譯時類型字節,短,或炭的,它是由一個加寬原語轉換被提升爲int類型的值(§ 5.1.2)。

(二元數值提升是相似的,在兩個操作數操作。)

所以,即使bbyte~bint,因爲b的價值被提升了一個int

解決辦法:將它轉換回一個byte

b = (byte) (~b); 

爲什麼,Java的?

這留下了問題,爲什麼?對於我能找到的操作員來說,用於在bytes,shorts和char上操作的JVM字節碼指令根本不存在。例如,您正在使用的一元位運算符(〜)is implemented as an "XOR" operation with -1 (all bits set)。從該鏈接:

tempSpock &= ~mask; 

成爲

25 iload_2 // Push local variable 2 (mask). 
26 iconst_m1 // Push -1. 
27 ixor // Bitwise EXCLUSIVE-OR top two ints: ~mask 

但是,我只能find instructions for XOR(以及其它一元和二元運算太)爲int S和long S(floatdouble版本存在其他運營商在適當情況下)。

因此,Java必須執行這些促銷活動,因爲在byte s,short s或char s上沒有用於執行這些操作的字節碼指令。

爲什麼不呢,JVM?

這引出了另一個問題:爲什麼JVM不支持這種字節碼指令?答案似乎是,「因爲在單字節指令集中編碼它們會太多。」按照JVM Specification, Section 2.11.1

鑑於Java虛擬機的一個字節的操作碼大小,編碼類型到其指令集的設計操作碼的地方壓力。如果每種類型的指令都支持所有的Java虛擬機的運行時數據類型,則將會有比指令更多的指令。相反,Java虛擬機的指令集爲某些操作提供了降低的類型支持級別。換句話說,指令集有意不是正交的。根據需要,可以使用單獨的指令在不支持和受支持的數據類型之間進行轉換。

(重點煤礦)

總之,JVM的一個字節碼指令集排除在byte S,char s和short S代表大多數操作的字節碼指令,因此需要一元數值升級和二進制數值提升。

+0

你的字節碼參數是無稽之談。如果這是由語言指定的,編譯器可以很好地添加強制轉換。舉一個例子,看看'short'是如何定義'+ ='的。 – starblue

3

是的,小於int的類型經過升級用作大多數運算符的操作數。首先將它們有效地轉換爲int。因此,在上面的代碼中,結果的類型是int。有關詳細信息,請參閱JLS的this section

至於爲什麼 Java這樣做,我不確定。但有一個可能的原因是C做到了這一點,並且保持熟悉的語義可能是語言設計目標。在Java中受試者