和運算符相關的概念
1:操作數 參與運算符運算的數據。
2:表達式 操作數使用運算符連接的整體。
3:一元運算符 :需要一個操作數的運算符。 單目運算符。+1
4:二元運算符 :需要兩個操作數的運算符。 1+1 1-1 雙目運算符
5:三元運算符 :需要三個操作數的運算符。 三目運算符 only one。
6:返回值: 參與所有運算符運算的數據 都是 操作數 或者表達式的返回值 參與的。
參與運算的數據計算的結果 就是 參與運算數據的返回值。
小知識:
一個10進制數轉換爲2進制,奇數的未尾都爲1,偶數的末尾都0
(位運算符):
與&:兩個操作數中位都爲1,結果才爲1,否則結果都爲0;
或|:兩個位只要有一個爲1,那麼結果就是1,否則就爲0 ;
非~:如果位爲0,結果爲1,如果位爲1,結果爲0;
異或^:兩個操作數的位中,相同則結果爲0,不同則結果爲1
(移位運算符):
左移位運算符<<:是將運算符左邊的對象,向左移動運算符左邊指定的位數,並且在低位補零。其實,向左移n爲,就相當於乘上2的n此方;
右移位運算符>>:是將運算符左邊的對象向右移動運算符右邊指定的位數,並且在高位補0,其實右移位,就相當於除上2的n此方;
帶符號的右移運算符>>>:是將運算符左邊的運算對象,向右移動運算符右邊指定的位數。如果是正數,在高位補0;如果是負數,則在高位補1
算術運算符
//運算符練習
public class TestMath{
public static void main(String[] args){
//算術運算符
// 1 + : 一元運算符(通常省略) 和 二元 運算符 (實現兩個操作數相加)
//打印的是表達式 操作數 的 返回值。
System.out.println(+7);//7
System.out.println(1+7);//8
// 2: - : 一元 運算符 (負數) 二元運算符 (實現兩個操作數相減)
System.out.println(-7);//-7
System.out.println(1-7);//-6
// 3 * : 二元運算符 (實現兩個操作數相乘的結果) 正負號的結算的結果 和 數學中的規則一樣
System.out.println(1*2);//2
System.out.println(-1*2);//-2
System.out.println(1*-2);//-2
System.out.println(-1*-2);//2
//4 / : 二元運算符 (實現兩個操作數相除的結果) 整數相除結果還是整數,餘數忽略。有一個操作數是小數,結果就是小數。
// 正負號的規則和數學中一樣。
System.out.println(5/3);//1
System.out.println(5.0/3);//1.666666666666666667
System.out.println();
// 5 % 取餘: 二元運算符 ( a%b a 除以b 得到的餘數)
System.out.println(5%3);//2
System.out.println(1%3);//1
//規則:結果的符號位 與 左邊的操作數相同
System.out.println(5%3);//2
System.out.println(-5%3);//-2
System.out.println(5%-3);//2
System.out.println(-5%-3);//-2
//除 和 取餘 的應用技巧
//比如我得到一個三位的隨機數,求三位隨機數的個位 十位 百位 上的具體的數值大小。 345
final int MIN = 100;
final int MAX = 1000;
int num = (int)(Math.random() * (MAX-MIN) + MIN);
System.out.println("num = " + num);
//個位的值
int unit = num % 10;
//十位的值
int decade = num /10 % 10;
//百位
int hundred = num/100;
System.out.println(num + " 的百位是:" + hundred + "\t十位是:" + decade + "\t個位是:" + unit);
}
}
自增+自減
//運算符練習-2
public class TestMath1{
public static void main(String[] args){
// ++ 自增運算符 :一元運算符。對變量自身實現自增一的操作。
int age = 10;
//賦值操作最後執行。
age = age + 1;
//後綴模式 postfix
//自增後綴模式的表達式的返回值 是 變量自增之前的值。
//先返回,後自增。
age ++;
age = 0;
//後綴模式,首先 age ++ 產生返回值 返回 age 自增之前的值 num 。 然後age 做自增+1操作,然後將num 賦值給 value。
System.out.println(age ++);
int value = age ++;
System.out.println("age = " + age);
System.out.println("value = " + value);
age = 0;
value = age ++ + age ++ + age ++;
System.out.println("value = " + value);
//前綴模式 prefix
//先自增,後返回。
++ age;
age = 0;
System.out.println("age = " + ++age);
age = 0;
age = age ++;
System.out.println("age = " + age);
age = 0;
value = 0;
value = ++age + age ++ + age ++ + ++age;
System.out.println("age = " + age);//4
System.out.println("value = " + value);//8
// -- 自減運算符 ,實現 對變量自身自減一的操作。
// 前綴模式,先自減,後返回。
// 後綴模式,先返回,後自減。
}
}
賦值運算符
賦值運算符:=
二元運算符。
功能:將右邊表達式的返回值 賦值 給左邊的 變量 或者是終態變量。
注意:賦值語句也有返回值:他的返回值是左邊變量被賦予的值。
賦值運算符 左邊的 符號:左值,右邊的叫:右值。
左值:變量或者是終態變量。
右值:常量(1)、變量(age)、常量表達式(1+1).變量表達式(age + value).,常量變量表達式(1+age)。
注意:
賦值運算符 最後執行。
左值的類型和右值的類型需要兼容。
複合賦值運算符:
+=
-=
*=
/=
%=
&=
|=
^=
&&=
||=
//複合賦值運算符
public class Test1{
public static void main(String[] args){
//對指定的變量實現自增一的操作。
int age = 10;
age = age + 1;
age ++;
++ age;
age += 1;
//自增10
//age = age + 10;
age += 10;
//自減10
//age = age - 10;
age -= 10;
//自乘10
//age = age * 10;
age *= 10;
//自除10
age /= 10;
//age = age/10;
//自餘10
//age = age%10;
age %= 10;
}
}
關係運算符
關係運算符:
關係運算符一共有6個。
都是二元運算符。用來表示運算符左右量變的關係是否成立的!
如果關係成立,關係表達式的返回值 是true。否則 是false。
>:大於,左邊是否大於右邊
<:小於,右邊是否大於左邊
>=:大於等於,左邊是否大於等於右邊
<=:小於等於,右邊是否大於等於左邊
==:等於,左邊是否等於右邊
!=:不等於,左邊是否不等於右邊。
6種數值類型的數據都可以進行 關係的比較。 byte short int long float double
char 可以被看作整數對待,所以也可以進行所有關係的比較。
布爾類型:只適用於比較是否相等。 和 不同相等。 不能用於比較大小。
//關係運算符
public class TestReleation{
public static void main(String[] args){
System.out.println(5 > 6);//false
boolean bool = 5 != 6;//
System.out.println(bool);//true
System.out.println('a'-32 == 'A');
System.out.println('你'+0);
char c1 = 20320;
System.out.println(c1);
int age = 0;
System.out.println( age ++ > age);//false
System.out.println( age ++ < age);//true
System.out.println( age ++ == age);//false
System.out.println( age ++ != age);//true
age = 0;
System.out.println( ++ age != (age += 1));//true
}
}
邏輯運算符
邏輯運算符:6個。
& : 邏輯與
| : 邏輯或
^ : 邏輯異或
! : 邏輯非,邏輯取反。
&&:條件與、短路與
||:條件或、短路或
注意:參與邏輯運算的操作數 必須是 boolean值。 邏輯表達式的返回值也是 boolean 值。
//邏輯運算符
public class TestLogic{
public static void main(String[] args){
// & 邏輯與 二元的運算符。 規則:全真則真,有假則假。 表達的是並且的意思。
System.out.println((2>1) & true);//true
System.out.println(true & false);//false
System.out.println(false & true);//false
System.out.println(false & false);//false
System.out.println();
// | 邏輯或 二元運算符 規則:有真則真,全假則假。 表達的是或者的意思。
System.out.println(true | true);//true
System.out.println(true | false);//true
System.out.println(false | true);//true
System.out.println(false | false);//false
System.out.println();
//^ 邏輯異或 二元運算符 規則:相異爲 真true 相同 爲假false
System.out.println(true ^ true);//false
System.out.println(true ^ false);//true
System.out.println(false ^ true);//true
System.out.println(false ^ false);//false
System.out.println();
// ! 邏輯 非 一元運算符 規則:true 取反 返回 false,false 取反 返回 true
System.out.println(!true);//false
System.out.println(!false);//true
System.out.println();
// && 條件與 短路與 二元運算符 規則 全真則真,有假則假。 表達的是並且的意思。
System.out.println((2>1) && true);//true
System.out.println(true && false);//false
System.out.println(false && true);//false
System.out.println(false && false);//false
System.out.println();
// & 和 && 的區別:參與邏輯與&運算的所有的操作數表達式,都會被計算,並得到結果。不管前面的操作數是否是false。
// && 條件與 如果第一個操作數的返回值是 false,那麼後面的參與邏輯運算的表達式 將不再被計算,而直接將整個邏輯表達式的返回值返回 false。
// && 效率往往高於 & 。建議使用 && 。
int age = 0;
System.out.println((10 > 12) && (age ++ != 0));//false
System.out.println("age = " + age);
// | 和 || 區別:
// | : 參與邏輯或 | 運算的所有的操作數 都會被計算,即使前面的操作數已經是 true了。
// || 短路或 : 如果進行短路或 運算的操作數,前面的操作數 的返回值 是 true,那麼後面的表達式將不再被計算,而直接返回整個表達式的值爲true。
// 建議使用 || 短路或。 效率相對較高一點。
}
}
位運算符
位運算符:直接對底層的二進制位 做操作,效率比其他的運算符要高。只對整數類型使用。
7個位運算符。
&: 按位與
|: 按位或
^: 按位異或
~:按位取反
>>:帶符號右移
<<: 左移
>>>:無符號右移
//位運算符練習
import java.util.Random;
public class TestBit{
public static void main(String[] args){
// &: 按位與 二元運算符 規則:對應的位上進行按位與 全1 則 1 有0則0.
System.out.println(3 & 5);//1
//應用技巧:可以使用按位與 得到 指定的二進制位上的表示的數值的大小。將指定的二進制位設置爲0. 關燈
int age = 0b1010101;
System.out.println(age & 0xf);
System.out.println(age & 0b111);
// | : 按位或 二元運算符 規則: 對應的位上進行按位或,,有1則1,全0 則0
System.out.println(3 | 5);//7
//應用技巧:1:如果兩個操作數 對應的位上沒有全1 的情況,那麼按位或和加結果一樣。
System.out.println(1|2);//3
System.out.println(1|4);//5
System.out.println(4|2);//6
System.out.println(16|2);//18
System.out.println(7|16);//23
//找10個數,任意的組合十個數的加的結果。都是不同的。
//技巧2 :將指定位 設置爲 1. 開燈
// ^: 按位異或 二元運算符 規則:相同爲 0 ,相異爲1. 。一個數值,先後異或了一個值2次,那麼結果是它自身。
System.out.println(3 ^ 5 ^5);//3
//應用技巧:1 不需要中間變量交換兩個變量的值
int num1 = 15;
int num2 = 6;
num1 ^= num2; //num1 = num1 ^ num2;
num2 ^= num1; //num2 = num2 ^ num1;
num1 ^= num2; //num1 = num1 ^ num2;
System.out.println(num1 + "\t" + num2);
//2 可以實現加密效果
//明文 密文 密鑰
char c1 = '我';
char c2 = '愛';
char c3 = '你';
//密鑰
int key = 5210;
System.out.println("密文:"+(char)(c1^key)+(char)(c2^key)+(char)(c3^key));
System.out.println("解密:"+(char)(c1^key^key)+(char)(c2^key^key)+(char)(c3^key^key));
// ~:按位取反 規則:所有的二進制位 0變1 1 變0
System.out.println(~0);//-1
// >>:帶符號右移
// <<: 左移
// >>>:無符號右移
//移位 必須是整數類型 byte ,short char int long
//如果是小於等於int 類型的數據。移動n位,如果n 大於等於32 等價於 移動 n%32位 a >> n%32
// >>:帶符號右移 二元運算符 規則:低位被擠走,高位補符號位,正數補0 負數 補 1.
//應用:在某些區間內,如果想對某個數實現除以 2的n 次冪 可以通過對該數進行帶符號右移n 位來實現。
System.out.println(24>>3);//3
System.out.println(-16>>3);//-2
System.out.println(-16>>5);//0
// <<: 左移 二元運算符 規則:高位被擠走,低位補0
// 應用:在int 區間內 左移n 位 和 乘以2的n次冪等價。
System.out.println(2<<4);//2*2^4 32
System.out.println(2<<30);
// >>>:無符號右移 二元運算符,規則:低位被擠走,高位補0.
//應用:得到一個正整數。
//得到區間[10~30]之間的一個隨機數。
//創建得到隨機數的對象
Random random = new Random();
final int MIN = 10;
final int MAX = 31;
//得到一個隨機的int 值。
int num = random.nextInt();
System.out.println(num);
//得到了一個正整數
//num = num >>> 1;
num >>>= 1;
System.out.println(num);
num = num % (MAX-MIN) +MIN;
System.out.println(num);
//一句代碼實現
int value = (random.nextInt()>>>1)% (MAX-MIN) +MIN;
}
}
條件運算符
條件運算符:
java 中唯一的一個三目運算符。 需要三個操作數(三個表達式)。
語法:
表達式-1 ? 表達式-2 : 表達式-3 ;
表達式-1: 必須是一個boolean 表達式(返回值是boolean值的表達式)。
表達式-2,-3 是java 任意的表達式,但是兩個表達式的返回值的類型 要兼容。
執行過程:
1:計算表達式-1的返回值。
2:根據表達式-1 的返回值 ,如果是true,那麼就執行 表達式-2 並返回 該值作爲整個條件表達式的 返回值。
3:如果 表達式-1 的返回值 是 false,那麼就跳過 表達式-2 ,執行 並返回 表達式-3 的值。
//條件運算符
public class TestThree{
public static void main(String[] args){
// 隨機得到兩個隨機數,[10-30],打印結果。
// 將兩個隨機數中比較大的值 輸出。
//定義區間
final int MIN = 10,MAX = 31;
int num1 = (int)(Math.random()*(MAX-MIN)+MIN);
int num2 = (int)(Math.random()*(MAX-MIN)+MIN);
int num3 = (int)(Math.random()*(MAX-MIN)+MIN);
System.out.println("num1 = "+ num1 + "\tnum2 = "+num2 + "\tnum3 = "+num3);
int max = 0;
// max = num1 > num2 ? num1 : num2;
// max = max > num3 ? max : num3;
max = num1 > num2 ? (num1 > num3 ? num1 : num3) : (num2 > num3 ? num2 : num3);
System.out.println("max = "+max);
}
}
運算符的優先級
規律:
1:乘除取餘 優先級大於 加減
2:同級優先級 從左至右結合。
3:小括號優先級最高。
4:一元運算符大於二元的,二元的大於三元,賦值運算符優先級最低。
淺談Java操作符與其優先級
https://www.jb51.net/article/129977.htm
幾乎所有運算符都只能操作“主類型”(Primitives)。例外是“=”、“= =”和“! =”,它們能操作所有對象。除此以外,String類支持“+”和“+=”。
基本類型存儲了實際的數值。而並非指向一個對象的引用。所以在爲其賦值的時候,是直接把一個地方的內容複製到了另一個地方。例如,對基本數據類型使用a=b,那麼b的內容就複製給了a。若接着修改了a,而b根本不會受這種修改的影響。(基本類型是存儲在堆棧中的。假設a=4,那麼堆棧中如果沒有4,則會開闢一個空間,使值爲4。a=b之後,b也指向了堆棧中的這個4。此時a再等於5。那麼會重新在堆棧中尋找5,若沒有則新開闢使之爲5,然後a指向5。故不會影響b)
但是在爲對象“賦值”的時候,情況會發生變化。首先我們知道,對對象的操作,我們真正操作的是對對象的引用。所以倘若"將一個對象賦值給另一個對象",實際上是將“引用”從一個地方複製到另一個地方。這意味着如果對對象使用c=d之後,那麼c和d都將指向原來只有d指向的那個對象(兩個遙控器(引用)都能操作按個電視機(對象)了)。
面試題
1:爲什麼a%b 結果的符號位 與 左邊的操作數相同?
這是Java對取餘操作符(%)的定義所產生的後果。該操作符被定義爲對於所有的int數值a和所有的非零int數值b,都滿足下面的恆等式:(a / b) * b + (a % b)== a
換句話說,如果你用b整除a,將商乘以b,然後加上餘數,那麼你就得到了最初的值a。該恆等式具有正確的含義,但是當與Java的截尾整數整除操作符相結合時,它就意味着:當取餘操作返回一個非零的結果時,它與左操作數具有相同的正負符號。
通俗的解釋一下就是:(感謝大佬耐心解釋)
2: 前綴式 與 後綴式的真正區別
在Java中,運算是從左往右計算的,並且按照運算符的優先級,逐一計算出表達式的值,並用這個值參與下一個表達式的運算,如:1+2+3,其實是先計算出1+2表達式的值爲3,再參與下一個表達式的運算(1+2)+3,即3+3。再如判斷if(a+2==3)。如此類推。
a++是一個表達式 ,那麼a++就會有一個表達式的計算結果,這個計算結果就是a的舊值(加1前的值)。相對的,++a表達式的計算結果a加1後的值。
所以,自增的前綴形式與後綴形式的本質區別是:表達式的值(運算結果) 是加1前的變量的值還是加1後的變量的值(自減也是如此)。並不是先加1 與 後加1的區別,或者說,前後綴形式都是先加1(減1)的,纔得到表達式的值,再參與下一步運算。因爲這是一個表達式,必須先計算完表達式的運算,最後纔會得到表達式的值
看一下內存圖
原文鏈接:https://blog.csdn.net/HoneyGirls/article/details/81321512
對於02 1-2-1的解釋:
網上找的一張圖片,可能不太準確,但是暫時不太瞭解JVM 操作數棧那一塊東西,所以暫時先記錄一下朋友的解釋。但是還是沒看懂…
1:=號是優先級最低的,最後執行的。
2:不管你是四則運算加減乘除,還是什麼++a,a++,這些操作必須是操作操作數棧中的數據。
3:舉個栗子,我計算a + b × c ,怎麼計算的,abc這三塊內存(局部變量表)我都不動,我把a的“值”進棧(操作數棧),b和c的值也進棧(操作數棧),因爲我發現乘法優先級更高,所以我把b和c先出棧,計算好以後,再入棧,再計算棧裏剩下的a的值和bc計算結果的值。
4:我計算abc的時候,用的是abc在棧中的副本,而非abc本身那塊內存
5:我計算完++a的時候,我是給a這塊內存+1了,而不是把棧中的副本+1了。
6:但是這一套都弄完以後,a確實從1變成了2,可是棧中的副本還是1,最後把棧中的副本再賦值給等號左邊的a的時候,a還是1
7:abc本身的那塊內存學名叫“局部變量表”。
8:等號右邊進行計算的時候,是在“操作數棧”中計算的,計算結束,這個臨時的棧就空了。
9:四則計算是在操作數棧中計算的,而++操作是直接操作的局部變量表
2 自增自減是包含兩個兩個操作,不是線程安全的
注意:++a和a++實現方式的不同 這裏以後再補充
自增、自減運算符本質上不是一個計算操作,而是兩個計算操作。以a++爲例,這個運算將會編譯器解析成:a=a+1,即包含兩個單目運算符(+、=),一個單目運算符的計算操作可以看作是一個原子性操作。a++的步驟可以描述成 :1> 先取a加1,將結果存儲在臨時空間;2>將結果賦給a。所以,自增自減運算符包含兩個操作:一個加1(減1)的操作和一個賦值的操作
這個原理好像對我的編程沒有用吧?不是的,在單線程的環境下,你可以不管這個細節。但在多線程的情況下,你就得時刻牢記這個細節了。要知道,自增自減不是原子性操作,也就是說不是線程安全的運算。因此,在多線程下,如果你要對共享變量實現自增自減操作,就要加鎖,或者使用JDK提供的原子操作類(如AtomincInteger,AtomicLong等)提供的原子性自增自減方。
3 由 a+++b 表達式引起的思考
原文鏈接 :https://www.cnblogs.com/jinggod/p/8424808.html
看到這個表達式,真的很讓人疑惑:編譯器是怎麼解析的,是解析成
a++ + b
還是
a+ ++b
真糾結,乾脆直接在編譯器上跑一趟,看看結果吧!
int a = 5;
int b = 5;
int c=a+++b;
System.out.println("a的值是: "+a);
System.out.println("b的值是: "+b);
運行結果:
a的值是: 6
b的值是: 5
從結果可以確認,a+++b 其實是解析成了 a++ +b,爲什麼要這樣結合呢?其實有兩點原因:
Java中的運算是從左往右進行的;
java編譯器有一種規則——貪心規則。也就是說,編譯器會盡可能多地結合有效的符號。
那麼,a+++b這樣的結合方式就可以解釋了
但是這種結合是:儘可能多的結合,而不管這樣的結合是否合法。如:
a -- b
會被編譯器解析成
a-- b
儘管這是不合法,但編譯器還是這樣處理了,這就導致編譯不通過,產生編譯錯誤。
編譯器爲什麼要採用貪心規則呢?
從上面的分析來看,貪心規則在編程中也不好利用。那麼,貪心規則的主要目的是爲了什麼?
貪心規則的主要目的就是爲了分析String字符串,看看下面的例子就會明白:
String s = "\17";
System.out.println("\\17 轉義字符的值是:"+s+" 長度是:"+s.length());
s = "\171";
System.out.println("\\171 轉義字符的值是:"+s+" 長度是:"+s.length());
s = "\1717";
System.out.println("\\1717 轉義字符的值是:"+s+" 長度是:"+s.length());
s = "\17178";
System.out.println("\\17178 轉義字符的值是:"+s+" 長度是:"+s.length());
運行結果:
\17 轉義字符的值是: 長度是:1
\171 轉義字符的值是:y 長度是:1
\1717 轉義字符的值是:y7 長度是:2
\17178 轉義字符的值是:y78 長度是:3
“\17” 經轉義得到一個特殊字符 “” 。而“\171” 轉義後也得到一個字符 “y”。但 “\1717”、“\17178” 得到的字符串大於1,不再是一個字符,分別是 “y7”、“y78”。
也就是說,“\1717” 字符串只轉義了“\171” 部分,再鏈接 “7” 部分。“\17178” 字符串只轉義了 “\171” 部分,再連接 “78”。
那爲什麼 “\171” 爲什麼不轉義 ”\17“ 部分,再鏈接 ”1“ 呢,而是作爲一個整體進行轉義的字符串呢?
這就是 ”貪心規則“ 所決定的。八進制的轉義字符的取值範圍是 \0~\377。所以解析 ”\171“ 字符串時,編譯器儘可能多地結合字符成一個轉義字符,”\171“ 還在取值範圍內,所以就是一個字符。但 ”\1718” 字符串,最多結合前4個字符成一個有效的轉義字符 “\171”,而“\1717” 已經超出取值範圍,不是有效字符,所以最後解析成 “\171” + “7” 的結果。“17178” 也是如此。
見 https://blog.csdn.net/ClamJ092/article/details/102697234 轉義字符
總結:
編譯器在分析字符時,會盡可能多地結合成有效字符,但有可能會出現語法錯誤。
貪心規則是有用的,特別編譯器是對轉義字符的處理。
3:複合賦值運算符 和 普通的賦值方式的區別:
1:複合賦值運算符 生成的字節碼要小一點點。省一點點內存。
2:隱含了一個強制類型轉換,強制轉換的類型是左邊變量的類型。
4: &和&&的區別和聯繫,|和||的區別和聯繫
& 和 && 的區別:參與邏輯與&運算的所有的操作數表達式,都會被計算,並得到結果。不管前面的操作數是否是false。
&& 條件與 如果第一個操作數的返回值是 false,那麼後面的參與邏輯運算的表達式 將不再被計算,而直接將整個邏輯表達式的返回值返回 false。
&& 效率往往高於 & 。建議使用 && 。
| 和 || 區別:
| : 參與邏輯或 | 運算的所有的操作數 都會被計算,即使前面的操作數已經是 true了。
|| 短路或 : 如果進行短路或 運算的操作數,前面的操作數 的返回值 是 true,那麼後面的表達式將不再被計算,而直接返回整個表達式的值爲true。
建議使用 || 短路或。 效率相對較高一點。
5:爲什麼沒有無符號左移
因爲左移是在後面補0
而右移是在前面邊補1或0
有無符號是取決於數的前面的第一位是0還是1
所以右移是會產生到底補1還是0的問題。
而左移始終是在右邊補,不會產生符號問題。
所以沒有必要無符號左移<<<。
無符號左移<<<和左移<<是一樣的概念
而且,無符號右移運算只針對負數計算,對於正數沒有意義
有符號右移位運算符(>>)將運算對象向右移動運算符右側指定的位數。有符號右移位運算符使用了符號擴展:若值爲正,則在高位插入0;若值爲負,則在高位插入1
無符號右移位運算符(>>>),它使用了“零擴展”:無論正負,都在高位插入0