online - java轉byte




如果從數組中復制了Java,為什麼Java需要對最終變量進行顯式強制轉換? (2)

從以下代碼開始......

byte foo = 1;
byte fooFoo = foo + foo;

當我嘗試編譯此代碼時,我將收到以下錯誤...

錯誤:(5,27)java:不兼容的類型:從int到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

......很好。 該值將復製到最終變量,不能再更改。 使用數組中的值不會改變 foo 的值(正如預期的那樣......)。

為什麼以下需要演員?

final byte[] fooArray = new byte[1];
fooArray[0] = 1;
final byte foo = fooArray[0];
final byte fooFoo = foo + foo;

這與這個問題中的第二個例子有什麼不同? 為什麼編譯器會給我以下錯誤?

錯誤:(5,27)java:不兼容的類型:從int到byte的可能有損轉換

怎麼會發生這種情況?


JLS(第 §5.2 )具有使用 常量表達式 進行賦值轉換的特殊規則:

此外,如果表達式是 byteshortcharint 類型的常量表達式(第 §15.28 ):

  • 如果變量的類型是 byteshortchar ,則可以使用縮小的基元轉換,並且常量表達式的值可以在變量的類型中表示。

如果我們按照上面的鏈接,我們在 常量表達式 的定義中看到這些:

  • 原始類型的文字和 String 類型的文字
  • 添加劑操作符 +-
  • 引用常量變量的簡單名稱(第 §6.5.6.1 )( §4.12.4 )。

如果我們按照上面的第二個鏈接,我們會看到

原始類型或類型 String 變量是 final 並使用編譯時常量表達式(第 §15.28 )初始化,稱為 常量變量

因此,如果 foo 常量變量 ,則 foo + foo 只能分配給 fooFoo 。 要將其應用於您的案例:

  • byte foo = 1; 沒有 定義 常量變量, 因為它不是 final

  • final byte foo = 1; 確定一個 常量變量 ,因為它是 final 並用 常量表達式 (原始文字)初始化。

  • final byte foo = fooArray[0]; 沒有 定義 常量變量, 因為它沒有用 常量表達式 初始化。

請注意, fooFoo 本身是否 final 無關緊要。


值1非常適合一個字節; 1 + 1也是如此; 當變量為final時,編譯器可以進行 常量折疊 。 (換句話說:編譯器在執行該操作時不使用 foo ;但是“raw”1值)

但是當變量不是最終變量時,所有關於轉換和促銷的有趣規則都會出現(參見 here ;您希望閱讀有關擴展原始轉換的第5.12節)。

對於第二部分:使數組最終仍允許您 更改 其任何字段; 再一次; 沒有恆定的折疊可能; 所以“擴大”的行動再次開始。





byte