语法话题
本期的话题如下:
在Java中,a += b与a = a + b两条语句有什么不同?
对于Java初学者来说,可能认为二者是等价的,但实际上,二者还是有一定区别的。
这里,我们使用运算符+与+=来举例,不过,这种区别也适用于更通用的情况,可以认为是:a op= b与a = a op b的区别,其中op=可以是所有的复合赋值运算符:
+= -= *= /= %= <<= >>= >>>= &= ^= |=
区别1——隐式类型转换
设右侧操作数(表达式a + b)的类型为S,左侧操作数a的类型(目标类型)为T,当S与T赋值不兼容时:
- 对于a += b,能够执行一个隐式的类型转换,将a + b的结果类型(S)转换为a的类型(T)。
- 对于a = a + b,则不会执行隐式类型转换,而是产生编译错误。
程序示例如下:
package test;
public class Test {
public static void main(String[] args) {
short a = 0;
int b = 1;
// 可以。能够自动完成隐式转换。
// 相当于执行a = (short)(a + b)
a += b;
// 不可以,会产生编译错误。
// a = a + b;
}
}
区别2——求值次数
当左侧操作数a是通过数组引用来访问元素时(数组访问表达式),例如,x[0],其中,x为数组引用,0为元素索引,此时x[0](整体)就是操作数a:
- 对于a += b,a(数组引用与索引)只会求值(计算)一次。
- 对于a = a + b,a(数组引用与索引)会求值(计算)两次。
程序示例如下:
package test;
public class Test {
private static int[] array = { 1 };
public static void main(String[] args) {
int b = 0;
// getArray()[0]整体作为操作数a。
getArray()[0] += b;
getArray()[0] = getArray()[0] + b;
}
public static int[] getArray() {
System.out.println("getArray()方法执行。");
return array;
}
}
如果注释程序中的第9行,getArray()方法会执行两次,如果保留第9行,注释第10行,则getArray()方法只会执行一次。
知识扩展
扩展1——求值次数的延伸
对于之前的程序,我们进一步修改,将数组索引也通过调用函数来返回,程序修改如下:
package test;
import java.util.Arrays;
public class Test {
private static int index = 0;
private static int[] array = { 1, 2 };
public static void main(String[] args) {
int b = 100;
// getArray()[getIndex()] += b;
getArray()[getIndex()] = getArray()[getIndex()] + b;
System.out.println(Arrays.toString(array));
}
// 声明方法,用来返回数组索引,同时在每次调用后,将索引增1。
public static int getIndex() {
System.out.println("getIndex()方法执行。");
return index++;
}
public static int[] getArray() {
System.out.println("getArray()方法执行。");
return array;
}
}
通过之前的介绍,大家应该都已清楚,对于:
getArray()[getIndex()] += b;
getArray()与getIndex()两个方法只会执行一次,而:
getArray()[getIndex()] = getArray()[getIndex()] + b;
两个方法都会执行两次,不过,当使用简单赋值运算符的时候,数组array元素的值,会是怎样的呢?大家可以试一下,对比结果,看看是否符合自己的预期,并总结原因。
扩展2——非数组类型的求值次数
对于非数组类型,例如,当a与b都是int类型时,对于以下程序,操作数在求值次数上是否存在区别?
package test;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 2;
// 以下两条语句,a分别会求值几次?
a += b;
a = a + b;
}
}