Java面试复习之Java深入解析二

运算符与表达式

  1. 贪心规则:在分析符号时,编译器会尽可能多的结合有效的符号。i+++j的运算就是(i++)+j。如果不贪心,“\1717”就会出现二义性,“\17”和“17”,因此,转义符就会失去作用。编译器会将“\1717”解析为“\171”和“7”。
  2. i++和++i之间的区别:在java中,两者都是先对值加1,然后再参与运算。只不过i++在加1前会先将值复制一份作为临时变量,然后用临时变量参与运算。可以用一下代码进行验证:
int i=5;
i=i++;
System.out.println(i);

结果

5

深层次的理解:前置++直接将变量的值+1,然后使用这个变量的值。后置++是先将变量的值压栈(暂时保存起来),然后将变量加1,再使用压栈的值参与运算。

3.相除与求余:

相除:

整型0除0,产生异常;浮点0除0,不会产生异常,结果为NAN。NAN不等于任何值,包括自身。可以用Float中的isNaN来判断是否是一个NaN。

System.out.println(0.0/0.0);
System.out.println(0.0/0.0==NaN);
System.out.println(Double.isNaN( 0.0/0.0));

运行结果为:

NaN
false
true

除法运算规则:

  • 两个操作数均为0或infinity时,结果为NaN;有NaN参与的运算,结果均为NaN。
  • 相除结果的符号与两操作数的符号有关,相同为正,不同为负。
  • 0做被除数结果为0;0做除数结果为无穷。
  • 无穷做被除数结果为无穷;无穷做除数结果为0。

求余:

  • 有NaN参与的求余结果均为NaN;无穷作为被除数时,结果为NaN;正负0作为除数时结果为NaN。
  • 余数的符号与被除数的符号相同。
  • 余不过,得自身。

4.+0与-0的异同:在数值上是相等的,用==来比较也返回true。但是在参与浮点运算时,会产生不一样的结果。+0和-0在存储中,符号为是不同的。Java的某些类也把+0和-0视为两个不同的数。在Float类中的compare方法里+0大于-0。

System.out.println(Float.compare(+0f,-0f));

结果返回1。
5.位移运算符:byte、short、char参与时会自动提升至int,结果也为int。如果将int(long)类型移动超过31(64)位,就会把有效数全移走了。所以,当操作符右侧的数大于31(63)时,系统做了处理。取右侧数的补码的低5(6)位进行操作。
右移与相除区别:相除时会向0舍入。而右移只会向下舍入。正数时,除法和右移都是向下舍入。负数时,除法是向上舍入,右移是向下舍入。如下:

System.out.println(-3/2);//向0舍入,结果为-1
System.out.println(-3>>1);//向下舍入,结果为-2

结果

-1
-2

“>>>”表示无符号右移,最高位是用0来填充。“>>”最高位用符号为来填充。一个负数经过无符号右移后变成正数

System.out.println(-1>>>1);

结果

2147483647

byte类型的-1经过无符号右移(一位一位移,不管移动多少次)后还是-1。因为byte参与运算时要扩展位int。-1的补码全为1,符号位为1,扩展后为32个1。无符号右移一位后,最高位补0。使用“>>>=”时会自动进行类型转换,因此右移后的int类型要截取低八位转回byte类型。

byte b=-1;
byte b1=b>>>=1;
System.out.println(b>>>1);//运算后为int类型
System.out.println(b1);//运算后将byte类型赋值给b1

运行结果

2147483647
-1

6.三目运算符:表达式1?表达式2:表达式3;
表达式1必须为boolean或者可以通过拆箱转化为boolean的包装器Boolean类型
7.从左向右的计算顺序:代码如下

int[] a={0,0,0,0,0,0};
int i=1,j=3;
a[++i]=i++;//相当于a[2]=2,i=3;
a[j]=j=4;//相当于a[3]=4,j=4
System.out.println("i="+i+"\tj="+j);
System.out.println(Arrays.toString(a));

运行结果

i=3	j=4
[0, 0, 2, 4, 0, 0]

复合赋值运算符会自动进行隐式类型转换,b+=1相当于b=(byte)(b+1)。复合赋值运算符在进行运算时,也是按照从左向右的规则。运算前,先会确定左侧的操作数,将左侧的操作数保存起来,左侧的操作数不会受到右侧的表达式的影响而造成改变。

byte b=2;
b+=2;
b+=b++;//b=b+b++
System.out.println(b);

运行结果

8

8.三种交换变量的方式:

  • 第一种:通过第三个变量来备份某一个变量实现交换
int a=2,b=5;
int c;
c=a;
a=b;
b=c;
System.out.println("a="+a+"\t\tb="+b);
  • 第二种:通过相加的方式
int a=2,b=5;
int c=a+b;
a=c-a;
b=c-b;//也可以写成b=c-a;
System.out.println("a="+a+"\t\tb="+b);
  • 第三种:通过异或的方式,如果对x异或y两次,结果为x。
int a=2,b=5;
a=a^b;
b=a^b;//相当于b=a^b^b,异或两次后变回原值
a=a^b;//相当于a=a^b^a,对b异或两次还是b

9.switch语句表达式:可以使byte、short、char、int四种基本类型或这四种基本类型的包装器类型。也可以使枚举类型或字符串类型。会先计算表达式,然后和case中的值进行比较。然后执行case后面的所有语句。所以在当前case语句末尾要加break。
switch对字符串类型的处理:遇到字符串时,会先将switch语句拆分为两个switch语句。第一个switch语句根据对象的哈希吗来对一个临时变量赋值,第二个switch会根据临时变量的值来匹配case表达式的值。

猜你喜欢

转载自blog.csdn.net/Hello_1024/article/details/83187676