Java的运算符

作者: FFJ | 来源:发表于2017-09-11 22:36 被阅读1次

    Java有4大类运算符:算术运算、位运算、关系运算和逻辑运算。

    运算符的优先级

    优先级 运算符
    1 ( ) [ ] .(点运算符)
    2 ! ++ -- ~ +(正) -(负)
    3 * / %
    4 + -
    5 >> >>> <<
    6 < <= > >=
    7 == !=
    8 &
    9 ^
    10 |
    11 &&
    12 ||
    13 ?:
    14 = += -+ *= /= %=

    模运算符

    Java中,模运算符不止可以用在对整数类型取模,还可以用在浮点类型(这点跟很多其他的编程语言不一样),如

    int x = 9;
    double y = 40.5;
    System.out.println(y%x);
    
    运行结果:
    4.5
    

    复合赋值运算符

    复合赋值运算符:“+=”,“-=”,“*=”,“/=”,“%=”(两个运算符中间不要有空格)

    对于,javatotal *= sum + 12;等价于:total = total * (sum + 12);

    有关“++”(“--”也适用)运算符的说明:

    public class Hello {
        public static void main(String[] args) {
            int i = 10;
            int k = i + ++i;
            System.out.println(k);
            i = 10;
            int j = i++ + i;
            System.out.println(j);
            i = 10;
            int m = i + i++;
            System.out.println(m);
            i = 10;
            int n = ++i +i;
            System.out.println(n);
        }
    }
    
    运行结果:
    21
    21
    20
    22
    
    • 首先声明,
      当 i = 10 时,进行 “i++” 运算后, i 的值是 11,而“i++”这个表达式的值是10;
      当 i = 10 时,进行 “++i” 运算后, i 的值是 11,而“++i”这个表达式的值也是11;
    • 优先级相同的四则运算,运算顺序是从左往右的。
      对于int k = i + ++i;,左边的 i 取值为 10,右边的 i 取值也为10,此时先计算 “++i” 的值(“++”,“--”为单目运算符,运算优先级比算数运算高),为11。所以 k 的值为 21。
      对于int j = i++ + i;,左边的 i 取值为 10,先进行 “i++” 的运算,此时 i = 11,“i++” 的值为10。所以 j 的值为 21。
      对于int m = i + i++;,左边的 i 取值为10,右边的 i 取值也为 10,而 “i++” 的值为 10,故 m 的值为 20。
      对于int n = ++i +i;,左边的 i 取值为 10,经过 “++i” 的计算表达式值为 11,i 的值为11,故 n 的值为 22。

    运算符“++”前置等价于“+=1”。如,有int i = 1,则“++i” 与“i += 1”效果一样,表达式的值都为2。

    int i = 1;
    System.out.println(i+=1);
    
    运算结果:
    2
    
    int i = 1;
    System.out.println(++i);
    
    运算结果:
    2
    
    int i = 1;
    System.out.println(i++);
    
    运算结果:
    1
    

    位运算符

    Java定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long,int,short,char和 byte。

    运算符 结果
    ~ 按位非(NOT)(一元运算)
    & 按位与(AND)
    | 按位或(OR)
    ^ 按位异或(XOR)
    >> 右移
    >>> 右移,左边空出的位以0填充
    << 左移
    &= 按位与赋值
    |= 按位或赋值
    ^= 按位异或赋值
    >>= 右移赋值
    >>>= 右移赋值,左边空出的位以0填充
    <<= 左移赋值

    Java使用大家知道的2的补码 (two's complement) 这种编码来表示负数,也就是通过将与其对应的正数的二进制代码取反(即将1变成0,将0变成1),然后对其结果加1。要对一个负数解码,首先对其所有的位取反,然后加1。

    位逻辑运算符

    按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。
    按位与运算符“&”,如果两个运算数都是1,则结果为1。
    按位或运算符“|”,任何一个运算数为1,则结果为1。
    按位异或运算符“^”,只有在两个比较的位不同时其结果是 1。否则,结果是零。

    按位异或运算符有一个有用的属性,如

    00101010 42
    ^00001111 15
    ---------------
    00100101 37

    可以看到,通过按位异或,取出了低位的值。

    左移运算符

    左移运算符<<使指定值的所有位都左移规定的次数。它的通用格式如下所示:
    value << num
    每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。

    在对byte和short类型的值进行移位运算时,由于Java会自动把这些类型扩大为 int型,而且,表达式的值也是int型 。对byte和short类型的值进行移位运算的结果是int型,而且如果左移不超过31位,原来对应各位的值也不会丢弃。但是,如果你对一个负的byte或者short类型的值进行移位运算,它被扩大为int型后,它的符号也被扩展。这样,整数值结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单办法是将结果转换为byte型。

    public class test {
    
        public static void main(String[] args) {
            byte a = 64, b;
            int i;
          
            byte c = -64, d;
            int j;
          
            j = c << 2;
            i = a << 2;
            d = (byte)(c << 2);
            b = (byte) (a << 2);
          
            System.out.println("Original value of a: " + a);
            System.out.println("i and b: " + i + " " + b);
            
            System.out.println("Original value of c: " + c);
            System.out.println("i and b: " + j + " " + d);
            }
    
    }
    
    该程序产生的输出下所示:
    Original value of a: 64
    i and b: 256 0
    Original value of a: -64
    i and b: -256 0
    

    每次左移都可以使原来的操作数翻倍,所以这个办法可以用来进行快速的2的乘法。但是,如果将1移进高阶位(31或63位),那么该值将变为负值。

    class MultByTwo {
        public static void main(String args[]) {
            int i;
            int num = 0xFFFFFFE;
            for(i=0; i<4; i++) {
                num = num << 1;
                System.out.println(num);
            }
        }
    }
    
    该程序的输出如下所示:
    536870908
    1073741816
    2147483632
    -32
    
    右移运算符

    右移运算符>>使指定值的所有位都右移规定的次数。它的通用格式如下所示:
    value >> num
    这里,num指定要移位值value移动的位数。

    将值每右移一次,就相当于将该值除以2并且舍弃了余数。

    所以,如果想利用这个特点将一个整数进行快速的2的除法,需要确保你不会将该数原有的任何一位移出。

    右移时,被移走的最高位(最左边的位)由原来最高位的数字补充。如果要移走的值为负数,每一次右移都在左边补1,如果要移走的值为正数,每一次右移都在左边补0,这叫做符号位扩展(保留符号位)(sign extension),在进行右移操作时用来保持负数的符号。

    由于符号位扩展(保留符号位)每次都会在高位补1,因此-1右移的结果总是–1。(-1的二进制补码是全1)

    若不希望在右移时保留符号,用按位与可以实现。如,要进行运算的是byte型的数,则将它的值转换为用十六进制表示。注意右移后的值与0x0f进行按位与运算,这样可以舍弃任何的符号位扩展。

    无符号右移

    当处理像素值或图形时,就常常不希望进行符号位扩展。

    Java的无符号右移运算符>>>,总是在左边补0。

    由于无符号右移运算符>>>总是把short和byte型的数据扩大为int型,所以只是对32位和64位的值有意义。如,

    byte b = (byte) 0xf1;
    byte d = (byte) (b >>> 4);
    

    运算结果d的值为0xff。

    关系运算符

    在C/C++中,这些类型的语句是很常见的:

    int done;
    // ...
    if(!done) ... // Valid in C/C++
    if(done) ... // but not in Java 
    

    而在Java中,这些语句必须写成下面这样:

    if(done == 0)) ... // This is Java-style.
    if(done != 0) ...
    

    因为在C/C++中,任何非0的值为真,而0值是假。但是,Java中真值、假值跟数字没有关系。

    所有的关系运算符的优先级比算数运算的低,但是比赋值运算的高。

    判断是否相等的 == 和 != 的优先级比其他的低,而连续的关系运算是从左到右进行的。

    布尔逻辑运算符

    运算符 含义
    & 逻辑与
    | 逻辑或
    ^ 异或
    || 短路或
    && 短路与
    ! 逻辑反
    &= 逻辑与赋值(赋值的简写形式)
    |= 逻辑或赋值(赋值的简写形式)
    ^= 异或赋值(赋值的简写形式)
    == 相等
    != 不相等
    ?: 三元运算符(IF-THEN-ELSE)

    两个boolean类型的数据可以做 == 和 != 的比较,但是不可以做 > ,>= , < , < =运算。boolean类型的不可以和整型或浮点型的数据作比较。

    短路逻辑运算符

    对于 && 运算,如果左边表达式的值为false,就不在计算右边表达式的值,直接得出为false的结论;
    对于 || 运算,如果左边的表达式值为true,就不在计算右边表达式的值,直接得出true的结论。

    短路逻辑运算符的应用,如,

    if (denom != 0 && num / denom > 10)
    

    防止被0除错误。

    赋值运算符

    赋值运算符允许你对一连串变量赋值。如,

    int x,y,z;
    x = y = z = 100; 
    

    括号运算符

    圆括号(不管是不是多余的)不会降低你程序的运行速度。因此,添加圆括号可以减少含糊不清,不会对你的程序产生消极影响。

    结合关系

    例:

    int result = 2;
    result = (result = result * 2) * 6 * (result = 3 + result);
    

    此处 result 的运算结果是168。即,先计算左边括号里的表达式,再计算右边括号里的表达式。
    真正自己编程的时候,这个表达式应该被拆成若干个表达式,然后以明显的正确的顺序来进行计算。如,

    int result = 2;
    int temp;
    int tempTwo;
    result = result * 2;
    temp = result;
    tempTwo = result +3;
    result = temp * 6 * tempTwo;
    

    相关文章

      网友评论

        本文标题:Java的运算符

        本文链接:https://www.haomeiwen.com/subject/jhlqsxtx.html