读thinking in java笔记(二):操作符

在最底层,Java中的数据是通过使用操作符来操作的。
1. 使用Java操作符
    操作符作用于操作数,生成一个新值。另外,有些操作符可能会改变操作数自身的值,这被称为“副作用”。那些能改变操作数的操作符,最普遍的用途就是用来产生副作用;但要记住,使用此类操作符生成的值,与使用没有副作用的操作符生成的值,没有什么区别。
    几乎所有的操作符都只能操作“基本类型”。例外的操作符是“=”、“==”和“!=”,这些操作符能操作所有的对象,除此之外String类支持“+”和“+=”。
  1.1 优先级
    当一个表达式中存在多个操作符时,操作符的优先级就决定了各部分的计算顺序。Java对计算顺序做了特别的规定。其中最简单的规则就是先乘除后加减。程序员经常会忘记其他优先级规则,所以应该用括号明确规定计算顺序。

public class Precedence {
  public static void main(String[] args) {
    int x = 1, y = 2, z = 3;
    int a = x + y - 2/2 + z;           // (1)
    int b = x + (y - 2)/(2 + z);       // (2)
    System.out.println("a = " + a + " b = " + b);
  }
} 
/* Output:
a = 5 b = 1
*/

    这两个语句看起来大体相同,但是从输出就可以看出他们具有迥然不同的含义,而这正是使用括号的结果。
    请注意,System.out.println(“a = ” + a + ” b = ” + b); 该语句中包含“+”操作符。在这种上下文环境中,“+”意味着“字符串连接”,并且如果必要,它还要执行“字符串转换”。当编译器观察到一个String后面紧跟一个“+”,而这个“+”的后面又紧跟一个非String类型的元素时,就会尝试着将这个非String类型的元素转换为String。正如在输出中所看到的,它成功的将a和b从int转换为String。
2. 赋值
    赋值操作符“=”。它的意思是“取右边的值(右值),把它复制给左边(即左值)”。右值可以是任何常数、变量或者表达式(只要它能生成一个值就行)。但左值必须是一个明确已命名的变量。
    对基本数据类型的赋值是很简单的。基本类型存储了实际的数值,而并非指向一个对象引用,所以在为其赋值的时候,是直接将一个地方的内容复制到了另一个地方。例如:对基本数据类型使用a=b,那么b的内容就复制给a。若接着又修改了a,而b根本不会受这种修改的影响。
    但是在为对象赋值的时候,情况却发生了变化。对一个对象进行操作时,我们真正操作的是对象的引用。所以倘若“将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方。这意味着假若对对象使用c=d,那么c和d都指向原本只有d指向的那个对象。

练习: 创建一个包含一个float域的类,并用这个类来展示别名机制。
public class Tank {
    float val;

    public static void main(String[] args) {
        Tank t1 = new Tank();
        Tank t2 = new Tank();
        t1.val = 4;
        t2.val = 6;
        System.out.println("1: t1.val: " + t1.val + " t2.val: " + t2.val);
        t1 = t2;
        System.out.println("2: t1.val: " + t1.val + " t2.val: " + t2.val);
        t1.val = 8;
        System.out.println("3: t1.val: " + t1.val + " t2.val: " + t2.val);
    }
}
/**
 * 1: t1.val: 4.0 t2.val: 6.0
 * 2: t1.val: 6.0 t2.val: 6.0
 * 3: t1.val: 8.0 t2.val: 8.0
 */

    Tank类非常简单,它的两个实例(t1和t2)是在main中创建的。对每个Tank类对象的val域都赋予了一个不同的值,然后将t2赋给t1,接着又修改了t1。由于赋值操作的是一个对象的引用,所以修改t1的同时也改变了t2。这是由于t1和t2包含的是相同的引用,它们指向相同的对象。(原本t1包含的对对象的引用是指向一个值为4的对象。在对t1赋值的时候,这个引用被覆盖,也就是丢失了;而那个不再被引用的对象会由“垃圾回收器”自动清理)。这种特殊的现象通常称为“别名现象”,是Java操作对象的一种基本方式。所谓的“别名现象”也就是说有不止一个的引用指向同一个对象,当通过其中的一个引用使得该对象发生改变时,发现用另一个引用获取对象的属性时,也发生了改变。
  2.1 方法调用中的别名问题
    将一个对象传递给方法时,也会产生别名问题:

import static net.mindview.util.Print.*;

class Letter {
  char c;
}

public class PassObject {
  static void 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. 算术操作符
    java中的基本算术操作符包括了+ 、 - 、 * 、 / 、% 。整数除法会直接去掉结果的小数位,而不是四舍五入。
    Java也使用了一种简化符号进行运算与赋值操作。这用操作符后紧跟一个等号来表示,它对于Java中的所有操作符都适用,只要其有实际意义就行。例如,要将x加4,并将结果赋回给x,可以这样写:x+=4。

//show all math operators
public class MathOps {
    public static void main(String[] args) {
        // create a seeded random number generator
        Random rand = new Random(13);
        int i, j, k;
        // choose value from 1 to 100
        j = rand.nextInt(100) + 1;
        System.out.println("j: " + j);
        k = rand.nextInt(100) + 1;
        System.out.println("k: " + k);
        i = j + k;
        System.out.println("j + k : " + i);
        i = j - k;
        System.out.println("j - k : " + i);
        i = k / j;
        System.out.println("k / j : " + i);
        i = k * j;
        System.out.println("k * j : " + i);
        i = k % j;
        System.out.println("k % j : " + i);
        j %= k;
        System.out.println("j %= k : " + j);
    }
    /**
     * j: 7
     * k: 69
     * j + k : 76
     * j - k : -62
     * k / j : 9
     * k * j : 483
     * k % j : 6
     * j %= k : 7
     */
}

    要生成数字,程序首先会创建一个Random类的对象。如果在创建过程中没有传递任何参数,那么Java就会将当前时间作为随机数生成器的种子,并由此在程序每一次执行时都产生不同的输出。通过在创建Random对象时提供种子(用于随机数生成器的初始化值,随机数生成器对于特定的种子值总是产生相同的随机数序列),就可以在每一次执行程序时都产生相同的随机数。
    通过Ramdom类的对象,程序可生成许多不同类型的随机数字。只需要调用方法nextInt()和nextFloat()即可。传递给nextInt()的参数设置了所产生随机数的上限,而其下限为0,但是这个下限并不是我们想要的,因为它会产生除0的可能性,因为我们对结果做了加一操作。

练习:编写一个计算速度的程序,它所使用的距离和时间都是常量。
public class CalculateSpeed {
    public static void main(String[] args) {
        Random rand_d = new Random(24);
        Random rand_t = new Random(81);
        float distance = rand_d.nextFloat();
        float time = rand_t.nextFloat();
        float speed = distance / time;
        System.out.println("速度为:" + speed);
    }
}

  3.1 一元加、减操作符
    一元减号(-)和一元加号(+)与二元减号和加号都使用相同的符号。其实就是一元就是表示正负号,二元就是运算符加减;根据表达式的书写形式,编译器会自动判断出使用的是哪一种。例如语句:x = -a;的含义是显然的。编译器能正确识别下述语句:x = a * -b;但读者会被搞糊涂,所以有时更明确地写成:x = a * (-b);一元减号用于转变数据的符号;而一元加号只是为了与一元减号相对应,但是它唯一的作用仅仅是将较小类型的操作数提升为int。
4. 自动递增和递减
    递增和递减操作符不仅改变了变量,并且以变量的值作为结果。对于前缀递增和前缀递减(如++a或--a),会先执行运算,再生成值。而对于后缀递增和后缀递减(如a++或a--),会先生成值,再执行运算。

举例:
public class AutoInc {
    public static void main(String[] args) {
        int i = 1;
        System.out.println("i: " + i);
        System.out.println("++i: " + ++i);  //pre-increment
        System.out.println("i++: " + i++ ); //post-increment
        System.out.println("i: " + i);
        System.out.println("--i: " + --i);  //pre-increment
        System.out.println("i--: " + i--);  //post-increment
        System.out.println("i: " + i);
    }
    测试结果为:
    /**
     * i: 1
     * ++i: 2
     * i++: 2
     * i: 3
     * --i: 2
     * i--: 2
     * i: 1
     */
}

5. 关系操作符
    关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系。如果关系是真实的,关系表达式会生成true;如果关系不真实,则生成false。关系操作符包括>、<、 >=、 <=、 ==、 != 等于和不等于适用所有的基本数据类型,而其他比较符不能用于Boolean类型。因为Boolean值只能为true或false,“大于”和“小于”没有实际意义。关系操作符==和!=也适用于所有对象。基本数据类型使用==和!=直接比较它们的值,而引用型数据类型使用==和!=时则比较的是引用的内存地址值。equals()不适用于“基本类型”,在没有覆盖equals()方法的类中使用equals()进行比较时依然比较的是内存地址值。

练习:创建一个名为Dog的类,它包含两个String域:name和says。在main()方法中,创建两个dog对象,一个名为spot(它的叫声为“Ruff !”),另一个名为scruffy(它的叫声为“Wurf!")。然后显示出它们的名字和叫声。
public class Dog {
    private String name;
    private String says;

    public static void main(String[] args) {
        Dog spot = new Dog();
        Dog scruffy = new Dog();
        spot.says = "Ruff! ";
        scruffy.says = "Wurf! ";
        System.out.println("spot: " + spot.name + " -- " + spot.says);
        System.out.println("scruffy: " + scruffy.name + " -- " + scruffy.says);
    }
}
/**
 * spot: null -- Ruff! 
 * scruffy: null -- Wurf!
 */

练习:在上个练习的基础上,创建一个新的dog索引,并对其赋值为spot对象。测试用==和equals()方法来比较所有引用的结果。
public class Dog {
    private String name;
    private String says;

    public static void main(String[] args) {
        Dog spot = new Dog();
        Dog scruffy = new Dog();
        Dog new_d = new Dog();
        new_d = spot;
        spot.says = "Ruff! ";
        scruffy.says = "Wurf! ";
        System.out.println("spot: " + spot.name + " -- " + spot.says);
        System.out.println("scruffy: " + scruffy.name + " -- " + scruffy.says);
        System.out.println("new_d: " + new_d.name + " -- " + new_d.says);
        System.out.println(spot == new_d);
        System.out.println(spot.equals(new_d));
    }

    /**
     *  spot: null -- Ruff! 
     *  scruffy: null -- Wurf! 
     *  new_d: null -- Ruff! 
     *  true
     *  true
     */

6. 逻辑操作符
    逻辑操作符“与”(&&)、“或”(||)、“非”(!)能根据参数的逻辑关系,生成一个布尔值(true或false)。与、或、非操作只可应用于布尔值。注意,如果在应该使用String值的地方使用了Boolean,布尔值会自动转换成适当的文本形式。
    短路现象:即一旦能明确无误的确定整个表达式的值,就不再计算表达式余下的部分了。因此,整个逻辑表达式靠后的部分有可能不会被运算。例如:表达式1 && 表达式2 && 表达式3 ,假如第一个表达式结果为true,第二个结果为false,由于这意味着整个结果为false,所以没必要计算余下的表达式。
7. 直接常量
    一般来说,如果在程序里使用了“直接常量”,编译器可以准确地知道要生成什么样的类型,但有时候却是模棱两可的。如果发生这种情况,必须对编译器加以适当的“指导”,用与直接量相关的某些字符来额外增加一些信息。

举例:
public class Literals {

    public static void main(String[] args) {
        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;
        System.out.println("c: " + Integer.toBinaryString(c));
        byte b = 0x7f;
        System.out.println("b: " + Integer.toBinaryString(b));
        short s = 0x7fff;
        System.out.println("s: " + Integer.toBinaryString(s));
        long n1 = 200L;
        long n2 = 200l;
        long n3 = 200;
        System.out.println("n1:" + n1 + "|| n2: " + n2 + "|| n3: " + n3);
        float f1 = 1F;
        float f2 = 1f;
        float f3 = 1;
        System.out.println("f1:" + f1 + "|| f2: " + f2 + "|| f3: " + f3);
        double d1 = 1d;
        double d2 = 1D;
        System.out.println("d1:" + d1 + "|| d2:" + d2);
    }
    /**
     * i1: 101111
     * i2: 101111
     * i3: 1111111
     * c: 1111111111111111
     * b: 1111111
     * s: 111111111111111
     * n1:200|| n2: 200|| n3: 200
     * f1:1.0|| f2: 1.0|| f3: 1.0
     * d1:1.0|| d2:1.0
     */
}

    直接常量后面的后缀字符标志了它的类型。若为大写(或小写)的L,代表long(但是使用小写字符l容易造成混淆,因为它看起来看像数字1)。大写(或小写)字符F,代表Float,大写(或小写)字符D,则代表double。
    十六进制数适用于所有整数数据类型,以前缀0X(或0x),后面跟随0~9或小写(或大写)的a~f来表示。
    八进制数由前缀0以及后续的0~7的数字来表示。
8. 三元操作符
    三元操作符也称为条件操作符,它显得比较特别,因为它有三个操作数;但它确实属于操作符的一种,因为它最终也会生成一个值。表达式为:

boolean-exp ? value0 : value1

    如果表达式的结果为true,就计算value0,而且这个计算结果也就是操作符最终产生的值。如果表达式的结果为false,就计算value1,同样,它的结果也就成了操作符最终产生的值。
    当然也可以换用普通的if-else语句,但是三元操作符更加简洁。但假如你打算频繁使用它,还是要多做思量,因为它很容易产生可读性差的代码。
9. 字符串操作符+ 和 +=
    这个操作符在Java中有一项特殊的用途:连接不同的字符串。字符串操作有一些很有趣的行为。如果表达式以一个字符串开头,那么后续所有操作数必须是字符串型(请记住,编译器会把双引号内的字符序列自动转成字符串)

举例:
public class StringOperator {
    public static void main(String[] args) {
        int x = 0, y = 1, z = 2;
        String s = "x, y, z ";
        System.out.println(s + x + y + z);
        System.out.println(x + " " + s); //converts x to a String
        s += "(summend) = ";
        System.out.println(s + (x + y + z));
        System.out.println("" + x); //shortand for Integer.toString();
    }
    /**
     * x, y, z 012
     * 0 x, y, z 
     * x, y, z (summend) = 3
     * 0
     */
}

    请注意第一个打印语句的输出是012而不是3,而3正是将这些整数求和之后应该得到的结果,之所以出现这种结果,是因为Java编译器会将x、y、z转换成它们的字符串形式,然后连接这些字符串,而不是先把它们加到一起。
    请注意main()中的最后一个示例:有时会看到这种一个空的String后面跟 + 和一个基本类型变量,以此作为不调用更加麻烦的显式方法(在本例中应该是Interger.toString())而执行字符串转换的方式。
10. 类型转换操作符
    在适当的时候,Java会将一种数据类型自动转换为另一种。例如,假设我们为某浮点变量赋以一个整数值,编译器会将int自动转换为float。类型转换运算允许我们显式地进行这种类型的转换,或者在不能自动进行类型转换的时候强制进行类型转换。
    要想执行类型转换,需要将希望得到的数据类型置于圆括号内,放在要进行类型转换的值的左边。

示例:
public class Casting {
    public static void main(String[] args) {
        int i = 200;
        long lng = (long)i; //"widening," so cast not really required
        lng = i;
        long lng2 = 200;
        //this is narrowing conversion
        i = (int)lng2; //cast required
    }
}

    正如所看到的,即可以对数值进行类型转换,亦可对变量进行类型转换。请注意,这里可能会引入“多余的”转型,例如,编译器在必要的时候会自动进行int值到long值的提升。但是你仍然可以做这样“多余的”事,以提醒自己需要留意,也可以使代码更清晰。在其他情况下,可能只有先进行类型转换,代码编译才能通过。
    在Java中类型转换则是一种比较安全的操作。然而,如果要执行一种名为“窄化转换”的操作(也就是说,将能容纳更多信息的数据类型转换成无法容纳那么多信息的类型),就有可能面临信息丢失的危险。此时,这么做,必须显式的进行类型转换。“扩展转换(widening conversion)”,则不必显式地进行类型转换,因为新类型肯定能容纳原来类型的信息,不会出现任何信息的丢失。
    Java允许我们把任何基本数据类型转换成别的基本数据类型,但是Boolean除外,后者根本不允许进行任何类型的转换处理。“类”数据类型不允许进行类型转换。为了将一种类转换成另一种,必须采用特殊的方法(本书后面会说到,对象可以在其所属类型的类族之间进行类型转换,例如“橡树”可转型为“树”。)
    总结:1. 基本类型(除布尔)可以相互转换 2. 引用类型不可以相互转换(类族之间可以)
  10.1 截尾和舍入
    在执行窄化转换时,必须注意截尾和舍入的问题。例如,如果将一个浮点数转换为整型值,Java会如何处理呢?例如,将29.7转换为int,结果是29还是30呢?

示例1public class CastingNumbers {
    public static void main(String[] args) {
        double above = 29.7,below = 29.4;
        float fabove = 29.7f, fbelow = 29.4f;
        System.out.println("(int)above: " + (int)above);
        System.out.println("(int)below: " + (int)below);
        System.out.println("(int)fabove: " + (int)fabove);
        System.out.println("(int)fbelow: " + (int)fbelow);
    }
    /**
     * (int)above: 29
     * (int)below: 29
     * (int)fabove: 29
     * (int)fbelow: 29
     */
}

示例2public class RoundingNumbers {
    public static void main(String[] args) {
        double above = 29.7,below = 29.4;
        float fabove = 29.7f, fbelow = 29.4f;
        System.out.println("Math.round(above): " + Math.round(above));
        System.out.println("Math.round(below): " + Math.round(below));
        System.out.println("Math.round(fabove): " + Math.round(fabove));
        System.out.println("Math.round(fbelow): " + Math.round(fbelow) );
    }
    /**
     *  Math.round(above): 30
     *  Math.round(below): 29
     *  Math.round(fabove): 30
     *  Math.round(fbelow): 29
     */
}

    结论:将float和double转型为整数时,总是对该数字执行截尾。如果想要得到舍入的结果,就需要使用java.lang.,Math中的round()方法。
  10.2 提升
    如果对基本数据类型执行算术运算或按位运算,大家会发现,只要类型比int小(即char、byte或者short),那么在运算之前,这些值会自动转换为int。这样一来,最终生成的结果就是int类型。如果想把结果赋值给较小的类型,就必须使用类型转换(既然把结果赋给了较小的类型,就有可能出现信息的丢失)。通常,表达式中出现的最大的数据类型决定了表达式最终结果的数据类型。如果将一个float值与一个double值相乘,结果就是double;如果将一个int和一个long值相加,则结果为long。

    结语:注意,能够对布尔值进行的运算非常有限。我们只能赋予它true或false,并测试它为真还是为假,而不能将布尔值相加,或对布尔值进行其他任何运算。
    在char、byte和short中,我们可看到使用算术操作符中数据类型提升的效果。对这些类型的任何一个进行算术运算,都会获得一个int结果,必须将其显式地转换回原来的类型(窄化转换可能出现信息的丢失),以将值赋给原本的类型。但对于int值则不必进行类型转换,因为所有数据已经属于int类型。但要注意,如果对两个足够大的数值进行相乘操作,结果就会溢出。

11. 操作符小结
    展示了哪些数据类型能进行哪些特定的运算。基本是同一个不断重复的程序,但是每次使用了不同的基本数据类型。

//: 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;
    //! float f = (float)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 bl = (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 bl = (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 bl = (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 bl = (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 bl = (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 = ~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 bl = (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 = ~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 bl = (boolean)x;
    char c = (char)x;
    byte b = (byte)x;
    short s = (short)x;
    int i = (int)x;
    long l = (long)x;
    float f = (float)x;
  }
} ///:~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值