3.1 逻辑 && 和 逻辑 | |
4.1 按位与(&)和按位或( | )
4.2 按位异或(^)和按位取反(~)
在我们C语言深度解剖的专栏已经讲解了一些常见的运算符了,但是基本的 + - * / 没有细说,毕竟那是深度解剖,是在一定基础上更深入学习的,我们 Java 是从 0 基础讲解的,所以这里会涉及到很全面的操作符,由于 Java 很少关注底层,所以我们也不会像讲 C语言的时候那样偶尔去从汇编的角度讲解。
相信大家对于四则运算都不陌生啊, 毕竟谁没做过加减乘除运算,但是这里我们主要是介绍 % 运算符,它与 C语言里的有点区别我们接着往下看:
显然答案是跟我们C语言当中是一模一样的,但是这里我们需要强调一点,以上都是二元操作符,必须拥有两个操作数,不论在C还是在Java中 int / int 的结果是整数,而且是向下取整, 也就是说,会舍去小数位,尽管你是 3.9 他算出的结果仍然是 3 。
注意: 将他们的计算结果转化成 float 或 double 是没有用的,因为结果是取整之后的值。
如果是第一次看到这些结果的你们可能有些意外,我记得C语言中是不能对浮点数取模的啊,在Java中是允许这样操作的,其实上面的例子很简单,就是10以内的除法,如果你能对上面都算准确的话,那么你取模这个运算符肯定是没问题的。
注意:取模和除法时,右操作数不能为0,否则会报错! (0乘任何数都为0)
在讲C语言的时候,我们就说过,自古以来有个约定,返回值为0为正常退出,非0则为异常退出。所以在除法或者取模时,右操作数是万万不可出现 0 的!
这种运算符呢,常见的有: += -= *= /= %= >>= 等等...
他们会将操纵的结果最后赋值给左操作数。
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);
}
}
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
}
}
相信大家对于自增自减运算符并不少见,但是在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++,他们的效果是一样的,这个我就不多说,但是我们这里主要是区别前置++和后置++他们赋值的情况。
这里就跟C语言不一样了,C语言中如上代码算出的结果是 11,如果看过我C语言深度解剖专栏符号篇的,在那我们已经从汇编的角度去演示过他们的底层逻辑了,只不过在 Java 中我们很少去关注底层,这里我们注意一下就行,其实以后也基本不会碰到这种后置自增之后给自己赋值的代码,也不用太过于纠结,我们有个认识就行。
关系运算符这一块跟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 去比较的。
逻辑运算符显然也是很不陌生的,但是在Java中逻辑运算符 && || 左右表达式的结果必须是 boolean 类型,而且整个表达式的运算结果也是 boolean 。
例: 表达式1 && 表达式2 ,要求: 表达式1 和 表达式2 的运算结果是 boolean 类型
1 && 5 -> 这个是错误的!!!
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,否则程序会异常,但是我们上面代码可以通过,最主要原因是他们发生短路并不会去执行运算符右边的表达式,感兴趣的可以下来试一试,如果没出现短路,程序是肯定会出现异常的。
int a = 10;
System.out.println(!(a == 10)); //取非就将 true 变为 false
//err:System.out.println(!a); 操作数结果必须为布尔值
我们知道计算机中最小的存储单位是字节,但是数据最小的操作单位是比特位,一个字节等于八个比特位,也就是八位二进制,位运算符是针对数据二进制位按位操作的。
由于这一块跟C语言基本一致,所以我们就大概的过一遍即可:
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
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
按位取反具体大家可以自己下来写一下,将补码每位都取反,然后判断符号位,在转换成对应的原码即可知道取反后的值。
很明显这段代码是进行两个数的平均值的,至于为什么会是这样,大家可以结合上下文,画画图或者分析一下,也可以想这样求平均值好处是什么?锻炼独立思考的能力,我就不过多说明了。
这个也是Java中唯一一个三目操作符了,它的用法跟C语言很想,但是也是有一点点小区别,毕竟Java中是true表示真,false表示假。
public class TestDemo {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = a > b ? (a += 10) : (b += 10);
}
}
单独存在三目操作符是错误的:a > b ? a : b;