1. 程式人生 > >Java程式設計思想學習(三)----第三章:操作符

Java程式設計思想學習(三)----第三章:操作符

3.2使用Java操作符

  操作符接受一個或多個引數,並生成一個新值。

  操作符作用於運算元,生成一個新值。有些操作符可以改變運算元自身的值。幾乎所以的操作符都只能操作“基本型別”。例外的操作符有“=”,“==”,“!=”,這些操作符能操作所有物件。String支援“+”和“+=”。

 3.3優先順序 

  @Test
    public void precedence() {
        int x=1,y=2,z=3;
        int a = x+y-2/2+z;
        int b = x + (y -2)/(2 - z);
        System.out.println(
"a = " + a + "b = " + b); //a = 5b = 1 }/* Output:a = 5 b = 1*///:~

System.out.println()語句中,當編譯器觀察到一個String後面緊跟一個“+”,而這個“+”的後面又緊跟一個非String型別的元素時,就會嘗試將非String型別元素轉換為String

3.4賦值

  對基本資料型別的賦值是很簡單的。基本型別儲存了實際的數值,而並非指向一個物件的引用,所以在為其賦值的時候,是直接將一個地方的內容複製到另一個地方。

  但是物件”賦值“的時候,情況發生了變化。對一個物件進行操作時,我們真正操作的是對物件的引用。

class Tank {
    float level;
}
public class Assignment {
    public static void main(String[] args) {
        TankOld t1 = new TankOld();
        TankOld t2 = new TankOld();
        
        t1.level = 18;
        t2.level = 24;
        
        System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level);
        
        t1 
= t2; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1.level = 33; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); test(); }/* Output: 1:t1.level: 18.0, t2.level: 24.0 1:t1.level: 24.0, t2.level: 24.0 1:t1.level: 33.0, t2.level: 33.0 test--------------- 1:t1.level: 18.0, t2.level: 24.0 1:t1.level: 24.0, t2.level: 24.0 1:t1.level: 33.0, t2.level: 24.0 *///:~ public static void test() { System.out.println("test---------------"); TankOld t1 = new TankOld(); TankOld t2 = new TankOld(); t1.level = 18; t2.level = 24; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1.level = t2.level; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1.level = 33; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); } }

原本t1包含的對物件的引用,是指向一個值為9的物件。在t1賦值時,這個引用被覆蓋了,也就是丟失;而那個不再被引用的物件會由“垃圾回收器”自動清理。

避免錯誤可以寫成:t1.level = t2.level;

直接操作物件內的域容易導致混亂,違背了良好的面向物件程式設計的原則。

3.4.1方法呼叫中的別名問題

class Letter{
    char c;
}

public class PassObject{

    static voic f(Letter y){
        y.c = 'z';
    }

    public static void main(String[] args){
        Letter x = new Letter();
        x.c = 'a';
        print("1:x.c:"+x.c);

        f(x);
        print("2:x.c:"+x.c);
    }
}/* Output:
 1:x.c:a
 2:x.c:z
*///~

現在需要知道它的存在,並在使用中注意這個陷阱。

3.5算數操作符

  Java的基本算術操作符與其他大多數程式設計語言是相同的。其中包括加號(+)、減號(-)、除號(/)、乘號(*)以及取模操作符(%,它從整數除法中產生餘數)。整數除法會直接去掉結果的小數位,而不是四捨五入地圓整結果。

  簡化符號同時進行運算和賦值操作。如x = x + 4,可以寫為 x += 4。

  要生成數字,程式首先會建立一個Random類的物件。如果在建立過程中沒有傳遞任何引數,那麼Java就好將當前時間作為隨機數生成器的種子,並由此在程式每一次執行都產生不一樣的輸出。通過在建立Random物件時提供種子(隨機數生產器對於特定的種子總是產生相同的隨機數序列),就可以在每一次執行過程式時都生成相同的隨機數。

3.5.1一元加、減操作符

  一元減號用於轉變資料的符號,而一元加號只是為了和一元減號相對應,但是它唯一的作用僅僅是講較小型別的運算元提升為int。

3.6自動遞增和遞減

  對於字首遞增和遞減(如++a或--a),會先執行運算,在生成值。而對於字尾遞增和字尾遞減(如a++或a--),會先生成值在執行運算。它們是除了賦值操作符以外,唯一具有“副作用”的操作符。他們會改變運算元,而不僅僅是使用自己的值。

3.7關係操作符

  關係操作符包括小於(<)、大於(>)、小於或等於(<=)、大於或等於(>=)、等於(==)以及不等於(!=)。

3.7.1測試物件的等價性

public class Equivalence  {
   public static void main(String[]args){
   Integer n1 = new Integer(47);
   Integer n2 = new Integer(47);
   System.out.println(n1 == n2);
   System.out.println(n1 != n2);
   }
}/*Output:
   false
   true
   *///:~

但是儘管物件的內容相同,然而物件的引用卻是不同的,而==和!=比較的就是物件的引用。

如果想比較兩個物件的實際內容是否相同,又該如何操作呢?此時,必須使用所有物件都適用的特殊方法equals()但這個方法不適用於“基本型別”,基本型別直接使用==和!=即可。

class Value{
    int i;
}

public class EqualsMethod2{
    public static void main(String[] args) {
            Value v1 = new Value();
            Value v2 = new Value();
            v1.i = v2.i = 100;
            System.out.println(v1.equals (v2));
        }
}/*Output:
   false
   *///:~

equals()的預設行為是比較引用。所以除非在自己的新類中覆蓋equals()方法,否則不可能表現出我們希望的行為。

大多數Java類庫都實現了equals()方法,以便用來比較物件的內容,而非比較物件的引用。

3.8邏輯操作符

邏輯操作符“與”(&&)、“或”(||)、“非”(! )能根據引數的邏輯關係,生成一個布林值(true或false)。

與在C及C++中不同的是:不可將一個非布林值當作布林值在邏輯表示式中使用。如果在應該使用String值的地方使用了布林值,布林值會自動轉換成適當的文字形式。
在上述程式中,可將整數型別替換成除布林型以外的其他任何基本資料型別。但要注意,對浮點數的比較是非常嚴格的。即使一個數僅在小數部分與另一個數存在極微小的差異,仍然認為它們是“不相等”的。

3.8.1 短路

public class ShortCircult{
    static boolean test1(int val){
        System.out.println("test1(" + val + ")");
        System.out.println("result: " + (val < 1));
        return val < 1;
    }
    static boolean test2(int val){
        System.out.println("test2(" + val + ")");
        System.out.println("result: " + (val < 2));
        return val < 2;
    }
    static boolean test3(int val){
        System.out.println("test3(" + val + ")");
        System.out.println("result: " + (val < 3));
        return val < 3;
    }
    public static void main(String[] args) {
        boolean b=test1(0)&&test2(2)&&test3(2);
        System.out.println("expression is " + b);
    }
}/*Output:
    test1 (0)
    result: true
    test2 (2)
    result: false
    expression is false
   *///:~

第二個測試產生了一個false結果。由於這意味著整個表示式肯定為false,所以沒必要繼續計算剩餘的表示式,那樣只是浪費。“短路”一詞的由來正源於此。

3.9 直接常量

@Test
    public void literalsTest1() {
        int i1 = 0x2f; // 十六進位制(小寫標識)
        System.out.println("i1: " + Integer.toBinaryString(i1));
        int i2 = 0x2F; // 十六進位制(大寫標識)
        System.out.println("i2: " + Integer.toBinaryString(i2));
        int i3 = 0177; // 八進位制(前導零)
        System.out.println("i3: " + Integer.toBinaryString(i3));
        char c = 0xffff; // 超出char自身的範圍
        System.out.println("c: " + Integer.toBinaryString(c));
        byte b = 0x7f; // 超出byte自身範圍
        System.out.println("b: " + Integer.toBinaryString(b));
        short s = 0x7fff; // 超出short自身範圍
        System.out.println("s: " + Integer.toBinaryString(s));
        long n1 = 200L; // long字尾
        System.out.println("n1: " + Long.toBinaryString(n1));
        long n2 = 200l; // long字尾(和1容易引起混淆)
        System.out.println("n2: " + Long.toBinaryString(n2));
        long n3 = 200;
        System.out.println("n3: " + Long.toBinaryString(n3));
        float f1 = 1;
        float f2 = 1f; // float字尾
        float f3 = 1F; // float字尾
        double d1 = 1d; // double字尾
        double d2 = 1D; // double字尾
    }  /* Output:
    i1: 101111
    i2: 101111
    i3: 1111111
    c: 1111111111111111
    b: 1111111
    s: 111111111111111
    n1: 11001000
    n2: 11001000
    n3: 11001000
    *///:~

如果在程式裡使用了“直接常量”,編譯器可以準確地知道要生成什麼樣的型別,但有時候卻是模稜兩可的。
直接常量後面的字尾字元標誌了它的型別。若為大寫(或小寫)的L,代表long(但是,使用小寫字母l容易造成混淆,因為它看起來很像數字1)。大寫(或小寫)字母F,代表float;大寫(或小寫)字母D,則代表double。
十六進位制數適用於所有整數資料型別,以字首0x(或0X),後面跟隨0-9或小寫(或大寫)的a-f來表示。如果試圖將一個變數初始化成超出自身表示範圍的值(無論這個值的數值形式如何),編譯器都會向我們報告一條錯誤資訊。如果超出範圍,編譯器會將值自動轉換成int型,並告訴我們需要對這次賦值進行“窄化轉型”。如果將比較小的型別傳遞給Integer.toBinaryString()方法,則該型別將自動被轉換為int。

3.9.1 指數記數法

@Test
    public void exponents() {
        //大寫和小寫一樣
        float expFloat = 1.39e-43f;
        expFloat = 1.39E-43f;
        System.out.println(expFloat);
        double expDouble = 47e47d; // 'd'可選
        double expDouble2 = 47e47d; // 自動轉為double
        System.out.println(expDouble);
        float f4 = 1e-43f; // 10的次方
        float f5 = (float) Math.pow(10, -43f);
        System.out.println(f4);
        System.out.println(f5);
        System.out.println(f4 == f5);
    } /* Output:
    1.39E-43
    4.7E48
    1.0E-43
    1.0E-43
    true
    *///:~

設計師們很自然地決定e代表“10的冪次”。

那麼在Java中看到像1.39e-43f 這樣的表示式時,請轉換思維,它真正的含義是1.39×10-43

編譯器通常會將指數作為雙精度數(double)處理,所以假如沒有這個尾隨的f,就會收到一條出錯提示,告訴我們必須使用型別轉換將double轉換成float

3.10 按位操作符

按位操作符會對兩個引數中對應的位執行布林代數運算,並最終生成一個結果。

①如果兩個輸入位都是1,則按位“與”操作符(&)生成一個輸出位1;否則生成一個輸出位0。
②如果兩個輸入位裡只要有一個是1,則按位“或”操作符 (|) 生成一個輸出位1;只有在兩個輸入位都是0的情況下,它才會生成一個輸出位0。
③如果輸入位的某一個是1,但不全都是1,那麼按位“異或”操作 (^) 生成一個輸出位1。
④按位“非”(~),也稱為取反操作符,它屬於一元操作符,只對一個運算元進行操作(其他按位操作符是二元操作符)。按位“非”生成與輸入位相反的值——若輸入0,則輸出1,若輸入1,則輸出0。

按位操作符和邏輯操作符都使用了同樣的符號,因此我們能方便地記住它們的含義:由於位是非常“小”的,所以按位操作符僅使用了一個字元。

對於布林值,按位操作符具有與邏輯操作符相同的效果,只是它們不會中途“短路”。

3.11 移位操作符

">>" "<<"

Java中增加了一種“無符號”右移位操作符(>>>),它使用“零擴充套件”:無論正負,都在高位插入0。這一操作符是C或C++中所沒有的。只有數值右端的低5位才有用。這樣可防止我們移位超過int型值所具有的位數。若對一個long型別的數值進行處理,最後得到的結果也是long。此時只會用到數值右端的低6位,以防止移位超過long型數值具有的位數。

“移位”可與“等號”(<<=或>>=或>>>=)組合使用。如果對byte或short值進行這樣的移位運算,得到的可能不是正確的結果。它們會先被轉換成int型別,再進行右移操作,然後被截斷,賦值給原來的型別,在這種情況下可能得到-1的結果。

@Test
    public void bitManipulation() {
        Random rand = new Random(47);
        int i = rand.nextInt();
        int j = rand.nextInt();
        printBinaryInt("-1", -1);
        printBinaryInt("+1", +1);
        int maxpos = 2147483647;
        printBinaryInt("maxpos", maxpos);
        int maxeng = -2147483648;
        printBinaryInt("maxeng", maxeng);
        printBinaryInt("i", i);
        printBinaryInt("j", j);
        printBinaryInt("~j", ~j);
        printBinaryInt("-i", -i);
        printBinaryInt("i & j", i & j);
        printBinaryInt("i | j", i | j);
        printBinaryInt("i ^ j", i ^ j);
        printBinaryInt("i << 5", i << 5);
        printBinaryInt("i >> 5", i >> 5);
        printBinaryInt("(~i) >> 5", (~i) >> 5);
        printBinaryInt("i >>> 5", i >>> 5);
        printBinaryInt("(~i) >>> 5", (~i) >>> 5);
        //     10111010001001000100001010010101
        //11111101110100010010001000010100
        //00000101110100010010001000010100
        /* Output:
             -1, int: -1, binary:
                11111111111111111111111111111111
            +1, int: 1, binary:
                1
            maxpos, int: 2147483647, binary:
                1111111111111111111111111111111
            maxeng, int: -2147483648, binary:
                10000000000000000000000000000000
            i, int: -1172028779, binary:
                10111010001001000100001010010101
            j, int: 1717241110, binary:
                1100110010110110000010100010110
            ~j, int: -1717241111, binary:
                10011001101001001111101011101001
            -i, int: 1172028779, binary:
                1000101110110111011110101101011
            i & j, int: 570425364, binary:
                100010000000000000000000010100
            i | j, int: -25213033, binary:
                11111110011111110100011110010111
            i ^ j, int: -595638397, binary:
                11011100011111110100011110000011
            i << 5, int: 1149784736, binary:
                1000100100010000101001010100000
            i >> 5, int: -36625900, binary:
                11111101110100010010001000010100
            (~i) >> 5, int: 36625899, binary:
                10001011101101110111101011
            i >>> 5, int: 97591828, binary:
                101110100010010001000010100
            (~i) >>> 5, int: 36625899, binary:
                10001011101101110111101011
        */
        long l = rand.nextLong();
        long m = rand.nextLong();
        printBinaryLong("-1L", -1L);
        printBinaryLong("+1L", +1L);
        long ll = 9223372036854775807L;
        printBinaryLong("maxpos", ll);
        long lln = -9223372036854775808L;
        printBinaryLong("maxeng", lln);
        printBinaryLong("l", l);
        printBinaryLong("m", m);
        printBinaryLong("~m", ~m);
        printBinaryLong("-l", -l);
        printBinaryLong("l & m", l & m);
        printBinaryLong("l | m", l | m);
        printBinaryLong("l ^ m", l ^ m);
        printBinaryLong("l << 5", l << 5);
        printBinaryLong("l >> 5", l >> 5);
        printBinaryLong("(~l) >> 5", (~l) >> 5);
        printBinaryLong("l >>> 5", l >>> 5);
        printBinaryLong("(~l) >>> 5", (~l) >>> 5);
        /*    Output:
             -1L, Long: -1, binary:
                1111111111111111111111111111111111111111111111111111111111111111
            +1L, Long: 1, binary:
                1
            maxpos, Long: 9223372036854775807, binary:
                111111111111111111111111111111111111111111111111111111111111111
            maxeng, Long: -9223372036854775808, binary:
                1000000000000000000000000000000000000000000000000000000000000000
            l, Long: -8652529054300476342, binary:
                1000011111101100000010101010101100001101101011000110110001001010
            m, Long: 2955289354441303771, binary:
                10100100000011010011000000001010010011111101111010011011011011
            ~m, Long: -2955289354441303772, binary:
                1101011011111100101100111111110101101100000010000101100100100100
            -l, Long: 8652529054300476342, binary:
                111100000010011111101010101010011110010010100111001001110110110
            l & m, Long: 72066398748419146, binary:
                100000000000010000000001000000001101001000010010001001010
            l | m, Long: -5769306098607591717, binary:
                1010111111101111010011101010101110011111111111111110111011011011
            l ^ m, Long: -5841372497356010863, binary:
                1010111011101111010001101010100110011110010110111100101010010001
            l << 5, Long: -179768631971968704, binary:
                1111110110000001010101010110000110110101100011011000100101000000
            l >> 5, Long: -270391532946889886, binary:
                1111110000111111011000000101010101011000011011010110001101100010
            (~l) >> 5, Long: 270391532946889885, binary:
                1111000000100111111010101010100111100100101001110010011101
            l >>> 5, Long: 306069219356533602, binary:
                10000111111011000000101010101011000011011010110001101100010
            (~l) >>> 5, Long: 270391532946889885, binary:
                1111000000100111111010101010100111100100101001110010011101
         */
        printBinaryLong("i ^ m", i ^ m);
        /*    Output:
         * i ^ m, Long: -2955289355552037810, binary:
         *         1101011011111100101100111111110100101001110100111110010001001110
         */
        char cone = 'a';
        int conei = 'a';
        char ctwo = 2;
        char cthree = '0';
        printBinaryInt("cthree", cthree);
        cthree = (char) (cone + ctwo);
        printBinaryInt("cone", cone);
        printBinaryInt("conei", conei);
        printBinaryInt("ctwo", ctwo);
        printBinaryInt("cthree", cthree);
        /*    Output:
         *     擴充套件
             cthree, int: 48, binary:
                110000
            cone, int: 97, binary:
                1100001
            conei, int: 97, binary:
                1100001
            ctwo, int: 2, binary:
                10
            cthree, int: 99, binary:
                1100011
         */
    }
    
    public void printBinaryInt(String s, int i) {
        System.out.println(s + ", int: " + i + ", binary:\n    " + Integer.toBinaryString(i));
    }
    public void printBinaryLong(String s, Long l) {
        System.out.println(s + ", Long: " + l + ", binary:\n    " + Long.toBinaryString(l));
    }

3.12 三元操作符if-else

  三元操作符: boolean-exp ? value0 : value1

  也可以換用普通的if-else語句(在後面介紹),但三元操作符更加簡潔。

3.13 字串操作符+和+=

  引入了操作符過載(operator overloading)機制。表示式以一個字串起頭,那麼後續所有運算元都必須是字串型。

3.14 使用操作符時常犯的錯誤

while(x=y){
    //......
}

不會得到編譯時錯誤的情況是x和y都為布林值。在這種情況下,x=y屬於合法表示式。

3.15 型別轉換操作符

  如果要執行一種名為窄化轉換(narrowing conversion)的操作(也就是說,將能容納更多資訊的資料型別轉換成無法容納那麼多資訊的型別),就有可能面臨資訊丟失的危險。而對於擴充套件轉換(widelung conversion).則不必顯式地進行型別轉換,因為新型別肯定能容納原來型別的資訊,不會造成任何資訊的丟失。

  Java允許我們把任何基本資料型別轉換成別的基本資料型別,但布林型除外,後者根本不允許進行任何型別的轉換處理。“類”資料型別不允許進行型別轉換。

  物件可以在其所屬型別的類族之間可以進行型別轉換,例如,“橡樹”可轉型為“樹”,反之亦然。但不能把它轉換成類族以外的型別,如“岩石”。

3.15.1 截尾和舍入

  將float或double轉型為整型值時,總是對該數字執行截尾。如果想要得到舍入的結果,就需要使用java.lang.Math中的round()方法。

3.15.2 提升

  表示式中出現的最大的資料型別決定了表示式最終結果的資料型別。如果將二個float值與一個double值相乘,結果就是double,如果將一個int和一個long值相加,則結果為long。

3.16 Java沒有sizeof

  在C和C++中,sizeof()操作符可以告訴你為資料項分配的位元組數。在C和C++中,需要使用sizeof()的最大原因是為了“移植”。不同的資料型別在不同的機器上可能有不同的大小,所以在進行一些與儲存空間有關的運算時,程式設計師必須獲悉那些型別具體有多大。Java不需要sizeof()操作符來滿足這方面的需要,因為所有資料型別在所有機器中的大小都是相同的。

3.17 操作符小結

//:operators/AllOps.java
//Tests all the operators on all the primitive data types to show which ones are //accepted by the Java compiler.

public class AllOps{
    //To accept the results of a boolean test:
    void f(boolean b){

    }

    void boolTest(boolean x, boolean y){
        //Arithmetic operators:
        //! x=x*y;
        //! x=x/y;
        //! x=x%y;
        //! x=x+y;
        //! x=x-y;
        //! x++;
        //! x--;
        //! x=+y;
        //! x=-y;
        //Relational and logical:
        //! f(x>y);
        //! f(x>=y);
        //! f(x<y);
        //! f(x<=y);
        f(x == y);
        f(x != y);
        f(!y);
        x = x && y;
        x = x || y;
        //Bitwise operators:
        //! x=~y;
        x = x & y;
        x = x | y;
        x = x ^ y;
        //! x=x<<1;
        //! x=x>>1;
        //! x=x>>>1;
        //Compound assignment:
        //! x+=y;
        //! x-=y;
        //! x*=y;
        //! x/=y;
        //! x%=y;
        //! x<<=1;
        //! x>>=1;
        //! x>>>=1;
        x &= y;
        x ^= y;
        x |= y;
        //Casting:
        //! char c=(char)x;
        //! byte b=(byte)x;
        //! short s=(short)x;
        //! int i=(int)x;
        //! long l=(long)x;
        //! double d=(double)x;
    }

    void charTest(char x, char y){
        //Arithmetic operators:
        x = (char) (x * y);
        x = (char) (x / y);
        x = (char) (x % y);
        x = (char) (x + y);
        x = (char) (x - y);
        x++;
        x--;
        x = (char) +y;
        x = (char) -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        x = (char) ~y;
        x = (char) (x & y);
        x = (char) (x | y);
        x = (char) (x ^ y);
        x = (char) (x << 1);
        x = (char) (x >> 1);
        x = (char) (x >>> 1);
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        x <<= 1;
        x >>= 1;
        x >>>= 1;
        x &= y;
        x ^= y;
        x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        byte b = (byte) x;
        short s = (short) x;
        int i = (int) x;
        long l = (long) x;
        float f = (float) x;
        double d = (double) x;
    }

    void byteTest(byte x, byte y){
        //Arithmetic operators:
        x = (byte) (x * y);
        x = (byte) (x / y);
        x = (byte) (x % y);
        x = (byte) (x + y);
        x = (byte) (x - y);
        x++;
        x--;
        x = (byte) +y;
        x = (byte) -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        x = (byte) ~y;
        x = (byte) (x & y);
        x = (byte) (x | y);
        x = (byte) (x ^ y);
        x = (byte) (x << 1);
        x = (byte) (x >> 1);
        x = (byte) (x >>> 1);
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        x <<= 1;
        x >>= 1;
        x >>>= 1;
        x &= y;
        x ^= y;
        x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        char c = (char) x;
        short s = (short) x;
        int i = (int) x;
        long l = (long) x;
        float f = (float) x;
        double d = (double) x;
    }

    void shortTest(short x, short y){
        //Arithmetic operators:
        x = (short) (x * y);
        x = (short) (x / y);
        x = (short) (x % y);
        x = (short) (x + y);
        x = (short) (x - y);
        x++;
        x--;
        x = (short) +y;
        x = (short) -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        x = (short) ~y;
        x = (short) (x & y);
        x = (short) (x | y);
        x = (short) (x ^ y);
        x = (short) (x << 1);
        x = (short) (x >> 1);
        x = (short) (x >>> 1);
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        x <<= 1;
        x >>= 1;
        x >>>= 1;
        x &= y;
        x ^= y;
        x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        char c = (char) x;
        byte b = (byte) x;
        int i = (int) x;
        long l = (long) x;
        float f = (float) x;
        double d = (double) x;
    }

    void intTest(int x, int y){
        //Arithmetic operators:
        x = x * y;
        x = x / y;
        x = x % y;
        x = x + y;
        x = x - y;
        x++;
        x--;
        x = +y;
        x = -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        x = ~y;
        x = x & y;
        x = x | y;
        x = x ^ y;
        x = x << 1;
        x = x >> 1;
        x = x >>> 1;
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        x <<= 1;
        x >>= 1;
        x >>>= 1;
        x &= y;
        x ^= y;
        x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        char c = (char) x;
        byte b = (byte) x;
        short s = (short) x;
        long l = (long) x;
        float f = (float) x;
        double d = (double) x;
    }

    void longTest(long x, long y){
        //Arithmetic operators:
        x = x * y;
        x = x / y;
        x = x % y;
        x = x + y;
        x = x - y;
        x++;
        x--;
        x = +y;
        x = -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        x = ~y;
        x = x & y;
        x = x | y;
        x = x ^ y;
        x = x << 1;
        x = x >> 1;
        x = x >>> 1;
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        x <<= 1;
        x >>= 1;
        x >>>= 1;
        x &= y;
        x ^= y;
        x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        char c = (char) x;
        byte b = (byte) x;
        short s = (short) x;
        int i = (int) x;
        float f = (float) x;
        double d = (double) x;
    }

    void floatTest(float x, float y){
        //Arithmetic operators:
        x = (x * y);
        x = (x / y);
        x = (x % y);
        x = (x + y);
        x = (x - y);
        x++;
        x--;
        x = +y;
        x = -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        //! x = (float) ~y;
        //! x = (float) (x & y);
        //!  x = (float) (x | y);
        //! x = (float) (x ^ y);
        //!  x = (float) (x << 1);
        //!  x = (float) (x >> 1);
        //!  x = (float) (x >>> 1);
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        //! x <<= 1;
        //!  x >>= 1;
        //!  x >>>= 1;
        //!  x &= y;
        //!  x ^= y;
        //!  x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        char c = (char) x;
        byte b = (byte) x;
        short s = (short) x;
        int i = (int) x;
        long l = (long) x;
        double d = (double) x;
    }

    void doubleTest(double x, double y){
        //Arithmetic operators:
        x = (x * y);
        x = (x / y);
        x = (x % y);
        x = (x + y);
        x = (x - y);
        x++;
        x--;
        x = +y;
        x = -y;
        //Relational and logical
        f(x > y);
        f(x >= y);
        f(x < y);
        f(x <= y);
        f(x == y);
        f(x != y);
        //! f(!x);
        //! f(x&&y);
        //! f(x||y);
        //Bitwise operators:
        //! x = (float) ~y;
        //! x = (float) (x & y);
        //!  x = (float) (x | y);
        //! x = (float) (x ^ y);
        //!  x = (float) (x << 1);
        //!  x = (float) (x >> 1);
        //!  x = (float) (x >>> 1);
        //Compound assignment:
        x += y;
        x -= y;
        x *= y;
        x /= y;
        x %= y;
        //! x <<= 1;
        //!  x >>= 1;
        //!  x >>>= 1;
        //!  x &= y;
        //!  x ^= y;
        //!  x |= y;
        //Casting:
        //! boolean b1=(boolean)x;
        char c = (char) x;
        byte b = (byte) x;
        short s = (short) x;
        int i = (int) x;
        long l = (long) x;
    }

}

在char、byte和short中,我們可看到使用算術操怍符中資料型別提升的效果。對這些型別的任何一個進行算術運算,都會獲得一個int結果,必須將其顯式地型別轉換回原來的型別(窄化轉換可能會造成資訊的丟失),以將值賦給原本的型別。但對於int值,卻不必進行型別轉化,因為所有資料都已經屬於int型別。但不要放鬆警惕,認為一切事情都是安全的,如果對兩個足夠大的int值執行乘法運算,結果就會溢位。下面這個例子向大家展示了這一點:

//:operators/Overflow.java
//Surprise! Java lets you overflow.

public class Overflow{
    public static void main(String[] args)
    {
        int big = Integer.MAX_VALUE;
        System.out.println("big = " + big);
        int bigger = big * 4;
        System.out.println("bigger = " + bigger);
    }
}/*Output:
    big = 2147483647
    bigger = -4
    *///:~