一道笔试题的思考(一)

1:++操作为什么比+1操作高效,试从内存方面详细解释

都知道编译后++操作的指令比+1的少,所以肯定高效,但具体解释起来还要记住很多东西。++操作主要是通过字节码iinc指令来实现,其意思是:将指定的int型整型变量增加指定值。决定测试一下,以下代码:

                int i = 100;
		i++;
编译成字节码后:


bipush表示将单字节的常量值(-128~127)推送至栈顶,这里插播一句,java内存里面的栈是根据方法来分的,一个方法一个栈帧,一个栈帧里面有变量表,有操作数栈,有程序计数器等,上面的i是存在变量表里面第二个变量里面,因为第一个变量永远是this,bipush就是把常量池里面的100存入操作数栈的栈顶,istore_1指令的意思是:将操作数栈顶的int型数值存入第二个本地变量。所以经过第二步现在的i的值是100.现在看重点i++操作(即iinc 1,1),即将第二个变量(从0开始计数)加1.注意到这个操作是在变量表里面执行,没有通过操作数栈。

再看下面+1的代码:

                int i = 100;
		i = i+1;
编译成字节码后:

一道笔试题的思考(一)
很明显,多了很多条指令,前面2句指令是一样的,但是从第三条开始,iload_1是把第二个局部变量存入操作数栈顶,iconst_1是把常量池中的常量1推送到栈顶,现在操作数栈从栈顶往下的数分别是1和100.iadd是把操作数栈顶的两个整数相加再压入栈顶,现在栈顶变为101,istore_1是把栈顶的元素存入局部变量表中的第二个变量。很容易发现,+1的操作比++的操作多了以操作数栈为中介的步骤,所以效率会比++低。

字节码这一块有很多东西,但是我个人觉得不一定要记忆,不懂的地方去翻看一下就行了,当时我还想到了一个问题,iinc操作是针对整型的,如果是long型呢?会有linc吗? 查了一下,没有这个指令,可是以下的代码是可以执行的,那么它后面的指令会是什么呢?

                long i = 0;
		i++;
编译成字节码后:


ldc2_w #5 跟bipush功能差不多,但是是把长整型推送至栈顶,后面的字节码跟上面第二种情况是一样的,只是把所有的整型操作换成了长整型操作(即把指令前面的i换成l了),并没有linc类似的指令。所以++操作和+1操作对于长整型是一样的,不信的话读者可以编译成字节码试试,对于long型,++操作跟+1操作编译成字节码是一样的。


你可能感兴趣的:(笔试题)