5. 运算符

内容导视:

加油,还不算晚。

5.1 算术运算符

内容导视:

5.1.1 四则运算

这个不用过多介绍,分别是加减乘除,操作数是数值类型或者能自动拆箱成数值类型,与初等数学一致,直接使用即可。

int a = 5; int b = 2; int add = a b;// 7 int sub = a - b;// 3 int mult = a * b;// 10 int divide = a / b;// 2

注意 int 类型只能保存整数,会被削去小数部分。

此外 “ ” 除了能够计算加法,操作数可以是 String 类型,用于拼接字符串,只要有一边操作数是 String 类型,则最终结果也是 String 类型,之前已经说过:

System.out.println(100 2 "字符串" 3 * 8);

“102字符串24”;从左至右,遇到字符串就拼接,拼接后还是字符串;乘法优先于加法。

5.1.2 求余数

求余数也称取模。得到的余数一定小于除数。

如 10 % 3 = 1、11 % 3 = 2、12 % 3 = 0;

int i = 11 % 4;

11 除以 4,商为 2,余数为 3;所以 i = 3。

% 的本质

a % b = a - a / b * b

知道了上面的式子,自己试着算一下吧:

System.out.println(-10 % 3); System.out.println(10 % -3); System.out.println(-10 % -3);

计算结果如下:

-10 % 3 = -10 - (-10) / 3 * 3 = -10 - (-3) * 3 = -1 10 % -3 = 10 - 10 / (-3) * (-3) = 10 - (-3) * (-3) = 1 -10 % -3 = -10 - (-10) / (-3) * (-3) = -10 - 3 * (-3) = -1

5.1.3 自增自减

是让变量保存的值,自加一。

int i = 10; i ; System.out.println(i);// i = 11

int i = 10; i; System.out.println(i);// i = 11

放在变量前后的区别

放在变量前:

int i = 10; int j = i; System.out.println(j);// j = 11

等价于

int i = 10; i = (int)(i 1);// 先自加一,后赋值 int j = i; System.out.println(j);// j = 11

放在变量后:

int i = 10; int j = i ; System.out.println(j);// j = 10

int i = 10; int j = i;// 先返回值,后自加一 i = (int)(i 1); System.out.println(j);// j = 10

结论:

当 出现在变量前,先自加一,再返回值;所以 i 自加一等于 11,再赋值给 j,j 为 11;

当 出现在变量后,会先返回值,再自加一;把 i 赋值给 j 即 10,再 i 自加 1。

反正 i 一定是 11;使用 或 -- 时,不会改变运算结果的类型。

例如:

byte b = 1; b = b 1;

会报错从 int 转成 byte 可能会有损失;

换成如下会自动强转成 byte 类型,但是要注意别超了 byte 的取值范围,否则强转后会有精度损失。

byte b = 127; b ;//b = -128

-- 同理:

int i = 3;// i = 3 int j = i--;// j = 3、i = 2 int z = --j;// j = 2、z = 2

i = 2、j = 2、z = 2。

建议 、--,最好单独一行,很直观地就能判断是加一或减一,放在表达式中分不清谁前谁后容易让人困扰。

思考

int i = 10; i = i; System.out.println(i);

这道题,不是那么好讲,使用 Javap -v 反编译(先弹出栈顶的数)看看就行,不用了解,没有人会这么用的。

什么是栈顶,就是容器最上面的一个元素。打个比方,一个空羽毛球筒,现在放入羽毛球 a(称为入栈),此时栈顶是羽毛球 a;现在又放入一个羽毛球 b,b 把 a 压住了,b 在 a 的上面,此时 b 就是栈顶;想要拿出 a,必须先拿出 b(称为弹栈,把最上面的元素取出来),这就是后进先出先进后出

c语言如何使用mq中间件(cqh-运算符)(1)

对代码进行反汇编,反编译后得到的结果:

0: bipush 10 // 将 10 压入操作数栈中 {10} 2: istore_1 // 从操作数栈中弹出一个数也就是 10,存储到第 2 个变量槽 {} {?,10} 3: iinc 1, 1 // 第 2 个变量槽的值自增 1 {} {?,11} 6: iload_1 // 将局部变量表的第 2 个变量槽中的值复制到操作数栈顶 {11} {?,11} 7: istore_1 // 将 11 取出,存储到第 2 个变量槽中 {} {?,11}

人话就是:将 10 赋给变量 i,i 自增一为 11,将 11 赋给 i。

下一道题:

int i = 10; i = i ; System.out.println(i);

反编译部分节选:

// int i = 10; 0: bipush 10 // 将 10 压入操作数栈 {10} 2: istore_1 // 将 10 弹出存储到第 2 个变量槽 {} {?,10} 3: iload_1 // 将第 2 个变量槽的值压入操作数栈 {10} {?,10} // i ; 4: iinc 1, 1 // 第 2 个变量槽的值自增 1 {10} {?,11} // i = 10; 7: istore_1 // 将 10 弹出存储到第 2 个变量槽 {} {?,10} 8: return

可以看到 10 被存储到操作数栈,但没有先赋给 i,而是 i 自增为 11 后,再将 10 赋给 i。

例 3:

byte b = 1; byte b1 = b ;// b1 = 1,b = 2 byte b2 = --b;// b = 1,b2 = 1 System.out.println(b);// 1 System.out.println(b1);// 1 System.out.println(b2);// 1

反编译部分节选:

// byte b = 1; 0: iconst_1 # 将 1 压入栈中 {1} 1: istore_1 # 弹栈,存储到第 2 个变量槽中 {} {?,1} // b1 = b, b = (byte)(b 1); 2: iload_1 # 将第 2 个变量槽的值压入操作数栈 {1} {?,1} 3: iload_1 # 将第 2 个变量槽的值压入操作数栈 {1,1} {?,1} 4: iconst_1 # 将 1 压入栈中 {1,1,1} {?,1} 5: iadd # 取出栈中最上面两个值相加,并将结果 2 压入栈中 {2,1} {?,1} 6: i2b # 将 int 类型的值转为 byte,然后又扩展至 int 类型压入栈中 {2,1} {?,1} 7: istore_1 # 弹栈,存储到第 2 个变量槽中 {1} {?,2} 8: istore_2 # 弹栈,存储到第 3 个变量槽中 {} {?,2,1} // b = (byte)(b - 1), b2 = b; 9: iload_1 # 将第 2 个变量槽的值压入栈中 {2} {?,2,1} 10: iconst_1# 将 int 类型的常量 1 压入栈中 {1,2} {?,2,1} 11: isub # 取出栈中最上面两个值相减:2 - 1,并将结果 1 压入栈中 {1} {?,2,1} 12: i2b # 将 int 类型的值转为 byte,... {1} {?,2,1} 13: istore_1# 弹栈,存储到第 2 个变量槽 {} {?,1,1} 14: iload_1 # 将第 2 个变量槽的值压入栈中 {1} {?,1,1} 15: istore_3# 弹栈,存储到第 4 个变量槽 {} {?,1,1,1} 16: return # 结束。

5.2 赋值运算符

内容导视:

  • 基本赋值运算符
  • 扩展赋值运算符
5.2.1 基本赋值运算符

之前用过很多次了,通过 “=” 把值赋给变量,完成值传递。

int a = 10;// 10 被赋给了 int 类型的 a

int j = 10; int i = j;// j 保存的 10 被赋给了 int 类型的 i

5.2.2 扩展赋值运算符

扩展赋值运算符: =、-=、*=、/=、%=、...

只要学会了 =,其它触类旁通。

int x = 5; x = 2;// x = 7

相当于将自保存的值加 2:

int x = 5; x = (int)(x 2);// x = 7

使用扩展运算符,不会改变运算结果类型,与 一样, 就等同于 = 1。

看看下面的 i 的值为多少?

byte i = 8; i *= 2;

i = (byte)(i * 2) = 16。

例 2:

byte b = 64; b *= 2;

b = (byte)(b * 2) = (byte)128 = -128;

例 3:

byte b = 23; b %= 2;

b = (byte)(b % 2) = 1;

例 4:

byte b = 13; b /= 2;

b = (byte)(13 / 2) = 6;

5.3 关系运算符

就是判断对错,得到一个结果。结果为真,返回 true,假:false。

使用的符号都是英文半角符号,字符之间没有空格。

!= != ! = 都错。

内容导视:

  • 数字比较运算符
  • 判等运算符
5.3.1 数字比较运算符

<、<=、>、>=,要求运算符两边是数值类型,或者可以自动拆箱为数值类型,得到的布尔字面量使用 boolean 类型的变量接收。

boolean result1 = 6 > 3; boolean result2 = 9 < 6; System.out.println(result1);// true System.out.println(result2);// false

特殊情况

  • 如果有一边操作数是 NaN,则结果就是 false。
  • Infinity 是正无穷大,大于所有有穷值,-Infinity 是负无穷大,小于所有有穷值。
5.3.2 判等运算符

分为 == 和 !=,对应等于和不等于。[1]

数值类型的判等

当两边的操作数都是数值类型,或者其中之一是数值类型,且另一个可以自动拆箱转为数值类型,按数值大小比较。

System.out.println(5 == 5);// true,5 等于 5,返回 true System.out.println(5 == new Integer(5));// true,Integer 自动拆箱为 5 System.out.println(5 != 4);// true System.out.println('a' == 95);// false,'a' 对应十进制整数为 97

当判等运算符的两边之一是 NaN,则 == 结果为 false,!= 结果为 true,换言之 NaN 不等于任何数,包括它自己。如果 x != x 为 true,则 x 的值为 NaN。

final double NaN = 0.0 / 0.0; System.out.println(NaN == NaN);// false System.out.println(NaN != NaN);// true System.out.println(NaN == 3);// false System.out.println(NaN != 3);// true

Infinity 除了与自己比较时,== 为 true,与其它值比较,== 都为 false。

布尔类型的判等

当两边的操作数都是布尔类型,或者其中之一是布尔类型,且另一个可以自动拆箱转为布尔类型,如果两边都是 true 或者 false,则 == 结果为 true,否则为 false。

如果两边都是 true 或者 false,则 != 结果为 false,否则为 true。

System.out.println(true == true);// true System.out.println(false == false);// true System.out.println(true == false);// false System.out.println(true != true);// false System.out.println(false != false);// false System.out.println(true != false);// true

引用类型的判等

两边的操作数都是引用类型,两边操作数的类型相同或是父子类型。

如果两边的操作数的值都为 null,或都引用相同的对象,则 == 结果为 true,否则为 false。

如果两边的操作数的值都为 null,或都引用相同的对象,则 != 结果为 false,否则为 true。

String str1 = null; Object str2 = null; System.out.println(str1 == str2);// true System.out.println("hello" == "hello");// true System.out.println("hello1" == "hello");// false

关于 String 类型的比较可查看 “2.3.5 解析 -> 字符串类型字面量解析”,其它引用类型的比较等到面向对象吧。


[1] 注意别把 “==” 与 “=” 混用了。我知道在日常生活中,使用 “=” 判断是否相等,但是在程序里 “=” 是用来赋值的,“==” 才是用来判断是否相等。

我举个例子,if 旁边的括号中的值只允许为 boolean 类型,当值为 true 时,才会执行 if {} 中的语句。

int i = 4; if (i = 5) { System.out.println("Hello"); }

假如你的原意是想 i 等于 5 时,就输出 “Hello”,但是由于你使用的是单等号,代表赋值,此时的 i = 5,所以原意成了

int i = 4; if (5) { System.out.println("Hello"); }

在 Java 中,正好 boolean 类型不能参与转换,所以编译时直接报错,你可以及时发现,但不是次次都是这么好运气。

如下:

boolean b1 = false; if (b1 = true) { System.out.println("Hello");// Hello } System.out.println(b1);// true

原意是当 b1 等于 true 时,输出 “Hello”,但是你的意图被扭曲了,这只是你不小心丢了一个等号而已。

在 JDK 源码中,经常看到赋值、判断混合在一起,令人头晕,完全可以单独提取出来,可读性会好些。

你的原意可能如下:

boolean b1 = false; if (b1 == true) { System.out.println("Hello"); } System.out.println(b1);// false

说了这么多,只为说一句:判断两个值是否相等,请用 “==”。但是我私底下或写注释时,还是习惯用单等号代表两个值相等。

5.4 逻辑运算符

内容导视:

  • 异或

前提:逻辑运算符的两边要求都是布尔类型,且最终的结果也是布尔类型,下面是我高中时记的口诀:

and 与(&):一假为假

or 或(|):一真为真

not 非(!):真即假,假即真

xor 异或(^):不同为真,相同为假

5.4.1 逻辑与

a & b:当 a 和 b 同时为 true 时,结果才为真,否则为 false。

boolean b1 = 5 > 3; boolean b2 = 8 < 9; System.out.println(b1 & b2);// true

翻译成人话:5 大于 3 且 8 小于 9,命题为真。

需要注意的是,不同的运算符优先级不同,优先级高的先运算。之前通过乘法与加法的混合运算中就能看出来乘法优先。

思考如下输出结果:

boolean b1 = 1 < 0; boolean b2 = 79 > 99; boolean b3 = false; System.out.println(b1 & b2 == b3);

b1、b2、b3 都为 false;b1 & b2 为 false,false == b3,所以结果为 true?

但你没有想到 “==” 的优先级高于 “&”,所以是 b2 == b3 先运算结果为 true,b1 & true,结果为 false。

上面的一句相当于:

System.out.println(b1 & (b2 == b3));// false

那该怎么办?扭曲了原意!可以加小括号提升优先级:

System.out.println((b1 & b2) == b3);// true

短路与

&&(short circuiting)相比于逻辑与,效率更高:如果整个表达式结果已经确定,就停止并返回结果,剩下式子不再执行与判断。

什么意思?

一假为假,当左边的值为 false 时,还需要去执行去判断右边吗?完全可以推出结果为 false。

int x = 3; System.out.println((x < 2) & ( x > 3)); System.out.println(x);// 4

int x = 3; System.out.println((x < 2) && ( x > 3)); System.out.println(x);// 3

x < 2 为 false,那么整个式子已经可以确定为 false,不需要再判断。通过上面的例子可以看出,短路与并没有去执行右半部分的 x,所以 x 的结果不变,还是为 3。利用短路可以省去不必要的计算,从而提高效率。

5.4.2 逻辑或

a | b:当 a 和 b 同时为 false 时,结果才为 false,否则为 true。

System.out.println(8 < 1 | 9 > 3);// true

命题:8 小于 1 或者 9 大于 3,命题为真。

与 & 一样的是,| 也有对应的 ||。

短路或

如果整个表达式的结果已经确定,后面不再执行判断。

int x = 3; System.out.println(8 < 9 | x == 8); System.out.println(x);// 4

int x = 3; System.out.println(8 < 9 || x == 8); System.out.println(x);// 3

一般我们使用的是短路与、短路或,我几乎没有看见单个的,除非你想把所有的式子都执行一遍。

5.4.3 非

!a:对 a 取反;a 为 true,则结果为 false;a 为 false,结果为 true。

System.out.println(!(3 < 5));// false

3 < 5 为 true,再取反为 false。

5.4.4 逻辑异或

a ^ b:当 a 不等于 b,结果为 true,否则为 false。

System.out.println(8 < 9 ^ 9 > 3);// false System.out.println(8 < 9 != 9 > 3);// false

8 < 9 为 true,9 > 3 为 true,它们相等,所以为 false。

很少见,一般使用 !=。

5.5 条件运算符

算是条件语句的简化版吧,可以根据表达式的真假返回不同的值。

条件运算符又称三目运算符、三元运算符,因为有三个操作数。[1]

语法:布尔值 ? 值1 : 值2;

当布尔值为 true,返回值 1;为 false,返回值 2。

boolean isBoy = true; char zhangSan = isBoy ? '男' : '女'; System.out.println(zhangSan);// 男

double scope = 99.5; String evaluate = scope < 60 ? "不及格" : "及格"; System.out.println(evaluate);// 及格

很明显 scope 小于 60 为 false,所以返回值2,“及格”。

三目运算符与之后讲的 if-else 类似,但是它是有返回结果的,而 if-else 没有。

[1] 与此对应的二元运算符(如 !=、==、<、 ...)、一元运算符( 、--)。

5.6 按位运算符

内容导视:

  • 按位与
  • 按位或
  • 按位异或
  • 按位取反

前提:要求操作数是整数类型。

按位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整数类型。

除按位取反(一元运算符)外,其它按位运算符可以与 “=” 组合成扩展赋值运算符。如 &=,x &= 2; 相当于 x = (?)(x & 2);

? 是 x 的类型。

5.6.1 按位与

参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。

int x = 2 & 3;

首先写下它们的补码 2 的补码是 00000000 00000000 00000000 00000010 3 的补码是 00000000 00000000 00000000 00000011 比较结果: 00000000 00000000 00000000 00000010

所以 x = 2。

5.6.2 按位或

参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为那个数自己。

int x = 3 | 4;

3 的补码:... 00000011 4 的补码:... 00000100 比较结果:... 00000111

x = 7。

5.6.3 按位异或

参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位不同时,结果为 1,否则为 0。

int x = 9 ^ 12;

9 的补码:... 00001001 12 的补码:... 00001100 比较结果: ... 00000101

x = 5。

特性

x ^ y ^ y = x;

x ^ y ^ x = y;

int x = 9; int y = 15; int a = x ^ y ^ y; int b = x ^ y ^ x;

9 的补码: 00001001 15 的补码: 00001111 9 ^ 15: 00000110 (9^15)^15:00001001 (9^15)^9: 00001111

可以利用此特性,完成两整数交换:

int a = 3; int b = 9; a = a ^ b;// a = 3 ^ 9 b = a ^ b;// b = 3 ^ 9 ^ 9 = 3 a = a ^ b;// a = 3 ^ 9 ^ 3 = 9

5.6.4 按位取反

只对一个操作数进行运算,将操作数的二进制中的 1 改为 0,0 改为 1。

byte b = ~0;

0 的补码:00000000 00000000 00000000 00000000 取反: 11111111 11111111 11111111 11111111 是 -1 的补码,所以 b = -1;

例 2:

byte b = ~1;

1 的补码:00000000 00000000 00000000 00000001 取反: 11111111 11111111 11111111 11111110 是 -2 的补码,b = -2;

例 3:

b = ~ -128;

-128 的原码:10000000 00000000 00000000 10000000 反码: 11111111 11111111 11111111 01111111 补码: 11111111 11111111 11111111 10000000 取反: 00000000 00000000 00000000 01111111 是 127 的补码,b = 127;

推测:~x = -x - 1;

引子:

5 (-6) 对应的补码为 5 的补码 -6 的补码 = 00000101 11111010 = 11111111 所以补码 11111111 对应的值是 5 (-6) = -1

证明:* 代表未知,# 代表对 * 取反后的二进制位。

设正数 x,补码、原码、反码为:0******* ~x = 1####### 现在只要求补码 1####### 对应的值即可 -x - 1 = -x (-1) -x 的原码是 1******* -> 反码 1####### -> 补码 1####### 00000001 -1 的原码是 10000001 -> 反码 11111110 -> 补码 11111111 -x (-1) 对应的补码为: = 1####### 00000001 11111111 = 1####### (00000001 11111111) = 1####### 00000000 = 1####### 所以补码 1####### 对应的值是 -x - 1

设负数 x,原码为 1*******,反码 1#######,补码 1####### 00000001 ~x = 11111111 - (1####### 00000001) = 0******* - 00000001 现在只要求补码 0******* - 00000001 对应的值即可 -x 是正数,原码、反码、补码为 0******* -x - 1 = -x (-1) 对应的补码为: = 0******* 11111111 = 0******* 11111111 00000001 - 00000001 = 0******* 00000000 - 00000001 = 0******* - 00000001 0******* - 00000001 对应的值是 -x - 1

当 x 为 0 和 -128 时,取反也是 -x - 1。

5.7 移位运算符

移位运算符主要用来对操作数二进制的位进行移动,其操作数和运算结果都是整数类型。

可以与 “=” 组合成扩展赋值运算符。

内容导视:

  • 左移位运算符
  • 有符号右移位运算符
  • 无符号右移位运算符
5.7.1 左移位运算符

左移位运算符为 <<,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。

byte b = 4 << 2;

4 的补码:00000000 00000000 00000000 00000100 左移两位:00000000 00000000 00000000 00010000 是 16 的补码,b = 16;

例 2:

byte b = 3 << 4;

3 的补码:00000000 00000000 00000000 00000011 左移四位:00000000 00000000 00000000 00110000 是 48 的补码,b = 48;

规律:x << n = x * 2 ^ n。

5.7.2 有符号右移位运算符

对于正数, >> 会把所有的位右移,并在最前面补 0; 对于负数, >> 会把所有的位右移,并在最前面补 1。

byte b = 3 >> 1;

3 的补码 00000000 00000000 000000000 00000011 右移一位:00000000 00000000 000000000 00000001 是 1 的补码,所以 b = 1;

例 2:

byte b = -4 >> 2;

-4 的补码:11111111 11111111 11111111 11111100 右移 2 位:11111111 11111111 11111111 11111111 是 -1 的补码,所以 b = -1;

规律:x >> n = x / 2 ^ n。

我有时使用 x >> 1 代替 x / 2 的操作。

如 7 >> 1 = 7 / 2 = 3;

int start = 3; int end = 9; int mid1 = (start end) / 2; int mid2 = start (end - start) / 2; int mid3 = start ((end - start) >> 1); System.out.println(mid1);// 6 System.out.println(mid2);// 6 System.out.println(mid3);// 6

注意移位运算符没有算术运算符优先级高,所以需要加小括号提升优先级,否则 int mid3 = start (end - start) >> 1 = 3 6 >> 1 = 9 >> 1 = 4;

5.7.3 无符号右移位运算符

将所有位数右移,最前面补 0。

byte b = (byte)(-4 >>> 2);

-4 的补码:11111111 11111111 11111111 11111100 右移 2 位:00111111 11111111 11111111 11111111 是 1073741823 的补码,超出 byte 的取值范围 截去前面 3 个字节得到:11111111 是 -1 的补码,所以 b = -1;

例 2:

int i = -8 >>> 5;

-8 的补码:11111111 11111111 11111111 11111000 右移 5 位:00000111 11111111 11111111 11111111 是 134217727 的补码,i = 134217727;

例 3:

773 = 0x0305;使用两个字节 0x03、0x05 保存。

byte b1 = 0x03; byte b2 = 0x05; System.out.println(b1 << 8 | b2);

3 的补码: 00000000 00000000 00000000 00000011 左移 8 位:00000000 00000000 00000011 00000000 5 的补码: 00000000 00000000 00000000 00000101 按位或: 00000000 00000000 00000011 00000101 是 773 的补码,输出 773

5.8 运算符优先级

优先级高的先运算。

优先级从高到低 . () -- ~ ! 单目运算符 * / % 算术运算符 - << >> >>> 位移运算符 < > <= >= instanceof 比较运算符 == != 逻辑运算符 & ^ | && || ? : 三目运算符 = *= /= %= 赋值运算符 = -= <<= >>= >>>= &= ^= |=

例如:int a = 1 2 * 1; 先算乘法,接着加法,最后赋值。

int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; boolean f = true; boolean g = false; boolean h = g & f == e < d << c b / a;

g & f == ? 先算 f == ? f == e < ? 先算 e < ? e < d << ? 先算 d << ? d << c ? 先算 c ? c b / ? 先算 b / ? b / a 先算 a,先 ,a = 2,后返回值 2 b / 2 = 1; c 1 = 4; d << 4 = 64; e < 64 为 true f == true 为 true g & true 为 false 所以 h = false

5.x 总结回顾

使用 、--、 = 等扩展赋值运算符时不会改变运算结果类型。(使用了强制转换运算符,可能会造成精度损失)

判断两个基本类型的值是否相等请用 “==”。

逻辑运算符中一般使用短路与、短路或。

一定要注意不同运算符之间的优先级,最好亲自测一下,看是否与预期一致,或者直接加小括号提升优先级。

5.y 课后习题

5.1 double i = 5 / 2; 中的 i 的值为?

5.2 输出什么?

1)

String s = "张三"; int i = 3; System.out.println(s i * 2 "b");

2)

int x = 5; int y = 5; System.out.println( x < 6); System.out.println(y < 6); System.out.println(y);

3)

int x = 10; int a = x (x ); int b = x ( x); System.out.println(a); System.out.println(b); System.out.println(x);

4)

int i = 34; int j = i--; int z = --i; System.out.println(i); System.out.println(j); System.out.println(z);

5)

int i = 2; int j = 2 i ; System.out.println(i); System.out.println(j);

6)

boolean b = false; System.out.println(b = true); System.out.println(b == false);

7)

int x = 9; int y = 12; int z = x < y ? x y : x - y; System.out.println(z);

8)

int a = 10; int b = 99; int result = a > b ? a : b--; System.out.println(result); System.out.println(a); System.out.println(b);

5.3 利用三目表达式求出三个数之间的最大数。

5.4 利用所学知识求出 33 天是多少个星期零几天?

5.5 3 / 9 * (242.2 - 100) 的结果是什么?

5.6 下面代码输出什么?

1)

boolean x = true; boolean y = false; byte num = 2; if ((num == 2) && (y = true)) {num ;} if ((x = false) || ( num == 5)) {num ;} System.out.println(num); System.out.println(x); System.out.println(y);

2)

int i = 342; int b = i i; System.out.println(b);

3)

int i = 342; int b = i i; System.out.println(i); System.out.println(b);

5.z 习题答案

5.1 double i = 5 / 2; 中的 i 的值为?

5 / 2 = 2,再自动升级成 double 类型,所以 i = 2.0。


5.2 输出什么?

1)

String s = "张三"; int i = 3; System.out.println(s i * 2 "b");

"张三" 3 * 2 "b"

先算乘法,所以输出 张三6b

2)

int x = 5; int y = 5; System.out.println( x < 6); System.out.println(y < 6); System.out.println(y);

先 ,x = 6,再判断,输出 false;先判断 5 < 6,输出 true,再 ,y = 6,输出 6。

3)

int x = 10; int a = x (x ); int b = x ( x); System.out.println(a); System.out.println(b); System.out.println(x);

a = 10 10 = 20,x 后为 11;b = 11 12 = 23,x 为 12。输出 20、23、12。

4)

int i = 34; int j = i--; int z = --i; System.out.println(i); System.out.println(j); System.out.println(z);

j = 34,后--,i = 33;先--,i = 32,z = 32。输出 32、34、32。

5)

int i = 2; int j = 2 i ; System.out.println(i); System.out.println(j);

j = 2 2 = 4,随后 i 自加一为 3,输出 3、4

6)

boolean b = false; System.out.println(b = true); System.out.println(b == false);

b = true,输出 b 的值:true。true 等于 false 为假,输出 false。

7)

int x = 9; int y = 12; int z = x < y ? x y : x - y; System.out.println(z);

9 < 12 为 true,返回 x y = 21,赋给 z,输出 21。

8)

int a = 10; int b = 99; int result = a > b ? a : b--; System.out.println(result); System.out.println(a); System.out.println(b);

10 > 99 为 false,返回 b--:先将 b 的值 99 赋给 result,后 b--,b = 98。输出 99、10、98。


5.3 利用三目表达式求出三个数之间的最大数。

先定义三个变量保存数值,先让其中两数比较,返回大值赋给 max1;再让 max1 与剩下的数比较返回大值。

int n1 = 241; int n2 = 324; int n3 = 242; int max1 = n1 > n2 ? n1 : n2; int max2 = max1 > n3 ? max1 : n3; System.out.println(max2);

5.4 利用所学知识求出 33 天是多少个星期零几天?

让 33 除以 7,商就是星期数,余数就是天数。

int day = 33; int week = day / 7; int RemainDay = day % 7; System.out.println(day "天是" week "个星期零" RemainDay "天");

5.5 3 / 9 * (242.2 - 100) 的结果是什么?

因为 3 / 9 = 0,所以结果为 0;要想不偏离原意,请至少把其中一个数转为 double 类型。


5.6 下面代码输出什么?

1)

boolean x = true; boolean y = false; byte num = 2; if ((num == 2) && (y = true)) {num ;} if ((x = false) || ( num == 5)) {num ;} System.out.println(num); System.out.println(x); System.out.println(y);

只有 if () 中为 true,才会执行 {} 中的语句。

直接快进到 if 语句 num == 2: 先判断 num 是否等于 2,为 true 再自加一,num = 3;此时不能断定结果,继续看右边 y = true:给 y 赋值为 true 两边条件都为 true,&& 后的结果为 true,执行 num num = 4 接着看第 2 个 if 语句 x = false:给 x 赋值 false 既然 x 为假,不能断定结果,继续看第 2 个条件 num == 5: 先自加一,num = 5 再判断 num 是否等于 5,为 true 两个条件一假一真,|| 后的结果为 true,执行 num num = 6 输出 6、false、true

2)

int i = 342; int b = i i; System.out.println(b);

先 i,i = 343,再赋值:b = 343 343 = 686。

3)

int i = 342; int b = i i; System.out.println(i); System.out.println(b);

i i 先进行加法运算再自加一 即 342 (i),此时 i 后,i = 343 现在再看右边的 i,先自加一,即 i = 344,再运算 int b = 342 344 = 686 i = 344 输出 344、656

例 1:

int i = 342; i = i i ; System.out.println(i);

先进行加法运算 342 i ,后自加 1,i = 343 先进行加法运算 342 343 后 i 自加 1,i = 344 计算 342 343 = 685 再赋给 i,输出 685

0: sipush 342 {342} 3: istore_3 {} {?,?,?,342} 4: iload_3 {342} {?,?,?,342} 5: iinc 3, 1 {342} {?,?,?,343} 8: iload_3 {342,343} {?,?,?,343} 9: iinc 3, 1 {342,343} {?,?,?,344} 12: iadd {685} {?,?,?,344} 13: istore_3 {} {?,?,?,685}

第 2 个例子:

int i = 342; i = i i; System.out.println(i);

先进行加法运算 342 i,后自加 1,i = 343 i 先自加一,i = 344,再进行加法运算 342 344 = 686 i = 686

第 3 个例子:

int i = 342; i = i i; System.out.println(i);

先自加一,i = 343,得到:343 i 先自加一,i = 344,得到:343 344 = 687 i = 687

像极了茴香豆的“茴”有几种写法,大家看个乐呵就行。

,