以下所有三种方法在功能上都相同 - 但是它们都具有我认为的风格差异。编译它们时,编译器是否会对它们进行不同的处理? (我缺乏检查和理解反编译字节码的技术诀窍)
// Method 1
private boolean isAcceptableRange(final int a, final int b) {
if ((Math.abs(a - b)) <= range) {
return true;
} else {
return false;
}
}
// Method 2
private boolean isAcceptableRange(final int a, final int b) {
if ((Math.abs(a - b)) <= range) {
return true;
}
return false;
}
// Method 3
private boolean isAcceptableRange(final int a, final int b) {
if ((Math.abs(a - b)) <= range)
return true;
return false;
}
我最初的想法是#1将是唯一的,因为额外的else
条款,其中#2和#3将最终相同。这意味着在优化磁盘/ ROM空间效率和可能的指令效率(思考嵌入式)时,请选择#2或#3选项。
或者编译器是否知道最终结果并“优化”它?
答案 0 :(得分:4)
或者编译器是否知道最终结果并且&#34;优化&#34;它走了?
是的,确实如此。让我们看看生成的字节码:
javap -c -private MyClass.class
javap
:是一个工具(除其他外)让你看到java类的字节码,它随JDK一起提供。-c
:将代码反汇编为字节码-private
:显示班级中的私人成员和方法。MyClass.class
:已编译的课程private boolean isAcceptableRange1(int, int);
Code:
0: iload_1
1: iload_2
2: isub
3: invokestatic #1 // Method java/lang/Math.abs:(I)I
6: aload_0
7: getfield #2 // Field range:I
10: if_icmpgt 15
13: iconst_1
14: ireturn
15: iconst_0
16: ireturn
private boolean isAcceptableRange2(int, int);
Code:
0: iload_1
1: iload_2
2: isub
3: invokestatic #1 // Method java/lang/Math.abs:(I)I
6: aload_0
7: getfield #2 // Field range:I
10: if_icmpgt 15
13: iconst_1
14: ireturn
15: iconst_0
16: ireturn
private boolean isAcceptableRange3(int, int);
Code:
0: iload_1
1: iload_2
2: isub
3: invokestatic #1 // Method java/lang/Math.abs:(I)I
6: aload_0
7: getfield #2 // Field range:I
10: if_icmpgt 15
13: iconst_1
14: ireturn
15: iconst_0
16: ireturn
我调用了方法isAcceptableRange1
,isAcceptableRange2
,isAcceptableRange3
。如您所见,所有方法都具有完全相同的字节码。
答案 1 :(得分:2)
我还没看过字节码。但基于我对编译器技术的一般了解:if (condition) {then-part} else {else-part}
会产生看起来基本类似的代码:
if (!condition) branch to Label_1;
perform then-part;
branch to Label_2;
Label_1:
perform else-part;
Label_2:
在您的示例#1中,&#34; then-part&#34;是一个return
语句。并且return
语句的代码可以是return
指令,也可以是子例程代码末尾某点的branch
(包括任何finally
那个有效)然后返回。一个体面的编译器不会在另一个无条件分支或return
指令之后生成一个分支(或任何其他代码),因为该代码永远不会被执行。所以示例#1最终看起来像
if (!condition) branch to Label_1;
set return value to "true";
return or branch to cleanup code;
Label_1:
set return value to "false";
return or branch to cleanup code;
这将是示例#2或#3生成的完全相同的代码。
所以你的问题的答案是:不,编译器不会以不同的方式处理你的任何例子,除非它是一个非常糟糕的编译器。