zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java 基础面试题——运算符

2023-09-27 14:25:45 时间

1.& 和 && 的区别是什么?

(1)&&:逻辑与运算符。当运算符左右两边的表达式都为 true,才返回 true。同时具有短路性,即如果第一个表达式为 false,则直接返回 false,不再判断第二个表达式。

(2)&:逻辑与运算符按位与运算符
按位与运算符:用于二进制的计算,只有对应的两个二进位均为1时,结果位才为1 ,否则为0。
逻辑与运算符:& 在用于逻辑与时,和 && 的区别是不具有短路性。所在通常使用逻辑与运算符都会使用 &&,而 & 更多的适用于位运算。

2.谈一谈 Java 中的移位运算符?

(1)移位运算符是最基本的运算符之一,几乎每种编程语言都包含这一运算符。移位操作中,被操作的数据被视为二进制数,移位就是将其向左或向右移动若干位的运算。移位运算符只作用于整形变量,分为两类,第一类是 long 类型,long 类型长度为 8 字节 64 位;第二类为 int 类,int 长度为 4 字节 32 位,short、byte、char 在做移位之前会自动转换为 int 型,因此与 int 规则一致, 在做完移位运算后,short、byte、char类型都将变成 int 型数据(转换过程中需要考虑高位丢失的问题)。

对于大数据的 2 进制运算,位移运算符比普通运算符的运算要快很多,因为只需对二进制数进行移位,而不用计算,这样即可以提高效率,也能节省资源。

(2)Java 中有以下 3 种移位运算符:

  • 左移运算符 <<:向左移若干位,高位丢弃,低位补零
  • 右移运算符 >>:向右移若干位,高位补符号位,低位丢弃
  • 无符号右移 >>>:无符号右移,忽略符号位,空位均用 0 补齐,最终结果必为非负数。

(3)下面结合几个例子来说说明它们的用法。

  • 左移运算符 <<
int a = 10;
//在不溢出的情况下,下面的代码等价于 int b = a * 2;
int b = a << 1;
System.out.println(a);      // 10
System.out.println(b);      // 20
System.out.println(Integer.toBinaryString(a));      // 1010
System.out.println(Integer.toBinaryString(b));      // 10100
System.out.println();

//在不溢出的情况下,下面的代码等价于 int b = a * (2^3) = a * 8 = 80;
int c = a << 3;
System.out.println(a);      // 10
System.out.println(c);      // 80
System.out.println(Integer.toBinaryString(a));      // 1010
System.out.println(Integer.toBinaryString(c));      // 1010000
  • 右移运算符 >>
int a = 10;
//在不溢出的情况下,下面的代码等价于 int b = a / 2;
int b = a >> 1;
System.out.println(a);      // 10
System.out.println(b);      // 5
System.out.println(Integer.toBinaryString(a));      // 1010
System.out.println(Integer.toBinaryString(b));      // 101
  • 无符号右移 >>>
int a = -10;
int b = a >>> 1;
System.out.println(a);      // -10
System.out.println(b);      // 2147483643
System.out.println(Integer.toBinaryString(a));      // 11111111111111111111111111110110
System.out.println(Integer.toBinaryString(b));      // 1111111111111111111111111111011

(4)如果移位的位数超过数值所占有的位数时,会怎样处理?
当 int 类型左移/右移位数大于等于 32 位操作时,会先求余 (%) 后再进行左移/右移操作。也就是说左移/右移 32 位相当于不进行移位操作(32 % 32 = 0),左移/右移 42 位相当于左移/右移 10 位(42 % 32 = 10)。当 long 类型进行左移/右移操作时,由于 long 对应的二进制是 64 位,因此求余操作的基数也变成了 64。也就是说:x << 42 等同于 x << 10,x >> 42 等同于 x >> 10,x >>> 42 等同于 x >>> 10。

int a = 10;
int b = a << 42;
int c = a << 10;
System.out.println(a);      // 10
System.out.println(b);      // 10240
System.out.println(c);      // 10240
System.out.println(Integer.toBinaryString(a));      // 1010
System.out.println(Integer.toBinaryString(b));      // 10100000000000
System.out.println(Integer.toBinaryString(c));      // 10100000000000

参考文章:Java中的移位运算符

3.a = a + b 与 a += b 有什么区别吗?

+= 操作符会进行隐式自动类型转换,此处 a += b 隐式地将加操作的结果类型强制转换为持有结果的类型,而 a = a + b 则不会自动进行类型转换。

byte a = 1;
byte b = 2; 
b = a + b; 		//报编译错误,不兼容的类型: 从 int 转换到 byte 可能会有精度损失
b += a;			//ok

同理,以下代码有也错误:

short s1= 1;
s1 = s1 + 1;	//报编译错误,不兼容的类型: 从 int 转换到 short 可能会有损失

short 类型在进行运算时会自动提升为 int 类型,也就是说 s1 + 1 的运算结果是 int 类型,而 s1 是 short 类型,从 int 转换到 short 可能会有精度损失,所以会报编译错误。正确写法如下:

short s1= 1;
s1 += 1;

+= 操作符会将右边的表达式结果强转为匹配左边的数据类型,所以没错。

其实,s1 += 1 相当于 s1 = (short)(s1 + 1),有兴趣的可以自己编译下这两行代码的字节码,你会发现是一样的。