第1部分 i++ 与 ++i 的区别
这两个的区别大部分人都知道,就简单提一下 i++ 是先进行赋值操作,后进行自增操作;而 ++i 是先进行自增操作,后进行赋值操作,举个栗子
int i = 1;
int j;
j = ++i; // 此时是先自增 i 的值再赋值给 j
System.out.println("j = " + j); // 输出:j = 2
// 此时 i 已经变为 2
j = i++; // 此时是先给 j 赋值,再自增 i
// 此时 i 已经变为 3
System.out.println("j = " + j); // 输出:j = 2 (因为上面 i 已经自增过一次了)
第2部分 i++ (或者 ++i )与 i = i + 1 、 i += 1 的区别
计算方式区别
如果变量 i 是 int 、 long、float 和 double 类型(此处简称为情况1)(对,float 和 double 是可以进行自增操作的,后面的 char 也可以),那么在计算方式上,三者差别不大,但是如果是short 、 byte 或者 char 类型(此处简称为情况2),三者就能体现出差别了 (我就知道可能会有人问其他数据类型,所以把基本数据类型都试了一遍,别问为什么没有boolean,因为boolean不能这么操作)
在情况2下,若直接 i = i + 1; Java是会报错的(不是Exception,而是Error,程序就没法执行),报错内容如下:
Error: java: 不兼容的类型: 从int转换到short(byte或者char)可能会有损失
必须要使用强制转换才行,像如下这样
short i = 1;
// j 的类型也可以是 short 或者 int
byte j = 1;
// 另外一提,此处换为 i = (byte) (i + j); 也能改正确执行,因为 byte < short,下面的 j 也可以直接换成数字 1
// 即使 j 也是 short 类型,二者计算也必须使用强制类型转换,因为他们的计算结果是 int 类型的
i = (short) (i + j);
但是使用 i++ (或者 ++i ) 和 i += 1 不会这样报错,相当于就是在计算后自动加了一个强制类型转换,只是你看不到而已,但是 i++(或++i) 和 i += 1这两者相当于是等价的操作,笔者也不知道二者在计算方式上有什么区别,如果有童鞋知道的话欢迎评论区补充
效率分析
笔者在测试效率的时候发现效率差别并不很大,用System.currentTimeMillis();(毫秒)根本看不出来,所以必须要用System.nanoTime();(纳秒 1纳秒=0.000001 毫秒)才能看出来区别,使用for循环增加样本数,减小误差,话不多说,直接上结果!
首先测试的代码如下,代码中 i 的类型,强制类型转换和for循环的次数都是在测试中随动的,为了防止出现强制类型转换类型不符误差和数据超过最大值符号变化带来的误差(笔者也不知道到底会不会有这种误差,反正保险起见就对了)
public static void main(String[] args) {
byte i = 1;
long time1 = 0;
long time2 = 0;
long time3 = 0;
long time4 = 0;
for (int index = 0; index < 25; index++) {
long start1 = System.nanoTime();
i = (byte) (i + 1);
long end1 = System.nanoTime();
time1 += end1 - start1;
long start2 = System.nanoTime();
i += 1;
long end2 = System.nanoTime();
time2 += end2 - start2;
long start3 = System.nanoTime();
i++;
long end3 = System.nanoTime();
time3 += end3 - start3;
long start4 = System.nanoTime();
++i;
long end4 = System.nanoTime();
time4 += end4 - start4;
}
System.out.println("i = i + 1\t用时:" + time1 + "\t\t纳秒");
System.out.println("i += 1\t\t用时:" + time2 + "\t\t纳秒");
System.out.println("i++\t\t\t用时:" + time3 + "\t\t纳秒");
System.out.println("++i\t\t\t用时:" + time4 + "\t\t纳秒");
}
首先测试 byte类型,一次for循环为25次,共执行10次(手动执行,因为不手动执行而是再嵌套一个for),结果如下
i = i + 1 用时:6155 纳秒
i += 1 用时:1472712 纳秒
i++ 用时:6155 纳秒
++i 用时:6156 纳秒
i = i + 1 用时:1017714 纳秒
i += 1 用时:4617 纳秒
i++ 用时:5130 纳秒
++i 用时:6155 纳秒
i = i + 1 用时:5130 纳秒
i += 1 用时:990014 纳秒
i++ 用时:6156 纳秒
++i 用时:5130 纳秒
i = i + 1 用时:6155 纳秒
i += 1 用时:6156 纳秒
i++ 用时:4617 纳秒
++i 用时:2565 纳秒
i = i + 1 用时:5130 纳秒
i += 1 用时:896657 纳秒
i++ 用时:4103 纳秒
++i 用时:5640 纳秒
// 尝试了一次使用for循环和Thread.sleep()的方式来代替手动执行
i = i + 1 用时:2564 纳秒
i += 1 用时:1539 纳秒
i++ 用时:2565 纳秒
++i 用时:885885 纳秒
i = i + 1 用时:3078 纳秒
i += 1 用时:1026 纳秒
i++ 用时:3077 纳秒
++i 用时:1217771 纳秒
// 中途跑了个别的代码
i = i + 1 用时:5643 纳秒
i += 1 用时:4104 纳秒
i++ 用时:1213154 纳秒
++i 用时:5642 纳秒
i = i + 1 用时:5643 纳秒
i += 1 用时:4104 纳秒
i++ 用时:1213154 纳秒
++i 用时:5642 纳秒
// 之后又测试了很多次都是 i++ 最高
之后又测试了short等其他类型,结果都是i++所用的时间最多,感觉是结果在中途尝试了别的方式之后,整个结果就完全变了,导致后面的结果完全一边倒,但是可以根据这些结果看出来这几种方式的值都可能很大,也可能很小,普遍的说法是i++效率高于i += 1 高于i = i + 1的,但是根据实验结果可以看出来这几种方式的用时经常会有某一种突然增高,忽略之后可以说看不出几种计算方式的效率有区别,即使真的有效率区别,也不会很大,纳秒级别的误差可以忽略不计。