运算符

算术运算符

算术运算符包括: +, -, *, /, %, ++, --

+

当左右两边都是数值型时, 则做加法运算.

当左右两边只要有一方为字符串, 则做拼接运算. 任何一个 Java 对象都可以转换为字符串.

如果 + 作用于字符, 就将字符转为整数进行计算.

程序示例:

public static void main(String[] args) {
System.out.println(100 + 86); // 186
System.out.println("100" + 86); // 10086
System.out.println(100 + 3 + "Hello"); // 103Hello
System.out.println("Hello" + 100 + 3); // Hello1003
System.out.println(3.7 + "hello"); // 3.7hello
System.out.println("abc" + true); // abctrue
System.out.println('中' + "abc" + true); // 中abctrue
System.out.println('a' + 'b'); // 195
System.out.println('a' + "b"); // ab
}

代码 System.out.println(100 + 3 + "Hello"); 中, 加法从左到右依次进行.

程序示例:

public static void main(String[] args) {
String s1 = "天龙八部";
String s2 = "笑傲江湖";
String s3 = s1 + s2;
System.out.println(s3); // 天龙八部笑傲江湖
char ch1 = '男';
char ch2 = '女';
// char ch3 = ch1 + ch2; // Type mismatch: cannot convert from int to char
System.out.println(ch1 + ch2); // 52906
double num1 = 123.56;
double num2 = 100.11;
double num3 = num1 + num2;
System.out.println(num3); // 223.67000000000002
}

/

除法分为整数除法和浮点数除法. 当两个操作数都是整数时, 执行整数除法, 否则执行浮点数除法.

两个整数相除, 即便除不尽, 小数部分也会直接丢弃而不是四舍五入. 浮点数参与除法运算, 即便数学上能除得尽, 结果也是浮点数.

程序示例:

public static void main(String[] args) {
// 两个整数相除, 即便除不尽, 小数部分也会直接丢弃而不是四舍五入
System.out.println(10 / 4); // 2
double num1 = 10 / 4;
int num2 = 10 / 4;
System.out.println(num1); // 2.0
System.out.println(num2); // 2
// 浮点数参与除法运算, 即便数学上能除得尽, 结果也是浮点数
System.out.println(8.0 / 4); // 2.0
double num3 = 8.0;
int num4 = 4;
double num5 = num3 / num4;
System.out.println(num5); // 2.0
// int num6 = num3 / num4; // Type mismatch: cannot convert from double to int
}

整数被 0 除将产生一个异常, 而浮点数被 0 除将会得到一个无穷大或 NaN 结果.

程序示例:

// 整数被 0 除将产生一个异常, 而浮点数被 0 除将会得到一个无穷大或 NaN 结果
public class DivideDemo {
public static void main(String[] args) {
// System.out.println(10 / 0); // Exception in thread "main" java.lang.ArithmeticException: / by zero
System.out.println(10.0 / 0); // Infinity
System.out.println(-10.0 / 0); // -Infinity
System.out.println(0.0 / 0); // NaN
System.out.println(-0.0 / 0); // NaN
System.out.println(0.0 / 0.0); // NaN
System.out.println(0 / 0.0); // NaN
}
}

%

% 的结果根据公式计算: a % b = a - a / b * b

可以简单记忆: 取模的结果的正负号和第一个运算数相同.

程序示例:

public static void main(String[] args) {
System.out.println(10 % 3); // 1
System.out.println(-10 % 3); // -1
System.out.println(10 % (-3)); // 1 , -3 可以不要括号
System.out.println(-10 % (-3)); // -1 , -3 可以不要括号
}

程序示例:

public static void main(String[] args) {
int all_days = 59;
int weeks = 59 / 7;
int days = 59 % 7;
System.out.println(all_days + " 天等于 " + weeks + " 星期 " + days + " 天."); // 59 天等于 8 星期 3 天.
}

% 可以作用于浮点数.

如果 a % b 中的 a 是浮点数, 那么 a % b = a - (int)a / b * b

程序示例:

System.out.println(-10.5 % 3); // -1.5
System.out.println(10.5 % -3); // 1.5
System.out.println(-10.4 % 3); // -1.4000000000000004, 说明结果可能是一个近似值

++

语句 ++i;i++; 独立使用时, 效果和 i = i + 1 完全一致.

程序示例:

public class ArithmeticOperatorExcercise01 {
public static void main(String[] args) {
int i = 1;
i = i++; // temp = i; i = i + 1; i = temp;
System.out.println(i); // 1
int j = 1;
j = ++j; // j = j + 1; temp = j; j = temp;
System.out.println(j); // 2
}
}

很多程序员认为前缀和后缀这种行为容易让人困惑. 在 Java 中, 很少在表达式中使用 ++ 和 --.

算术运算遇到小数有可能计算结果不精确.

程序示例:

public class test {
public static void main(String[] args) {
System.out.println(1.1 + 1.01); // 2.1100000000000003
System.out.println(1.1 - 1.01); // 0.09000000000000008
System.out.println(1.1 * 1.01); // 1.1110000000000002
}
}

获取一个整数各个位置的值的公式:


图 1

程序示例:

import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入一个三位数整数: ");
int input = sc.nextInt();
int a = input % 10;
int b = input / 10 % 10;
int c = input / 100 % 10;
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}

运行结果:

请输入一个三位数整数: 259
9
5
2

关系运算符

运算符 运算
== 相等
!= 不等
< 小于
> 大于
<= 小于等于
>= 大于等于
instanceof 检查是否是类的对象

关系运算符也叫比较运算符.

关系运算符的结果都是 boolean 型, 也就是要么是 true, 要么是 false.

关系运算符组成的表达式叫做关系表达式.

关系表达式经常用在 if 结构的条件中或循环结构的条件中.

程序示例:

public static void main(String[] args) {
int a = 9;
int b = 8;
boolean flag = a > b;
System.out.println(flag); // true
System.out.println(a < b); // false
// int c = a > b; // Type mismatch: cannot convert from boolean to int
}

逻辑运算符

运算符 运算
& 逻辑与
&& 短路与
| 逻辑或
|| 短路或
!
^ 逻辑异或

逻辑运算符用于连接多个条件表达式.

逻辑运算符的运算结果也是 boolean 类型.

逻辑运算符可以分为两组:

短路与 &&, 短路或 ||, 取反 !

逻辑与 &, 逻辑或 |, 逻辑异或 ^

a & b: & 叫逻辑与, 规则: 当 a 和 b 同时为 true, 则结果为 true, 否则为 false.

a && b: & 叫短路与, 规则: 当 a 和 b 同时为 true, 则结果为 true, 否则为 false.

a | b: 叫逻辑或, 规则: 当 a 和 b 只要有一个为 true, 则结果为 true, 否则为 false.

a || b: || 叫短路或, 规则: 当 a 和 b 只要有一个为true, 则结果为 true, 否则为 false.

!a: 叫取反, 或者非运算. 当 a 为 true, 则结果为 false, 当 a 为 false, 则结果为 true.

a ^ b: 叫逻辑异或, 当 a 和 b 不同时, 则结果为 true, 否则为 false.

区分逻辑与 & 和短路与 &&: 仅当第一个条件为 false 时, 这两个运算符有区别. 当第一个条件为 false 时, 整个表达式一定为 false, 此时短路与 && 将不再执行第二个表达式, 而逻辑与 & 将继续执行第二个表达式. 实际使用中一般都用短路与, 因为效率更高.

程序示例:

public static void main(String[] args) {
int a = 10;
int b = 1;
if (a < 1 && ++b < 20) { // 第一个条件为 false, 第二个条件不执行
System.out.println("OK");
} else {
System.out.println("NO");
}
System.out.println(b); // 1
if (a < 1 & ++b < 20) { // 第一个条件为 false, 第二个条件仍执行
System.out.println("OK");
} else {
System.out.println("NO");
}
System.out.println(b); // 2
}

区分逻辑或 | 和短路或 ||: 仅当第一个条件为 true 时, 两个运算符有区别. 当第一个表达式为 true 时, 整个表达式一定为 true, 此时短路或 || 将不再执行第二个表达式, 而逻辑或 | 将继续执行第二个表达式. 实际使用中较多使用短路或, 因为效率更高.

程序示例:

public static void main(String[] args) {
int a = 1;
int b = 10;
if (a < 10 || ++b < 20) { // 第一个条件为 true, 第二个条件不执行
System.out.println("OK");
} else {
System.out.println("NO");
}
System.out.println(b); // 10
if (a < 10 | ++b < 20) { // 第一个条件为 true, 第二个条件仍执行
System.out.println("OK");
} else {
System.out.println("NO");
}
System.out.println(b); // 11
}

程序示例:

public static void main(String[] args) {
System.out.println(60 > 20); // true
System.out.println(!(60 > 20)); // false
System.out.println((10 > 1) ^ (10 > 2)); // false
System.out.println((10 < 1) ^ (10 > 2)); // true
}

可以利用短路运算符来避免错误. 例如, 在下面的表达式中:

boolean b = x != 0 && 1 / x > x + y; // no division by 0

如果 x 等于 0, 那么第二部分就不会计算. 因此, 如果 x 为 0, 也就不会计算 1 / x, 就不会出现除以 0 的错误.

赋值运算符

赋值运算符分两类:

基本赋值运算符: =

复合赋值运算符: +=, -=, *=, /=, %=

自增, 自减和复合赋值运算符会进行类型转换.

程序示例:

public class AssignOperator {
public static void main(String[] args) {
byte b = 2;
// b = b + 2; // Type mismatch: cannot convert from int to byte
b += 2; // 等价于 b = (byte)(b + 2)
System.out.println(b); // 4
// b = b + 1; // Type mismatch: cannot convert from int to byte
b++; // 等价于 b = (byte)(b + 1);
System.out.println(b); // 5
}
}

在 Java 中, 赋值是一个表达式 (expression) , 也就是说, 它有一个值, 具体来讲就是所赋的那个值. 可以使用这个值完成一些操作.

程序示例:

public class AssignOperatorDemo {
public static void main(String[] args) {
int x = 1;
int y = x += 4;
System.out.println(y); // 5
}
}

这种嵌套赋值很容易混淆, 应当分别清楚地写出这些赋值:

程序示例:

public class AssignOperatorDemo {
public static void main(String[] args) {
int x = 1;
x += 4;
int y = x;
System.out.println(y); // 5
}
}

条件运算符

基本语法: 条件表达式 ? 表达式1 : 表达式2

如果条件表达式结果为 true, 则整个表达式的值为表达式 1 的值, 否则整个表达式的值为表达式 2 的值. 表达式 1 和表达式 2 只有一个会执行.

程序示例:

public static void main(String[] args) {
int a = 10;
int b = 99;
System.out.println(a > b ? a++ : b++); // 99
System.out.println(a); // 10
System.out.println(b); // 100
System.out.println(a < b ? ++a : ++b); // 11
System.out.println(a); // 11
System.out.println(b); // 100
}

表达式 1 和表达式 2 必须是可以赋给接收变量的类型或者可以进行自动类型转换的.

程序示例:

public static void main(String[] args) {
int a = 10;
int b = 20;
int c = a > b ? a : b;
System.out.println(c); // 20
// short d = a > b ? a : b; // Type mismatch: cannot convert from int to short
short e = a > b ? (short) a : (short) b;
System.out.println(e); // 20
short f = (short) (a > b ? a : b); // 后面的三元运算符表达式要括起来, 否则强制类型转换只对 a 起作用
System.out.println(f); // 20
double g = a > b ? a : b; // 自动类型转换
System.out.println(g); // 20.0
}

三元运算符可以修改为 if - else 语句.

语句 int res = a > b ? a : b; 等价于:

if (a > b) {
int res = a;
} else {
int res = b;
}

程序示例:

// 求三个数中的最大值
public static void main(String[] args) {
int a = 10, b = 20, c = 30;
int tmp;
/*
方法 1
if (a > b) {
tmp = a;
} else {
tmp = b;
}
if (tmp < c) {
tmp = c;
}
*/
/*
方法 2, 最推荐
tmp = a > b ? a : b;
tmp = tmp > c ? tmp : c;
*/
// 方法 3
tmp = (a > b ? a : b) > c ? (a > b ? a : b) : c; // 30
System.out.println(tmp);
}

位运算符

位运算符按位运算, 也会对符号位起作用, 是对补码进行操作的.

Java 中有 7 个位运算符:

&: 按位与, 两位全为 1 时, 结果为 1, 否则结果为 0.

|: 按位或, 两位只要有一个为 1, 则结果为 1, 否则结果为 0.

^: 按位异或: 两位不同时, 即一个为 0 而另一个为 1 时, 结果为 1, 否则结果为 0.

~: 按位取反: 0 变为 1, 1 变为 0.

>>: 算术右移, 低位溢出 (溢出就是扔掉不要了) , 符号位不变, 即用原来的符号位补现在的符号位, 并用 0 补上溢出的其余数字位. 右移一次就是除以 2, 右移两次就是除两次 2.

<<: 算术左移, 符号位不变, 低位补上 0. 左移一次就是乘以 2, 左移两次就是乘以 2 再乘以 2.

>>>: 逻辑右移, 也叫无符号右移, 规则为: 低位溢出, 高位补 0, 即不论正负, 高位一律补 0. 没有 <<<.

程序示例:

public class BitOperator {
public static void main(String[] args) {
System.out.println(2 & 3); // 0010 & 0011 = 0010
System.out.println(~-2); // 1
// -2 原码: 10000000 00000000 00000000 00000010
// -2 反码: 11111111 11111111 11111111 11111101
// -2 补码: 11111111 11111111 11111111 11111110
// ~-2 补码: 00000000 00000000 00000000 00000001, 最高位为 0
// ~-2 反码, 原码与 ~-2 补码相等, 三码合一
System.out.println(~2); // -3
// 2 的原码, 反码, 补码: 00000000 00000000 00000000 00000010
// ~2 的补码: 11111111 11111111 11111111 11111101, 最高位为 1
// ~2 的反码 (~2 的补码减 1): 11111111 11111111 11111111 11111100
// ~2 的原码: 10000000 00000000 000000000 00000011, 等于十进制的 -3
}
}

如果 n 是一个整数变量, 而且 n 的二进制表示中从右边数第 4 位为 1, 则 int fourthBitFromRight = (n & 0b1000) / 0b1000; 会返回 1, 否则返回 0. 利用并结合适当的 2 的幂, 可以屏蔽其他位, 而只留下其中的某一位.

需要建立位模式来完成位掩码时, >><< 运算符会很方便:

int fourthBitFromRight = (n & (1 << 3)) >> 3;

移位运算符的右操作数要完成模 32 的运算 (除非左操作数是 long 类型, 在这种情况下需要对右操作数完成模 64 运算) .

例如, 1 << 35 的值等同于 1 << 3 或 8.

在 C/C++ 中, 不能保证 >> 是完成算术移位 (扩展符号位) 还是逻辑移位 (填充 0) . 实现者可以选择其中更高效的任何一种做法. 这意味着 C/C++ 中的 >> 运算符对负数生成的结果可能会依赖于具体的实现. Java 则消除了这种不确定性.

运算符的优先级


图 1

上一行优先级高于下一行.

只有单目运算符和赋值运算符是从右往左运算的.

与 C 或 C++ 不同, Java 不使用逗号运算符. 不过, 可以在 for 语句的第 1 和第 3 部分中使用逗号分隔表达式列表, 也就是说 Java 中的逗号只作为分隔符而不是逗号运算符.

posted @   有空  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示

目录导航