[英]Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)
[英]Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
直到今天,我認為例如:
i += j;
只是一個捷徑:
i = i + j;
但是如果我們試試這個:
int i = 5;
long j = 8;
然后i = i + j;
不會編譯但i += j;
會編譯得很好。
這是否意味着實際上i += j;
是這樣的快捷方式i = (type of i) (i + j)
嗎?
與這些問題一樣,JLS 擁有答案。 在這種情況下, §15.26.2 復合賦值運算符。 摘錄:
E1 op= E2
形式的復合賦值表達式等價於E1 = (T)((E1) op (E2))
,其中T
是E1
的類型,只是E1
只計算一次。
引用自§15.26.2的示例
[...] 以下代碼是正確的:
short x = 3; x += 4.6;
並導致 x 的值為 7,因為它等價於:
short x = 3; x = (short)(x + 4.6);
換句話說,你的假設是正確的。
這種轉換的一個很好的例子是使用 *= 或 /=
byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57
或者
byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40
或者
char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'
或者
char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'
很好的問題。 Java 語言規范確認了您的建議。
例如,以下代碼是正確的:
short x = 3; x += 4.6;
並導致 x 的值為 7,因為它等價於:
short x = 3; x = (short)(x + 4.6);
是的,
基本上當我們寫
i += l;
編譯器將其轉換為
i = (int)(i + l);
我剛剛檢查了.class
文件代碼。
知道這真是一件好事
在i = i + l
情況下,您需要從long
explicitly
為int
然后它將編譯並提供正確的輸出。 喜歡
i = i + (int)l;
或者
i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.
但在+=
情況下,它工作正常,因為運算符隱式地將類型從右變量類型轉換為左變量類型,因此不需要顯式轉換。
這里的問題涉及類型轉換。
當你添加 int 和 long 時,
但是+=
的編碼方式是進行類型轉換。 i=(int)(i+m)
在 Java 中,當賦值操作右側的表達式類型可以安全地提升為賦值左側的變量類型時,會自動執行類型轉換。 因此我們可以安全地分配:
byte -> short -> int -> long -> float -> double.
反過來也一樣。 例如,我們不能自動將 long 轉換為 int,因為第一個需要比第二個更多的存儲,因此可能會丟失信息。 要強制進行這種轉換,我們必須執行顯式轉換。
類型 - 轉換
有時,這樣的問題可以在面試中提出。
例如,當你寫:
int a = 2;
long b = 3;
a = a + b;
沒有自動類型轉換。 在 C++ 中編譯上面的代碼不會有任何錯誤,但在 Java 中你會得到類似Incompatible type exception
東西。
所以為了避免它,你必須像這樣編寫代碼:
int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
主要區別在於a = a + b
沒有進行類型轉換,因此編譯器會因為您沒有進行類型轉換而生氣。 但是對於a += b
,它真正做的是將b
類型轉換為與a
兼容的類型。 所以如果你這樣做
int a=5;
long b=10;
a+=b;
System.out.println(a);
你真正在做的是:
int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);
這里的微妙之處...
當j
是 double 且i
是 int 時, i+j
有一個隱式類型轉換。 當它們之間存在操作時,Java總是將整數轉換為雙精度數。
為了澄清i+=j
其中i
是整數而j
是雙精度可以描述為
i = <int>(<double>i + j)
參見: 隱式轉換的這個描述
在這種情況下,為了清楚起見,您可能希望將j
類型轉換為(int)
。
Java 語言規范將E1 op= E2
定義為等效於E1 = (T) ((E1) op (E2))
,其中T
是E1
的類型,並且E1
被評估一次。
這是一個技術性的答案,但您可能想知道為什么會這樣。 好吧,讓我們考慮以下程序。
public class PlusEquals {
public static void main(String[] args) {
byte a = 1;
byte b = 2;
a = a + b;
System.out.println(a);
}
}
這個程序打印什么?
你猜到3了嗎? 太糟糕了,這個程序不會編譯。 為什么? 好吧,碰巧在 Java 中添加字節被定義為返回一個int
。 我相信這是因為 Java 虛擬機沒有定義字節操作來保存字節碼(畢竟數量有限),而是使用整數操作是一種語言中公開的實現細節。
但是,如果a = a + b
不起作用,則意味着如果E1 += E2
被定義為E1 = E1 + E2
則a += b
永遠不會對字節起作用。 正如前面的例子所示,情況確實如此。 作為使+=
運算符適用於字節和短褲的技巧,涉及到隱式轉換。 這不是什么了不起的黑客,但在 Java 1.0 工作期間,重點是讓語言發布開始。 現在,由於向后兼容,Java 1.0 中引入的這個 hack 無法刪除。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.