簡體   English   中英

Java:為什么我會收到錯誤消息“類型不匹配:無法將 int 轉換為字節”

[英]Java: why do I receive the error message "Type mismatch: cannot convert int to byte"

如果您聲明 byte 或 short 類型的變量並嘗試對它們執行算術運算,則會收到錯誤“類型不匹配:無法將 int 轉換為 short”(或相應地“類型不匹配:無法將 int 轉換為字節”)。

byte a = 23;
byte b = 34;
byte c = a + b;

在這個例子中,編譯錯誤在第三行。

盡管算術運算符被定義為可以對任何數字類型進行運算,但是根據Java語言規范(5.6.2二進制數字提升),字節和short類型的操作數在被傳遞給運算符之前會自動提升為int。

要對byte或short類型的變量執行算術運算,必須將表達式用括號括起來(在括號內將以int類型進行運算),然后將結果轉換回所需的類型。

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

這是真正的Java專家的一個后續問題:為什么? byte和short類型是完美的數字類型。 為什么Java不允許對這些類型進行直接算術運算? (答案不是“精度下降”,因為沒有明顯的理由首先將其轉換為int。)

更新:jrudolph建議此行為基於JVM中可用的操作,尤其是僅實現全字和雙字運算符。 因此,對於字節和短褲運算符,必​​須將它們轉換為int。

您的后續問題的答案在這里:

byte和short類型的操作數在交給操作員之前會自動提升為int

因此,在您的示例中,將ab都轉換為int然后再交給+運算符。 將兩個int相加的結果也是int 然后嘗試將int分配給byte值會導致錯誤,因為可能會丟失精度。 通過顯式轉換結果,您將告訴編譯器“我知道我在做什么”。

我認為問題是,JVM僅支持兩種類型的堆棧值:字大小和雙字大小。

然后,他們可能決定只需要一個對堆棧上字長的整數進行運算的操作。 因此,在字節碼級別只有iadd,imul等(並且沒有用於字節和短褲的運算符)。

因此,您將得到一個int值,這些操作是Java無法安全地轉換回較小字節和short數據類型的結果。 因此,它們迫使您強制將值縮小到字節/短。

但是最后您是對的:例如,此行為與int的行為不一致。 您可以毫無疑問地添加兩個整數,並且如果結果溢出也不會出錯。

Java語言始終將算術運算符的參數提升為int,long,float或double。 因此,采用以下表達式:

a + b

其中a和b是字節類型。 這是以下內容的簡寫:

(int)a + (int)b

此表達式的類型為int。 將int值分配給字節變量時,給出錯誤顯然很有意義。

為什么要用這種方式定義語言? 假設a為60而b為70,則a + b為-126-整數溢出。 作為可能導致int的更復雜表達式的一部分,這可能會成為一個困難的錯誤。 限制使用字節和數組存儲的簡短形式,文件格式/網絡協議和拼圖的常量。

JavaPolis 2007上有一個有趣的記錄。JamesGosling給出了一個例子,說明無符號算術有多么復雜(以及為什么Java中沒有它)。 喬什·布洛赫(Josh Bloch)指出,他的例子在正常的有符號算術下也給出了錯誤的例子。 對於可理解的算法,我們需要任意精度。

在 Java 語言規范(5.6.2 二進制數字提升)中:

1 如果任何表達式為 double 類型,則提升的類型為 double,其他非 double 類型的表達式經歷擴展原始轉換為 double。

2 否則,如果任何表達式是 float 類型,則提升的類型是 float,並且其他非 float 類型的表達式經歷擴展原始轉換為 float。

3 否則,如果任何表達式為 long 類型,則提升的類型為 long,並且其他非 long 類型的表達式經歷擴展原始轉換為 long。

4 否則,所有表達式都不是 double、float 或 long 類型。 在這種情況下,提升的類型是 int,並且任何不是 int 類型的表達式都會經歷擴展原始轉換為 int。

您的代碼屬於案例 4。變量ab在交給+運算符之前都轉換為int +操作的結果也是int類型而不是byte

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM