Operators
5 operators: Arithmetic(+,-,*,/), Assignment(=,+=,*=), Relational(>,<,=), Logical(&,&&,|,||), Byte Manipulation
order of operations 運算符優先級
? 速記 PUMA is a REBL TA.
| Operator |
Symbols |
| Post-Unary |
expr++, expr-- |
| Pre-Unary |
++expr, --expr |
| Brackets |
( ) |
| Other Unary |
+expr, -expr, !expr |
| Multiplicative |
*, /,% |
| Additive |
+, - |
| Relational |
<, >, <=,>=, instanceof |
| Equality |
==, != |
| Bitwise |
|
| Logical |
&, ^, ` |
| Logical short-circuit |
&&, ` |
| Ternary |
expr ? expr : expr |
| Assignment |
=, +=, -+, *=, /=, %= |
在基礎類型的四則運算中,編譯器會自動將類型提升到運算表達式的最高類型,默認類型是int類型
byte xByte = 3; byte yByte = 4; byte zByte = 0;
// 下面語句會編譯錯誤,表達式結果被提升到默認的int,而zByte卻是casting,因此必須casting
zByte = xByte + yByte;
byte xByte = 3; double yDouble = 4.0; byte zByte = 0;
// 下面語句會編譯錯誤,表達式的最高類型都是byte,
// 所以表達式結果被提升到默認的int,而zByte是byte類型,所以錯誤
zByte = (byte)xByte + (byte)yDouble;
// 下面語句編譯錯誤,因為被提升到最高的類型double
zByte = xByte + yDouble;
// 正確的做法是對整個表達式的結果做casting -> int類型narrow到byte類型
zByte = (byte)( xByte + yDouble );
Pre- and Post-Unary operators
Post-Unary優先級高于pre-unary, 賦值表達式的計算從左至右
pre-unary在表達式前先將variable的值自增/減,post-unary在表達式結束后將variable自增/減
int xInt = 4; int yInt = 7; int zInt = 3;
int result = ++xInt + yInt + --zInt; // 14
// 5(xInt=5) 7 2(zInt=2)
int result = ++xInt + xInt + ++xInt; //16
// 5(XInt=5) 5 6(xInt=6)
int result = ++xInt + ++xInt + xInt; // 17
// 5(XInt=5) 6(xInt=6) 6
int result = xInt++ + xInt + xInt++; // 14
// 4(xInt=4) 5 5(xInt=5)
Assignment Operators
assignment operators: +=, -+, *=, /=, %=
?? assignment operator itself can also be used an operation
? 經典使用案例:在if等條件語句中使用assignment operator,錯誤的使用可能會帶來意想不到的錯誤
int x = 5; int y = 3; int z = x + y;
z = 5 + ( y = x + y ); // z = 13, y = 8
// 經典例子
boolean flag = false; z = 0;
if( flag = true ) { // = 是賦值符號,此處flag被賦值為true,因此進入if語句塊
z = 5;
}else{
z = 3;
}
// z = 5!!!
compound assignment operators: +=, *=, -=, /=, %=
? arithmetic promotion doesn't occur in compound assignments which casts the results automatically
?? compound assignments widen or cast the result to the assigned type
xByte = (byte)( xByte + yDouble )// arithmetic promotion leads to the compile error
byte xByte = 5; double yDouble = 3.0;
xByte = xByte + yDouble;
// xByte = (byte)( xByte + yDouble ); 才是正確的
// compound assignment會自動對結果做casting, 因此無編譯錯誤
xByte += yDouble; // 等同于xByte = (byte)( xByte + yDouble )
float afloat = 5.0f; double yDouble = 3.0; long along = 10L; short ashort = 3; byte abyte = 0;
abyte += yDouble + afloat * along % ashort; // 10
comparison/relational operators
comparison/relational operators: <, >, <=,>=, instanceof, ==, !=
?? <, >, <=,>= 只能用于numerical types, 用于其他類型的時候會有compile error
==, != 只能用于primitive types, object references, Boolean
instanceof 只能用于object instances
boolean result = false; int aint = 3; long along = 4L;
result = aint != along; // true
class ClassA{}; class ClassB extends ClassA {};
ClassA instanceA = new ClassA(); ClassB instanceB = new ClassB();
boolean result = ( instanceA instanceof ClassA ); // true
result = ( instanceB instanceof ClassA ); // true
result = ( instanceA instanceof ClassB ); // false
comparison operators themselves can be operands 比較表達式本身也可以作為操作數
int xInt = 3; long yLong = 3L; float zFloat = 3.1f;
boolean result = ( ( zFloat >= yLong ) == ( xInt <= zFloat ) );
logical operators
logical operators: &, ^, |, &&, ||, !
& : both sides must be true, both sides are tested
&& : both sides must be true, short-circuit if the left is false
| : at least one side must be true, both sides are tested
|| : at least one side must be true, short-circuit if the left is true
^ : one side must be false, and the other side true 兩邊邏輯值不同時才返回true
! : reverses the boolean
order of operations
賦值語句總是從左至右計算各表達式,在一個表達式里根據相鄰的兩個操作符的優先級進行先后計算
?? 用后綴表達式的思想來考慮整個計算過程,就可以非常清晰正確的計算出結果了
int x = 3; int y = 4; int z = 0;
// ++ 和 + 比較,++優先級高,先計算x++
// + 和 + 比較,等同優先級,先左后右,所以y = 4
// + 和 -- 比較, --優先級高,先計算--y
z = x++ + y + --y + x; // 14
// 3(x=4) 4(y=4) 3(y=3) 4
z = x + y + --y + x++; // 13
// 3 4 3(y=3) 3(x=4)
?? 經典例子 - - 的優先級高于>, > 高于 ? :
int x = 3; int y = 6; int z = 2;
z *= y / x - y - x > y ? 4 : 2; // 4
// 相當于
z *= ( (y/x - y - x) > y ) ? 4 : 2;
?? 括號的優先級僅僅低于Pre- and Post-unary
int x = 3, y = 4;
int z = --x * x + y + 8; // 16
// --優先于(), 因此先計算--x
int z = --x * ( x + y + 8 ); // 28