問題描述
我知道在 Java 中整數文字默認是 int,所以如果我寫這樣的東西
I know that in Java Integer literals are int by default,so if I write something like this
byte byteValue = 2;
Java 自動將文字值 2(默認為 int)轉換為字節.如果我寫,同樣的事情也有效
Java auto converts the literal value 2(which is an int by default) to byte. And the same thing works if I write
byte byteValue = 4/2;
RHS 被評估為 int 并隱式轉換為字節.
The RHS is evaluated as an int and implicitly converted to a byte.
但是為什么下面兩種情況沒有發生隱式轉換呢?
int n1 = 4;
byte value = n1/2;
或在此
byte n1 = 4;
byte value = n1/2;
我知道這兩個示例的 RHS 都被評估為 int.但是為什么Java不像前兩種情況那樣將其隱式轉換為字節.是否只有在有字面量的情況下才會隱式轉換為較小的數據類型?
I know that the RHS of both these examples are evaluated as an int. But why doesn't Java convert it to a byte implicitly like it did in the first two cases.Does implicit conversion to smaller data type happen only if there are literals?
推薦答案
說明
讓我們看看你的代碼和一些修改過的例子:
Explanation
Lets take a look at your code and some modified examples:
// Example 1
byte byteValue = 2;
// Example 2
byte byteValue = 4/2;
// Example 3
byte byteValue = 2000;
// Example 4
byte byteValue = 500/2;
// Example 5
int n1 = 4;
byte byteValue = n1/2;
無損轉換
示例 3、示例 4 和 示例 5 會出現上述編譯時錯誤.
Non-lossy conversion
You will get the mentioned compile-time error for Example 3, Example 4 and Example 5.
首先,示例 1 到 4 的簡單數學運算是在編譯時執行的.因此 Java 將在編譯時計算 500/2
并將代碼替換為基本上 byte byteValue = 250;
.
First of all, the simple math you have for Example 1 to 4 is executed at compile-time. So Java will compute 500 / 2
at compile-time and replace the code with basically byte byteValue = 250;
.
Java 中字節的有效值為 -128
到 127
.因此,任何超出該范圍的值都不能僅被視為 byte
,而是需要顯式轉換.因此,示例 1 和 示例 2 通過.
Valid values for bytes in Java are -128
to 127
. So any value outside of that range can not just be taken as a byte
but requires explicit conversion. Because of that, Example 1 and Example 2 pass.
要了解其余部分失敗的原因,我們必須研究 Java 語言規范 (JLS),更具體的章節 5.1.3.縮小原始轉換范圍和5.2.分配上下文.
To understand why the rest fails, we have to study the Java Language Specification (JLS), more specifically chapter 5.1.3. Narrowing Primitive Conversion and 5.2. Assignment Contexts.
它表示從 int
到 byte
的轉換(如果它超出 byte
的范圍)是一個縮小原始轉換,并且它可能會丟失信息(原因很明顯).它繼續解釋轉換是如何完成的:
It says that a conversion from int
to byte
(if it is outside of the range of byte
) is a narrowing primitive conversion and that it may lose information (for obvious reasons). It continues by explaining how the conversion is done:
有符號整數到整數類型 T 的窄化轉換只會丟棄除 n 個最低位之外的所有位,其中 n 是用于表示類型 T 的位數.除了可能丟失有關數值,這可能會導致結果值的符號與輸入值的符號不同.
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
從第二章開始,如果值為常量表達式,則允許進行窄轉換的賦值.
From the second chapter, assignments with narrow conversions are allowed if the value is a constant expression.
此外,如果表達式是 byte
、short、char 或 int 類型的常量表達式(第 15.29 節):
In addition, if the expression is a constant expression (§15.29) of type
byte
, short, char, or int:
如果變量是 byte
、short 或 char 類型,并且常量表達式的值可以在變量的類型中表示,則可以使用縮小原語轉換.
A narrowing primitive conversion may be used if the variable is of type byte
, short, or char, and the value of the constant expression is representable in the type of the variable.
長話短說,可能會丟失信息(因為值超出范圍)的縮小轉換必須明確地通知 Java.Java 不會在您不強制的情況下為您完成它.這是由演員完成的.
Long story short, a narrowing conversion that may lose information (because the value exceeds the range) has to explicitly be announced to Java. Java will not just do it for you without you forcing it. That is done by a cast.
例如
byte byteValue = (byte) (500 / 2);
導致值 -6
.
你的最后一個例子很有趣:
Your last example is very interesting:
int n1 = 4;
byte byteValue = n1/2;
雖然這沒有超出范圍,但Java仍然將其視為有損縮小轉換.為什么會這樣?
Although this does not exceed the range, Java still treats it as lossy narrowing conversion. Why is that the case?
好吧,Java 不能 100% 保證 n1
在執行 n1/2
之前的最后一秒沒有改變.因此,它必須考慮您的所有代碼,以查看是否有人偷偷訪問 n1
并對其進行更改.Java 不會在編譯時進行這種分析.
Well, Java can not ensure 100% that n1
is not changed last second before n1/2
is executed. Therefore, it would have to consider all of your code to see if maybe someone accesses n1
sneaky and changes it. Java does not do this kind of analysis at compile-time.
因此,如果您可以告訴Java n1
保持4
并且實際上永遠不會改變,那么這將實際編譯.在這種特定情況下,將其設為 final
就足夠了.所以與
So if you can tell Java that n1
stays 4
and can actually never change, then this will actually compile. In this specific case, it would be enough to make it final
. So with
final int n1 = 4;
byte byteValue = n1/2;
它實際上會編譯,因為 Java 知道 n1
保持 4
并且不能再更改.因此它可以在編譯時將 n1/2
計算為 2
并將代碼替換為基本上 byte byteValue = 2;
,它在范圍內.
it will actually compile because Java knows that n1
stays 4
and can not change anymore. Hence it can compute n1/2
at compile-time to 2
and replace the code with basically byte byteValue = 2;
, which is in range.
所以你把 n1/2
做成了一個常量表達式,正如之前在 5.2.分配上下文.
So you made n1 / 2
a constant expression, as explained before in 5.2. Assignment Contexts.
您可以在 15.29.常量表達式.基本上所有簡單的東西都可以輕松計算,無需任何方法調用或其他花哨的東西.
You can check the details what it needs to have a constant expression in 15.29. Constant Expressions. Basically everything simple that can easily be computed in place without any method invocations or other fancy stuff.
這篇關于Java 中的隱式轉換是如何工作的?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!