java为什么复制数组会减一_如果从数组中复制了Java,为什么Java需要对最终变量进行显式强制转换?...
從以下代碼開始…
byte foo = 1;
byte fooFoo = foo + foo;
當我嘗試編譯此代碼時,會得到以下錯誤…
Error:(5, 27) java: incompatible types: possible lossy conversion from int to byte
…但如果foo是最終的…
final byte foo = 1;
final byte fooFoo = foo + foo;
文件將成功編譯。
繼續執行以下代碼…
final byte[] fooArray = new byte[1];
fooArray[0] = 1;
final byte foo = fooArray[0];
fooArray[0] = 127;
System.out.println("foo is:" + foo);
…將打印
foo is: 1
…這很好。該值將被復制到最終變量,并且不能再更改。使用數組中的值不會更改EDOCX1的值(如預期的那樣…)。
為什么以下內容需要演員表?
final byte[] fooArray = new byte[1];
fooArray[0] = 1;
final byte foo = fooArray[0];
final byte fooFoo = foo + foo;
這與這個問題中的第二個例子有什么不同?為什么編譯器會給出以下錯誤?
Error:(5, 27) java: incompatible types: possible lossy conversion from int to byte
怎么會這樣?
只需注意第二個示例,即從數組初始化foo,并測試它是否不變。即使foo不是final,它的值也不會改變。賦值(在本例中是初始化)復制發生時的值(1),即該值。無論最終結果是不是,fooArray[0]到127的后續變化不會自動傳播到foo。
JLS(§5.2)對常量表達式的賦值轉換有特殊的規則:
In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:
A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
如果我們遵循上面的鏈接,我們可以在常量表達式的定義中看到:
Literals of primitive type and literals of type String
The additive operators + and -
Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).
如果我們遵循上面的第二個鏈接,我們會看到
A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.
因此,如果foo是一個常量變量,那么foo + foo只能分配給fooFoo。要將其應用于您的案例:
byte foo = 1;沒有定義常量變量,因為它不是final變量。
final byte foo = 1;確實定義了一個常量變量,因為它是final并用常量表達式(原始文本)初始化。
final byte foo = fooArray[0];沒有定義常量變量,因為它沒有用常量表達式初始化。
注意,fooFoo本身是否是final并不重要。
但最后一個問題呢:"這怎么可能發生?"(此處=從int到byte的可能有損轉換)
@實際上,在你的例子中,這是不可能發生的。但是編譯器不知道這一點;規范不允許它進行這種推斷。
值1非常適合一個字節;1+1也是如此;當變量是最終變量時,編譯器可以進行常量折疊。(換句話說:編譯器在執行+operation時不使用foo;而是使用"raw"1值)
但是當變量不是最終變量時,所有關于轉換和升級的有趣規則都會出現(請參見這里;您想閱讀第5.12節關于擴大原始轉換的內容)。
第二部分:使一個數組成為最終數組仍然允許您更改它的任何字段;再次如此;不可能持續折疊;因此"加寬"操作再次開始。
這確實是編譯器在與final一起使用時在持續折疊中所做的,正如我們從字節代碼中看到的那樣:
byte f = 1;
// because compiler still use variable 'f', so `f + f` will
// be promoted to int, so we need cast
byte ff = (byte) (f + f);
final byte s = 3;
// here compiler will directly compute the result and it know
// 3 + 3 = 6 is a byte, so no need cast
byte ss = s + s;
//----------------------
L0
LINENUMBER 12 L0
ICONST_1 // set variable to 1
ISTORE 1 // store variable 'f'
L1
LINENUMBER 13 L1
ILOAD 1 // use variable 'f'
ILOAD 1
IADD
I2B
ISTORE 2 // store 'ff'
L2
LINENUMBER 14 L2
ICONST_3 // set variable to 3
ISTORE 3 // store 's'
L3
LINENUMBER 15 L3
BIPUSH 6 // compiler just compute the result '6' and set directly
ISTORE 4 // store 'ss'
如果您將最后一個字節更改為127,它還會抱怨:
final byte s = 127;
byte ss = s + s;
在這種情況下,編譯器計算結果并知道它超出了限制,因此它仍然會抱怨它們不兼容。
更多:
還有一個關于用繩子不斷折疊的問題:
我只有手機可以接,所以我跳過了字節碼部分。很高興你自愿這么做——)
同時也說明了其動機:當編譯到字節碼時,為了存儲和計算,byte變量被擴大到int變量,除非右邊的操作數是final常量,在這種情況下,計算可以在編譯時靜態進行。
總結
以上是生活随笔為你收集整理的java为什么复制数组会减一_如果从数组中复制了Java,为什么Java需要对最终变量进行显式强制转换?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 民生信用卡额度
- 下一篇: java美元兑换,(Java实现) 美元