「Java SE」运算符详解

遇山开山,见水架桥

目录

3.1 逻辑 && 和 逻辑 | |

4.1 按位与(&)和按位或( | )

4.2 按位异或(^)和按位取反(~)

在我们C语言深度解剖的专栏已经讲解了一些常见的运算符了,但是基本的 + - * / 没有细说,毕竟那是深度解剖,是在一定基础上更深入学习的,我们 Java 是从 0 基础讲解的,所以这里会涉及到很全面的操作符,由于 Java 很少关注底层,所以我们也不会像讲 C语言的时候那样偶尔去从汇编的角度讲解。

1、算数运算符

1.1 四则运算符

相信大家对于四则运算都不陌生啊, 毕竟谁没做过加减乘除运算,但是这里我们主要是介绍 % 运算符,它与 C语言里的有点区别我们接着往下看:

显然答案是跟我们C语言当中是一模一样的,但是这里我们需要强调一点,以上都是二元操作符,必须拥有两个操作数,不论在C还是在Java中 int / int 的结果是整数,而且是向下取整, 也就是说,会舍去小数位,尽管你是 3.9 他算出的结果仍然是 3 。

那么我们如果想得到小数该如何做呢?

  • 将除号两边任意一个整数乘以1.0(当两边操作数类型不同,会向类型大的提升,结果也跟着变)
  • 将除号两边任意一个整数强转成 float 或者 double
  • 直接用 double 或者 float 类型计算

注意: 将他们的计算结果转化成 float 或 double 是没有用的,因为结果是取整之后的值。

接下来我们来关心我们的%运算:

如果是第一次看到这些结果的你们可能有些意外,我记得C语言中是不能对浮点数取模的啊,在Java中是允许这样操作的,其实上面的例子很简单,就是10以内的除法,如果你能对上面都算准确的话,那么你取模这个运算符肯定是没问题的。

注意:取模和除法时,右操作数不能为0,否则会报错! (0乘任何数都为0)

在讲C语言的时候,我们就说过,自古以来有个约定,返回值为0为正常退出,非0则为异常退出。所以在除法或者取模时,右操作数是万万不可出现 0 的!

1.2 复合运算符

这种运算符呢,常见的有: += -= *= /= %= >>= 等等...

他们会将操纵的结果最后赋值给左操作数。

public class TestDemo {
    public static void main(String[] args) {
        int a = 1;
        a += 1; // 相当于 a = a + 1;
        System.out.println(a); //2
        a -= 1; // 相当于 a = a - 1;
        System.out.println(a); //1
        //...... *=  /=  %= 就不一一演示了
    }
}

但是其实这里我们要有几个注意的点:

如果当我们不同类型使用符合运算符时会自动发生类型转换,不需要我们手动强制类型转换。

public class TestDemo {
    public static void main(String[] args) {
        //如果不同类型使用符合运算符会自动类型转换
        int a = 10;
        double b = 10.5;
        a += b; //等价于 -> a = (int)(a + b);
    }
}

如果当我们使用时发现运算符优先级有歧义怎么回事?比如 a += b * 3;

public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        a *= 3 + 2; //等价于 -> a = a*(3+2) 这里先把 3+2 的值算出来在乘 a 
        System.out.println(a); //50 
    }
}

只有变量才能使用符合运算符做左值,常量是不可以的,因为他不可被修改!

1.3 自增自减运算符

相信大家对于自增自减运算符并不少见,但是在Java中确实还是有跟C语言不同的地方的,我们接着往后看:

public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        b = ++a; // a = a + 1; b = a;
        System.out.println(a); //11
        b = a++; // b = a; a = a + 1;
        System.out.println(a); //12
    }
}

至于单独使用 ++a,或者a++,他们的效果是一样的,这个我就不多说,但是我们这里主要是区别前置++和后置++他们赋值的情况。

  • 前置++: 先自身值增加1,然后赋值
  • 后置++: 先赋值,然后自身值增加1。

但是这里又有一个小问题,如果有人闲的无聊,把a++的值再次赋值给a,会发生什么情况呢?

这里就跟C语言不一样了,C语言中如上代码算出的结果是 11,如果看过我C语言深度解剖专栏符号篇的,在那我们已经从汇编的角度去演示过他们的底层逻辑了,只不过在 Java 中我们很少去关注底层,这里我们注意一下就行,其实以后也基本不会碰到这种后置自增之后给自己赋值的代码,也不用太过于纠结,我们有个认识就行。

注意:常量不能使用前置或后置++运算符

2、关系运算符

关系运算符这一块跟C语言基本一致,主要以下六个: == != >= <= > <

但是在Java中我们要区分跟C语言不同的点,前面我们强调过, Java中不存在 0为假 非0为真 ,说白了,以上六个关系运算符,其计算的结果为 ture 或者 false 并不是 0 或者 1。

public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println(a > b);  //如果a大于b,输出true 否则 输出false
        System.out.println(a < b);  //如果a小于b,输出true 否则 输出false
        System.out.println(a == b); //如果a等于b,输出true 否则 输出false
        System.out.println(a != b); //如果a不等于b,输出true 否则 输出false
        System.out.println(10 >= 15); //如果10大于或等于15,输出true 否则 输出false
        System.out.println(10 <= 15); //如果10小于或等于15,输出true 否则 输出false
    }
}

我们学编程语言,有些地方显然是不能跟数学一模一样的,就比如说: 10 < a < 15 ,这样写是错误的,因为 10 < a 的结果是 ture 或者 false 其中任何一个结果都不能跟 15 去比较的。

注意:关系运算符两边可以出现常量

3、逻辑运算符

3.1 逻辑 && 和 逻辑 | |

逻辑运算符显然也是很不陌生的,但是在Java中逻辑运算符 && || 左右表达式的结果必须是 boolean 类型,而且整个表达式的运算结果也是 boolean 。

例: 表达式1 && 表达式2 ,要求: 表达式1 和 表达式2 的运算结果是 boolean 类型

1 && 5 -> 这个是错误的!!!

  • &&:当运算符两边表达式的结果都为 true,则整体为 true
  • | | :当运算符两边表达式有一个结果为 true,则真题为 true

短路现象:

  • &&:当运算符左边表达式为 ,则不执行右边表达式,称为短路现象
  • | | :当运算符左边表达式为 ,则不执行右边表达式,称为短路现象
  • 如果 & 和 | 按位运算符两边表达式的值也为 true 或者 flase他们也表示逻辑运算,但不支持短路!
public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println((a > 10) && (a / 0 > 2)); //这里 除数为0并不会报错,因为&&出现了短路
        System.out.println((a < 20) || (a / 0 > 2)); //这里 除数为0并不会报错,因为||出现了短路
    }
}

以上代码就是逻辑与和逻辑或出现的短路现象,我们前面学习到,除数一定不能是0,否则程序会异常,但是我们上面代码可以通过,最主要原因是他们发生短路并不会去执行运算符右边的表达式,感兴趣的可以下来试一试,如果没出现短路,程序是肯定会出现异常的。

3.2 逻辑非!

int a = 10;
        System.out.println(!(a == 10)); //取非就将 true 变为 false
        //err:System.out.println(!a); 操作数结果必须为布尔值

这个就很简单了,主要注意一点,!的右边表达式结果必须为布尔值。

4、位运算符

我们知道计算机中最小的存储单位是字节,但是数据最小的操作单位是比特位,一个字节等于八个比特位,也就是八位二进制,位运算符是针对数据二进制位按位操作的。

4.1 按位与(&)和按位或( | )

由于这一块跟C语言基本一致,所以我们就大概的过一遍即可:

  • 按位与(&):如果两个二进制位都是 1, 则结果为 1, 否则结果为 0。
  • 按位或 (|): 如果两个二进制位都是 0, 则结果为 0, 否则结果为 1。

1 & 2:

1 的二进制补码:0000 0000 0000 0001

2 的二进制补码:0000 0000 0000 0010

------ 按位与 结果: 0000 0000 0000 0000 -> 对应十进制:0

1 | 2 :

1 的二进制补码:0000 0000 0000 0001

2 的二进制补码:0000 0000 0000 0010

------ 按位或 结果: 0000 0000 0000 0011 -> 对应十进制:3

4.2 按位异或(^)和按位取反(~)

  • 按位异或(^):如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1 。
  • 按位取反(~):将数值的二进制位取反,如果该位为 0 则转为 1, 如果该位为 1 则转为 0。

1 ^ 3 :

1 的二进制补码:0000 0000 0000 0001

3 的二进制补码:0000 0000 0000 0011

---按位异或结果: 0000 0000 . 0000 0010 -> 对应十进制:2

5 ^ 0 :

5 的二进制补码:0000 0000 ... 0000 0101

0 的二进制补码:0000 0000 ... 0000 0000

---按位异或结果: 0000 0000 ... 0000 0101 -> 对应十进制:5

结论:任何数异或0都等于它本身,相同的数异或结果为0

按位取反具体大家可以自己下来写一下,将补码每位都取反,然后判断符号位,在转换成对应的原码即可知道取反后的值。

5、移位运算符

Java中的移位运算符比C中多了一个,具体我们下面讲,但是跟C语言并没什么太大的区别这里我们简单提一下:

  • 左移操作符 <<: 二进制位向左移动 N 位,每次移动一次时最低位补0 -> 左移相当于原数字乘2的N次方
  • 右移操作符 >>: 二进制位向右移动 N 位,每次移动一次时最高位补符号位 -> 右移相当于原数字除上2的N次方
  • 无符号右移操作符 >>>: 二进制位向右移动 N 位,每次移动一次时最高位补0

这里我们来看一段有意思的代码:

很明显这段代码是进行两个数的平均值的,至于为什么会是这样,大家可以结合上下文,画画图或者分析一下,也可以想这样求平均值好处是什么?锻炼独立思考的能力,我就不过多说明了。

6、条件运算符

这个也是Java中唯一一个三目操作符了,它的用法跟C语言很想,但是也是有一点点小区别,毕竟Java中是true表示真,false表示假。

用法:布尔表达式1?表达式2 : 表达式3

解释:如果表达式1的结果为true则执行表达式2,如果为false则执行表达式3

public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = a > b ? (a += 10) : (b += 10);
    }
}

注意:表达式2和表达式3最好是同类型的,除非他们可以发生隐式类型转换,整个表达式的结果不能单独存在,必须要拿变量接收或者使用。

单独存在三目操作符是错误的:a > b ? a : b;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值