【0 基礎(chǔ)學(xué) Java】(四)運(yùn)算符

碼字不易,對(duì)你有幫助 點(diǎn)贊/轉(zhuǎn)發(fā)/關(guān)注 支持一下作者

微信搜公眾號(hào):不會(huì)編程的程序圓

看更多干貨,獲取第一時(shí)間更新

如果想看更好的排版,可以閱讀原文
點(diǎn)擊閱讀原文

思維導(dǎo)圖


image

目錄


@[toc]

正文


前言

在正式開始講 運(yùn)算符 之前,我們先來(lái)討論一下上節(jié)課我們所學(xué)的 變量 的一個(gè)注意點(diǎn)。

  • byte 與 char
  • short 與 char

上面兩組類型之間的轉(zhuǎn)換不管是從小到大還是從大到小,都需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換

public class helloWorld{
    
    public static void main(String[] args) {
        
        byte bt = 10;// byte 類型大小為 1 個(gè)字節(jié)
        char ch = ' ';// char 類型大小為 2 個(gè)字節(jié)
        short sh = 10;// short 類型大小為 2 個(gè)字節(jié)
        
        ch = bt;// 將 1 個(gè)字節(jié)的 bt 賦值給 2 個(gè)字節(jié)的 ch
        //編譯會(huì)報(bào)錯(cuò):不兼容的類型: 從byte轉(zhuǎn)換到char可能會(huì)有損失
        
        ch = sh;
        sh = ch;
        //編譯器還是會(huì)報(bào)錯(cuò):不兼容的類型:從short/char轉(zhuǎn)換到char/short可能會(huì)有損失
    }
}

原因:

1、char 是字符型,而 byte 和 short 是數(shù)值型,他們之間不建議轉(zhuǎn)換。

2、char 類型字符對(duì)應(yīng)的 十進(jìn)制 是沒有負(fù)數(shù)的。


一 運(yùn)算符

1. 算術(shù)運(yùn)算符

+

-

*

/

%

注意:

  • int / int 結(jié)果還是 int, 需要使用 double 來(lái)計(jì)算

    int a = 1;
    int b = 2;
    System.out.println(a / b);
    
    // 結(jié)果為 0
    

    如何正確的輸出我們想要的 0.5 呢?

    //以下三種方式得到的結(jié)果都是 0.5
    System.out.println(1.0 / 2);
    System.out.println(1 / 2.0);
    System.out.println(1.0 / 2.0);
    

    需要注意的是,在 1.0 / 2 時(shí),1.0 無(wú)疑是 double 類型,在運(yùn)算時(shí) 2 也會(huì)被提升為 double 類型,也就是 1.0 / 2.0

  • 0 不能作為除數(shù)

    int a = 1;
    int b = 0;
    System.out.println(a / b)
        
    // 運(yùn)行結(jié)果
    Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:5)
    
  • % 表示取余,不僅僅可以對(duì) int 求模,也能對(duì) double 來(lái)求模

    System.out.println(11.5 % 2.0);
    
    //運(yùn)行結(jié)果
    1.5
    
  • % 的操作數(shù)出現(xiàn)負(fù)數(shù)

    System.out.println(5 % 2);
    System.out.println(5 % -2);
    System.out.println(-5 % -2);
    System.out.println(-5 % -2);
    
    //運(yùn)行結(jié)果
    1
    1
    -1
    -1
    

    我們?cè)?【C語(yǔ)言必知必會(huì)】的【C語(yǔ)言入門到精通】的運(yùn)算符一節(jié)中討論過這個(gè)問題。

    簡(jiǎn)單的來(lái)說(shuō),結(jié)果正負(fù)取決于 左操作數(shù) 的正負(fù)


+=

-=

*=

/=

%=

int a = 10;
a += 1; // 等價(jià)于 a = a + 1
System.out.println(a);

//運(yùn)行結(jié)果
11


++

--

int a = 10;
int b = ++a;
System.out.println(b);
int c = a++;
System.out.println(c);

//運(yùn)行結(jié)果
11
11


結(jié)論:

  1. 如果不取自增運(yùn)算的表達(dá)式的返回值, 則前置自增和后置自增沒有區(qū)別。
  2. 如果取表達(dá)式的返回值, 則前置自增的返回值是自增之后的值, 后置自增的返回值是自增之前的值。


思考題:下面程序會(huì)輸出什么?

int i = 10;
        
i = i++;
System.out.println(i);

點(diǎn)擊查看答案

2. 關(guān)系運(yùn)算符

==

!=

<

>

>=

<=


int a = 10;
int b = 20;
System.out.println(a == b);
System.out.println(a != b);
System.out.println(a < b);
System.out.println(a > b);
System.out.println(a <= b);
System.out.println(a >= b);

//運(yùn)行結(jié)果
false
true
true
false
true
false

注意: 關(guān)系運(yùn)算符的表達(dá)式返回值都是 boolean 類型。


3. 邏輯運(yùn)算符

注意: 邏輯運(yùn)算符的操作數(shù)(操作數(shù)往往是關(guān)系運(yùn)算符的結(jié)果)和返回值都是 boolean 。

這一點(diǎn)是和 C 語(yǔ)言不同的地方:

int a = 1, b = 2;
        
System.out.println(a && b);

//編譯錯(cuò)誤
helloWorld.java:7: 錯(cuò)誤: 二元運(yùn)算符 '&&' 的操作數(shù)類型錯(cuò)誤
System.out.println(a && b);
                     ^

應(yīng)當(dāng)做出如下修改:

boolean flag1 = false, flag2 = false;
        
System.out.println(flag1 && flag2);

//運(yùn)行結(jié)果:
false


邏輯運(yùn)算符主要有三個(gè):

&&

||

!


邏輯與 &&

規(guī)則: 兩個(gè)操作數(shù)都為 true, 結(jié)果為 true, 否則結(jié)果為 false 。

int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b && b < c);

//運(yùn)行結(jié)果
true
邏輯或 ||

規(guī)則: 兩個(gè)操作數(shù)都為 true, 結(jié)果為 true, 否則結(jié)果為 false 。

int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b || b > c)
    
//運(yùn)行結(jié)果
true


邏輯非 !

規(guī)則: 操作數(shù)為 true, 結(jié)果為 false; 操作數(shù)為 false, 結(jié)果為 true(這是個(gè)單目運(yùn)算符, 只有一個(gè)操作數(shù))

int a = 10;
int b = 20;
System.out.println(!a < b);

//編譯錯(cuò)誤
! 只能作用于 boolean 類型,而 a 是 int 類型


短路求值

&& 和 || 遵守短路求值的規(guī)則。

System.out.println(10 > 20 && 10 / 0 == 0);
System.out.println(10 < 20 || 10 / 0 == 0);

//打印結(jié)果:
false
true

我們都知道, 計(jì)算 10 / 0 會(huì)導(dǎo)致程序拋出異常。但是上面的代碼卻能正常運(yùn)行, 說(shuō)明 10 / 0 并沒有真正被求值。


結(jié)論:

  • 對(duì)于 && ,如果左側(cè)表達(dá)式值為 false, 則表達(dá)式的整體的值一定是 false, 無(wú)需計(jì)算右側(cè)表達(dá)式
  • 對(duì)于 || ,如果左側(cè)表達(dá)式值為 true, 則表達(dá)式的整體的值一定是 true, 無(wú)需計(jì)算右側(cè)表達(dá)式


**& 和 | (不推薦使用) **

& 和 | 如果操作數(shù)為 boolean 的時(shí)候, 也表示邏輯運(yùn)算. 但是和 && 以及 || 相比, 它們不支持短路求值

System.out.println(10 > 20 & 10 / 0 == 0); // 程序拋出異常
System.out.println(10 < 20 | 10 / 0 == 0); // 程序拋出異常

4、位運(yùn)算符

位運(yùn)算符主要有 4 個(gè):

&

|

~

^

位操作表示 按二進(jìn)制位運(yùn)算。計(jì)算機(jī)中都是使用二進(jìn)制來(lái)表示數(shù)據(jù)的(01構(gòu)成的序列), 按位運(yùn)算就是在按照二進(jìn)制位的
每一位依次進(jìn)行計(jì)算。(這與 C 語(yǔ)言基本相同,我們?cè)?C 的教程中也詳細(xì)講過,這里不做展開。)

按位與:&

如果兩個(gè)二進(jìn)制位都是 1, 則結(jié)果為 1, 否則結(jié)果為 0 。

int a = 10;//01010
int b = 20;//10100
System.out.println(a & b);

//運(yùn)行結(jié)果:
0

操作數(shù)有負(fù)數(shù)的情況

byte a = -1;//1111 1111
byte b = 13;//0000 1101
 
 System.out.println(a & b);

//運(yùn)行結(jié)果:
13


byte a = -1;//1111 1111
byte b = -2;//1111 1110

System.out.println(a & b);

//運(yùn)行結(jié)果:
-2

這說(shuō)明,負(fù)數(shù)補(bǔ)碼的符號(hào)位是參數(shù) & 運(yùn)算的。

按位或:|

如果兩個(gè)二進(jìn)制位都是 0, 則結(jié)果為 0, 否則結(jié)果為 1 。

int a = 10;//01010
int b = 20;//10100
System.out.println(a | b);

//運(yùn)行結(jié)果
30(11110)

注意: 當(dāng) & 和 | 的操作數(shù)為整數(shù)(int, short, long, byte) 的時(shí)候, 表示按位運(yùn)算, 當(dāng)操作數(shù)為 boolean 的時(shí)候, 表示邏輯運(yùn)算 。

按位取反:~

如果該位為 0 則轉(zhuǎn)為 1, 如果該位為 1 則轉(zhuǎn)為 0 。

int a = 0xf;
System.out.printf("%x\n", ~a);

//運(yùn)行結(jié)果:
fffffff0

解析:

  • 0x 前綴的數(shù)字為 十六進(jìn)制 數(shù)字. 十六進(jìn)制可以看成是二進(jìn)制的簡(jiǎn)化表示方式. 一個(gè)十六進(jìn)制數(shù)字對(duì)應(yīng) 4 個(gè)二進(jìn)
    制位.
  • 0xf 表示 10 進(jìn)制的 15, 也就是二進(jìn)制的 1111
  • printf 能夠格式化輸出內(nèi)容, %x 表示按照十六進(jìn)制輸出(在 C 語(yǔ)言中,轉(zhuǎn)換說(shuō)明 x 表示以十六進(jìn)制打印 unsigned int 類型的值,unsigned int 是 4 個(gè) 字節(jié),Java 中雖然沒有 unsigned int 但是 %x 應(yīng)該同 C 一樣打印 4 個(gè)字節(jié)。所以,a 雖然是 0xf, 但是被編譯器看作是:0x0000000f )。
  • \n 表示換行符
按位異或:^

如果兩個(gè)數(shù)字的二進(jìn)制位相同, 則結(jié)果為 0, 相異則結(jié)果為 1 。

byte a = 10;//1010
byte b = 14;//1110
System.out.println(a ^ b);

//運(yùn)行結(jié)果:
4(0010)


5、移位運(yùn)算(了解)

如果你想搞明白,可以去看看我的 C 語(yǔ)言的操作符的文章 和 【C進(jìn)階】第一節(jié)數(shù)據(jù)存儲(chǔ)。

<<

>>

>>>


左移:<<

最左側(cè)位不要了, 最右側(cè)補(bǔ) 0 。

int a = 0x10;

System.out.printf("%x\n", a << 1);

//運(yùn)行結(jié)果:(注意打印的格式是 16 進(jìn)制)
20(相當(dāng)于乘以 2)
右移:>>

最右側(cè)位不要了, 最左側(cè)補(bǔ)符號(hào)位(正數(shù)補(bǔ)0, 負(fù)數(shù)補(bǔ)1) 。

int a = 0x10;
//0x10 -> 16 -> 0001 0000 >> 1 -> 0000 1000 -> 8

System.out.printf("%x\n", a >> 1);

// 運(yùn)行結(jié)果
8(相當(dāng)于除以 2)


int b = 0xffff0000;//這是一個(gè)負(fù)數(shù)

System.out.printf("%x\n", b >> 1);

// 運(yùn)行結(jié)果
ffff8000
無(wú)符號(hào)右移:>>>

最右側(cè)位不要了, 最左側(cè)補(bǔ) 0 。

int a = -1;
System.out.println(a >> 1);
System.out.println(a >>> 1);

//運(yùn)行結(jié)果:
-1 
2147483647


思考一下:

byte a = -1;

System.out.println(a >>> 1);//這樣會(huì)得到 127嗎?

//運(yùn)行結(jié)果:
2147483647

為什么會(huì)輸出這樣的值?

前面我們說(shuō)過,運(yùn)算過程中 byte,short 這類大小小于 4 個(gè)字節(jié)的類型會(huì)進(jìn)行數(shù)值提升,轉(zhuǎn)化為 int


那么這樣可以嗎?

byte a = -1;// 1111 1111
//a >>> 1 -> 0111 1111 1111 1111 1111 1111 1111 1111
byte b = (byte)(a >>> 1);
//知道了數(shù)值提升,我們這樣將運(yùn)算后的 int 轉(zhuǎn)化為 byte ,這樣可以得到正確結(jié)果嗎? 

System.out.println(b);

//運(yùn)行結(jié)果:
-1

這是因?yàn)椋旱诙綇?qiáng)制類型轉(zhuǎn)換時(shí),int 會(huì)發(fā)生截?cái)?,byte 只得到 int 的后 8 位:1111 1111。在輸出 b 時(shí),1111 1111 還是會(huì)被當(dāng)作 -1 。這樣看似 >>> 操作符沒有什么卵用,但是我們應(yīng)該知道,在計(jì)算機(jī)內(nèi)部真實(shí)的情況。

總結(jié):
  1. 左移 1 位, 相當(dāng)于原數(shù)字 * 2. 左移 N 位, 相當(dāng)于原數(shù)字 * 2 的N次方。
  2. 右移 1 位, 相當(dāng)于原數(shù)字 / 2. 右移 N 位, 相當(dāng)于原數(shù)字 / 2 的N次方。
  3. 由于計(jì)算機(jī)計(jì)算移位效率高于計(jì)算乘除, 當(dāng)某個(gè)代碼正好乘除 2 的N次方的時(shí)候可以用移位運(yùn)算代替。
  4. 移動(dòng)負(fù)數(shù)位或者移位位數(shù)過大都沒有意義 。

6、條件運(yùn)算符

表達(dá)式1 ? 表達(dá)式2 : 表達(dá)式3

含義:當(dāng) 表達(dá)式1 的值為 true 時(shí), 整個(gè)表達(dá)式的值為 表達(dá)式2 的值; 當(dāng) 表達(dá)式1 的值為 false 時(shí), 整個(gè)表達(dá)式的值為 表達(dá)式3 的值

// 求兩個(gè)整數(shù)的最大值
int a = 10;
int b = 20;
int max = a > b ? a : b;

7、運(yùn)算符優(yōu)先級(jí)

運(yùn)算符之間是有優(yōu)先級(jí)的. 具體的規(guī)則我們不必記憶. 在可能存在歧義的代碼中加上括號(hào)即可 。

想看詳細(xì)的還是去看我 C 語(yǔ)言運(yùn)算符相關(guān)的教學(xué)。

總結(jié)

  1. % 操作再 Java 中也能針對(duì) double 來(lái)計(jì)算 。
  2. 需要區(qū)分清楚 前置自增 和 后置自增之間的區(qū)別 。
  3. 由于 Java 是強(qiáng)類型語(yǔ)言, 因此對(duì)于類型檢查較嚴(yán)格, 因此像 && 之類的運(yùn)算操作數(shù)必須是 boolean 。
  4. 要區(qū)分清楚 & 和 | 什么時(shí)候是表示按位運(yùn)算, 什么時(shí)候表示邏輯運(yùn)算 。

二 注釋

Java 的注釋方式和 C 一樣,主要有以下幾種:

//行注釋
/*這是
一個(gè)
塊注釋*/
/*
 *這是
 *文檔
 *注釋
 */

三 關(guān)鍵字

與 C 語(yǔ)言相同,定義的 變量名 不能與 關(guān)鍵字 沖突。

用于定義訪問權(quán)限修飾符 private protected public
定義類,函數(shù),變量修飾符 abstract final static synchronized
定義類與類之間的關(guān)系 extends implements
定義建立實(shí)例以及引用實(shí)例,判斷實(shí)例 new this super instanceof
用于異常處理 try catch finally throw throws
用于包 package import
其他修飾符 native strictfp transient volatile assert

[0 基礎(chǔ)學(xué) java ] 系列的代碼可以在我的 Github 倉(cāng)庫(kù)查看,地址如下:

https://github.com/hairrrrr/Java_SE_EnjoyLearning

歡迎 star ?。c(diǎn)一個(gè) star 方便你下回查看)

本系列的教學(xué)也可以在 GitHub 觀看(GitHub 上看教學(xué)的好處是所有文章的目錄比較清晰)。


以上就是本次的內(nèi)容。

如果文章有錯(cuò)誤歡迎指正和補(bǔ)充,感謝!

最后,如果你還有什么問題或者想知道到的,可以在評(píng)論區(qū)告訴我呦,我可以在后面的文章加上你們的真知灼見。

關(guān)注我,看更多干貨!

我是程序圓,我們下次再見。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 位運(yùn)算符主要針對(duì)二進(jìn)制,它包括了:“與”、“非”、“或”、“異或”。從表面上看似乎有點(diǎn)像邏輯運(yùn)算符,但邏輯運(yùn)算符是...
    KYM1988閱讀 4,386評(píng)論 0 0
  • 1 關(guān)鍵字 1.1 關(guān)鍵字的概述 Java的關(guān)鍵字對(duì)java的編譯器有特殊的意義,他們用來(lái)表示一種數(shù)據(jù)類型,或...
    哈哈哎呦喂閱讀 778評(píng)論 0 0
  • 一、內(nèi)存分析(棧) 二、注釋:comment 注釋的作用:幫助開發(fā)人員更好的理解記憶程序的。 java 中支持三種...
    fe0180bd6eaf閱讀 503評(píng)論 2 0
  • 1、Java中的位運(yùn)算符(操作符) 位運(yùn)算符主要針對(duì)二進(jìn)制,它包括了:“與”、“非”、“或”、“異或”。從表面上看...
    老九君閱讀 315評(píng)論 0 0
  • Win7下如何打開DOS控制臺(tái)? a:開始--所有程序--附件--命令提示符 b:開始--搜索程序和文件--cmd...
    逍遙嘆6閱讀 1,702評(píng)論 4 12

友情鏈接更多精彩內(nèi)容