天天看點

Java入門(三):變量和運算符

上次談到了Java的基本資料類型,今天接着聊Java的變量、運算符。

一、變量

1、變量的分類

變量分為成員變量、局部變量和常量,其中成員變量又分為執行個體變量、類變量。

Java入門(三):變量和運算符

2、變量的定義

文法:變量類型(可以是基本類型,也可以是其他) 變量名 = 變量值 英文;結尾。

2.1 可以單次聲明一個變量,也可以單次聲明多個變量。

2.2 不能以數字、運算符、特殊字元(下劃線、美元符号$除外)開頭。

2.3 下劃線 _ 可以作為開頭,但是不建議這樣命名。

2.4 可以使用中文命名,但是不建議這樣做。

2.5 不能使用現有Java關鍵字和保留字命名。

2.6 建議使用駝峰命名法。

類名的首字母大寫;變量名、方法名首字母小寫;包名全部小寫;特殊含義的縮略詞全部大寫;常量名全部大寫;多個單詞可以使用下劃線分割。做到見名知意,不要使用拼音字母縮寫、拼音全拼、英文拼音混合的命名格式,不知道如何翻譯請查字典或線上翻譯單詞。變量名長一點無所謂,命名合理、規範,見名知意就可以。

3、變量的使用

執行個體變量的使用,需要使用new關鍵字建立對象,再通過對象引用。靜态變量可以直接使用。在使用變量前,請先初始化指派,不能聲明不指派直接使用。

package javalearningday02;

/**
 * 變量的使用
 * @author 小川94
 * @date 2018年1月21日
 */
public class UseVariable {
    
    // 成員變量,也可以稱為全局變量,可在本類或者其他類中使用
    private int age = 18;
    
    // 聲明一個靜态常量,成員變量的一種,也是一個類變量
    private static final String GENDER = "BOY";
    
    // 常量,由關鍵字final定義
    private final String NAME = "小川94";
    
    public static void main(String[] args) {
        // 在main方法中定義的局部變量
        int anotherAge = 20;
        
        // 變量的定義
        int a; // 單個變量定義
        int b = 2; // 單個變量定義并初始化
        int c,d; // 單次定義多個變量
        int _num = 1; // 可以是下劃線開頭,但是不建議
        int num_ = 2; // 可以下劃線結尾
        int $num; // 也可以美元符号開頭
        int num2; // 可以是數字結尾
        //int +num; // 錯誤寫法,不能用運算符開頭
        //int .num; // 錯誤寫法,不能用.号開頭
        //int 2num; // 錯誤寫法,不能以數字開頭
        //int *num; // 錯誤寫法,不能以*開頭,其他特殊符号也是不可以的
        int 變量 = 2; // 可以使用中文,但是建議不要使用
        
        // 不能使用關鍵字命名
        //int class; // 不能使用關鍵字
        //int goto; // Java保留關鍵字(保留關鍵字是指那些現有Java版本還未使用的關鍵字,但還是關鍵字)
        //int const; // Java保留關鍵字
        
        // 不能使用保留字命名
        /*
        int true;
        int false;
        int null;*/
    }
    
    public static String askName(String name){
        // 局部變量隻能在該變量定義并且初始化的操作域中使用,跨域使用會報錯
        // 錯誤寫法  anotherAge cannot be resolved to a variable
        //System.out.println(anotherAge);
        
        // 不能對非靜态變量進行靜态引用
        // 錯誤寫法  cannot make a static reference to the non-static field age
        // System.out.println(age); 
        
        // 對于全局變量的引用,如果是非靜态的,需要利用對象引用
        UseVariable useVariable = new UseVariable();
        System.out.println(useVariable.age);
        
        // 類變量(靜态成員變量)可以直接使用
        System.out.println("小川94的性别是"+GENDER);
        return "Hello "+name;
    }
}      

二、運算符

知道了資料類型,知道如何聲明一個變量并初始化,下面就開始做資料運算操作。

1、指派運算符。

=(指派),要和數學中的等号區分。

2、算術運算符。

+(加法)、-(減法)、*(乘法)、/(除法)、%(取餘)。這五種是開發中比較常用的。

關于除法:

(1)如果被除數是0,運作則會報算術異常,在做除法時需要判斷被除數是否為0。

(2)如果是兩個整數做除法,可能會丢失計算精度,選擇合适的資料類型尤為重要。

關于取餘:

(1)負數對整數的餘數是負數和0。

(2)正數的餘數是有周期性變化的。

(3)餘數是有範圍的數,可以控制資料範圍。

3、數值類型之間的轉換

數值之間的轉換可以分為自動轉換、強制轉換兩種形式。

3.1 自動轉換

如果兩個數中有一個為double類型,另一個數會被轉為double類型,然後再進行運算。

如果兩個數中有一個為float類型,另一個數會被轉為float類型,然後再進行運算。

如果兩個數中有一個為long類型,另一個數會被轉為long類型,然後再進行運算。

如果沒有上述的三種的類型,兩個數都會被轉為int進行運算。

小範圍的資料類型可以自動轉換到大範圍資料類型,大範圍的數可以涵蓋小範圍的數,小範圍内的數可以映射到大範圍内的數。

3.2 強制類型轉換

從大範圍的數向小範圍的數轉換,稱之為強制轉換,用法是在目标資料前使用括号,将想要轉換的類型輸入括号即可。

關于強制轉換,有幾點需要注意:

(1)範圍内的數,轉換是沒有損失的。

(2)double轉換為float,會出現精度損失。

(3)浮點數轉換為整數,隻會保留原數的整數位,不會保留小數位,也不會進行四舍五入操作。

(4)範圍外的數,會有溢出的風險。

4、結合指派和運算符

有時候為了省事,會把算術運算符和指派運算符連着一起寫。如:int n += 4; 這一句和int n = n+4;是等價的,其他的算術運算符也是如此,可以單獨寫在指派符号的前面。

5、自增、自減運算符

自增的文法是 變量++; 自減的文法是 變量--; 作用是将變量的值增加1,注意是變量,不是整體。

先加加(++變量)和後加加(變量++)在運算時有很大的不同。

(1)先加加,這裡為了友善簡寫為++n吧,是先将n的值加1,然後取n的值作為表達式(++n)整體的值。

int b = ++a;

-->第一步 a = a+1;

-->第二步 b = a;

(2)後加加,同樣為了友善簡寫為n++;是先将n的值作為表達式(n++)整體的值,然後将n的值加1。

int b = a++;

-->第一步 b = a;

-->第二步 a = a+1;

/**
     * 後加加,先将變量值賦給整體表達式,再計算n+1。後減減同理。
     */
    public static void selfAddAfter() {
        int n = 5;
        n = n++;
        n = n++;
        n = n++;
        n = n++;
        System.out.println("n的值是"+n); // n = 5;
    }
    
    /**
     * 先加加,先将變量值加1,再将加過1後的值賦給整體表達式。先減減同理
     */
    public static void selfAddBefore() {
        int m = 5;
        int n = ++m;
        System.out.println("m的值是"+m); // m = 6;
        System.out.println("n的值是"+n); // n = 6;
    }      

6、關系運算符

關系運算符,也可以稱為比較運算符,包括>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、==(等于)、!=(不等于),比較的結果為true或false。

7、邏輯運算符

邏輯運算符,包含&&(邏輯與運算)、||(邏輯或運算)、!(邏輯非運算)

在進行邏輯運算時,會出現短路運算的情況,即前一個邏輯判斷已經可以為結果定性,後面的邏輯判斷是不會執行的。

/**
     * 邏輯運算符
     */
    public static void logicOperation() {
        // false,并且發生了短路運算,因為3>4為false,可以直接為整個表達式定性,無需再判斷4>5表達式的值
        // 與運算中,所有條件都為true時,整體表達式才為true
        System.out.println(3>4 && 4>5); // 4>5下面标黃了,提示是Dead code,說明不會運作後半部分的表達式
        
        // true,這裡也發生了短路運算,不會去判斷3>4的值
        System.out.println(2>1 || 3>4);
        // 或運算中,隻要有一個為true,整個表達式的值就是true
        System.out.println(3>4 || 2>1);
        
        // true,非運算中,true變false,false變true
        System.out.println(!(4>5));
    }      

8、位運算符

與(&)、非(~)、或(|)、異或(^)、<<(帶符号左移)、>>(帶符号右移)、>>>(無符号右移),下面将詳細介紹這七種運算符。

8.1 與(&)運算

/** 
     * 與(&)運算
     * 規則:先将要運算的數轉為二進制,當相同的位上均為1時結果為1,否則結果為0
     */
    public static void andOperation() {
        /**
         * 98的原碼: 00000000 00000000 0000000 01100010
         * 18的原碼: 00000000 00000000 0000000 00010010
         * 與運算後:  00000000 00000000 0000000 00000010
         * 轉換為十進制的數是2
         */
        int num = 98&18;
        System.out.println("(98&18)的與(&)運算結果:"+num); // num = 2
    }      

8.2 非(~)運算

/** 
     * 非(~)運算
     * 規則: 正數的非運算是先取反再計算補碼,負數的非運算是先計算補碼再取反
     */
    public static void nonOperation() {
        byte num = ~90;
        /**
         * 正數非運算:原碼 -->取反(1變0,0變1,非運算)-->反碼(符号位不變,其餘1變0,0變1)--->補碼(反碼的基礎上加1)
         *      90
         * 原碼: 00000000 00000000 00000000 01011010
         * 取反: 11111111 11111111 11111111 10100101
         * 反碼: 10000000 00000000 00000000 01011010
         * 補碼: 10000000 00000000 00000000 01011011
         * 轉為十進制數則是-91
         */
        System.out.println("90的非(~)運算結果:"+num); // num = -91
        
        /**
         *      10
         * 原碼: 00000000 00000000 00000000 00001010
         * 取反: 11111111 11111111 11111111 11110101
         * 反碼: 10000000 00000000 00000000 00001010
         * 補碼: 10000000 00000000 00000000 00001011
         * 轉為十進制數是-11
         */
        System.out.println("10的非(~)運算結果:"+(~10)); // -11
        
        /**
         * 負數非運算:原碼 --->反碼(符号位不變,其餘1變0,0變1)--->補碼(反碼的基礎上加1)--->取反(1變0,0變1,非運算)
         *       -5
         * 原碼: 10000000 00000000 00000000 00000101
         * 反碼: 11111111 11111111 11111111 11111010
         * 補碼: 11111111 11111111 11111111 11111011
         * 取反: 00000000 00000000 00000000 00000100
         * 轉為十進制為 4 
         */
        System.out.println("(-5)的非(~)運算結果:"+(~(-5))); // 4
    }      

8.3 或(|)運算

/** 
     * 或(|)運算
     * 規則:當兩邊操作數的位有一邊為1時,結果為1,否則為0。
     */
    public static void orOperation() {
        /**
         * 23的原碼: 00000000 00000000 00000000 00010111
         * 75的原碼: 00000000 00000000 00000000 01001011
         * 或運算:   00000000 00000000 00000000 01011111
         * 轉換為十進制數是95
         */
        System.out.println("(23|75)的或(|)運算結果"+(23|75)); // 95
    }      

8.4 異或(^)運算

/**
     * 異或(^)運算
     * 規則:兩邊的對應位不同時,取1,否則取0。如果遇到負數,需要用負數的補碼進行計算
     */
    public static void differentOr() {
        /**
         * 17的原碼: 00000000 00000000 00000000 00010001
         * 29的原碼: 00000000 00000000 00000000 00011101
         * 異或運算:  00000000 00000000 00000000 00001100 
         * 轉為十進制數是12
         */
        System.out.println("(17^29)的異或(^)運算結果:"+(17^29)); //12
        
        /**
         * -17的原碼: 10000000 00000000 00000000 00010001
         * -17的反碼: 11111111 11111111 11111111 11101110
         * -17的補碼: 11111111 11111111 11111111 11101111
         *  29的補碼: 00000000 00000000 00000000 00011101
         *  運算結果:  11111111 11111111 11111111 11110010
         *  對結果反碼: 10000000 00000000 00000000 00001101 
         *  對結果補碼: 10000000 00000000 00000000 00001110
         *  結果轉為十進制數是-14
         */
        System.out.println("(-17^29)的異或(^)運算結果:"+(-17^29)); //-14
    }      

8.5 帶符号左移(<<)運算

/**
     * 帶符号左移(<<)運算
     * 規則: 符号位不變,左移幾位,則在補碼(正數的補碼、反碼與原碼一樣)的後面補幾個0
     *      也可以簡單了解成數學運算,左移幾位,就是原數乘以2的幾次方
     */
    public static void withSymbolToLeft() {
        /**
         * 10的原碼: 00000000 00000000 00000000 00001010
         * 左移四位:  00000000 00000000 00000000 10100000
         * 轉換為十進制數是160
         * 也可以了解成數學運算中的  10*(2*2*2*2) = 10*16 = 160
         */
        System.out.println("(10<<4)帶符号左移(<<)運算的結果:"+(10<<4)); // 160
        /**
         * -9的原碼: 10000000 00000000 00000000 00001001
         * -9的反碼: 11111111 11111111 11111111 11110110
         * -9的補碼: 11111111 11111111 11111111 11110111
         * 左移4位:  11111111 11111111 11111111 01110000
         * 再反碼:   10000000 00000000 00000000 10001111
         * 再補碼:   10000000 00000000 00000000 10010000
         * 轉為十進制數是-144
         * 也可以了解成數學運算中的  (-9)*(2*2*2*2) = (-9)*16 = -144
         */
        System.out.println("(-9)<<4)帶符号左移(<<)運算的結果:"+((-9)<<4)); // -144
    }      

8.6 帶符号右移(>>)運算

/**
     * 帶符号右移(>>)運算
     * 規則: 正數右移時,右移幾位,在補碼的左邊加幾個0,右邊的被自動擠掉;
     *      負數右移時,右移幾位,在補碼的左邊加幾個1,右邊的被自動擠掉
     */
    public static void withSymbolToRight() {
        /**
         * 20的原碼: 00000000 00000000 00000000 00010100
         * 右移4位:  00000000 00000000 00000000 00000001
         * 轉為十進制數是1
         */
        System.out.println("(20>>4)帶符号右移(>>)運算結果:"+(20>>4));
        /**
         * -86的原碼: 10000000 00000000 00000000 01010110
         * -86的反碼: 11111111 11111111 11111111 10101001
         * -86的補碼: 11111111 11111111 11111111 10101010
         * 右移四位:   11111111 11111111 11111111 11111010
         * 再計算反碼:  10000000 00000000 00000000 00000101
         * 再計算補碼:  10000000 00000000 00000000 00000110
         * 轉為十進制數是-6
         */
        System.out.println("(-86)>>4帶符号右移(>>)運算結果:"+((-86)>>4)); // -6
    }      

8.7 無符号右移(>>>)運算

/**
     * 無符号右移(>>>)運算
     * 規則: 無論正數還是負數,右移幾位,則在其補碼左邊加上幾個0
     */
    public static void noSymbolToRight() {
        /**
         * 50的原碼: 00000000 00000000 00000000 00110010
         * 右移4位:  00000000 00000000 00000000 00000011
         * 轉為十進制數是3
         */
        System.out.println("(50>>>4)的無符号右移(>>>)運算結果:"+(50>>>4)); // 3
        /**
         * -28的原碼: 10000000 00000000 00000000 00011100
         * -28的反碼: 11111111 11111111 11111111 11100011
         * -28的補碼: 11111111 11111111 11111111 11100100
         * 右移四位:   00001111 11111111 11111111 11111110
         * 再轉為十進制數是  0+0+0+0+134217728+67108864+33554432+16777216
         *                +8388608+4194304+2097152+1048576+524288+262144+131072+65536
         *             +32768+16384+8192+4096+2048+1024+512+256
         *             +128+64+32+16+8+4+2+0 = 268435454
         */
        System.out.println("(-28)>>>4的無符号右移(>>>)運算結果:"+((-28)>>>4)); // 268435454
    }      

9 三目運算符

文法為 條件 ? 條件為true執行 : 條件為false執行 。可以單個寫,也可以多層嵌套,但是如果條件比較複雜,建議單獨抽出來處理,便于閱讀和維護。

public static void threeHeadOperation() {
        int n = 3;
        int m = 10;
        int maxNum = n>m ? n : m; //單個寫法
        System.out.println(maxNum); // maxNum = 10
        
        // 設定忽略num小于0的情況
        int num = 4;
        String str = num != 0 ? num%2 == 0 ? "是偶數" : "是奇數" : "是0";
        System.out.println(str); // 是偶數
        
        // 上面的三目運算符等價于下面的代碼
        if (num != 0) {
            if (num%2 == 0) {
                System.out.println("num是偶數");
            } else {
                System.out.println("num是奇數");
            }
        } else {
            System.out.println("num是0");
        }
    }      

10 instanceof

public class JavaOperation {

    public static void main(String[] args) {
        instanceOfOperation();
    }

/**
     * instanceof 是用來在運作時指出對象是否是特定類的一個執行個體
     */
    public static void instanceOfOperation() {
        A a = new A();
        String str = a instanceof A ? "a是A的執行個體" : "a不是A的執行個體";
        System.out.println(str); // a是A的執行個體
        
        String str2 = null instanceof A ? "null是A的執行個體" : "null不是A的執行個體";
        System.out.println(str2); // null不是A的執行個體
    }
}

class A{
    
}      

Java入門(三)源碼已經上傳Github,位址:https://github.com/XiaoChuan94/javalearning/tree/master/javalearningday02,可以參考。

文章首發于我的個人公衆号:悅樂書。喜歡分享一路上聽過的歌,看過的電影,讀過的書,敲過的代碼,深夜的沉思。期待你的關注!

Java入門(三):變量和運算符

公衆号背景輸入關鍵字“Java學習電子書”,即可獲得12本Java學習相關的電子書資源,如果經濟能力允許,還請支援圖書作者的紙質正版書籍,創作不易。