以下哪些代码段( A和B低于)更有效(性能明智)以及为什么?
此外:
编译器是否重新排列validate()
方法调用,以便在需要时调用#34;"即在评估if语句中的每个单独条件时?换句话说,编译器是否将片段A视为片段B?
是否有其他替代方案(除了代码A和B)以获得更好的性能?
(validate(...)
检查字段(作为参数提供)是否包含有效值
代码段A:
boolean okTitle = validate(inputTitle);
boolean okLocation = validate(inputLocation);
boolean okDuration = validate(inputDuration);
boolean okReminder = validate(inputReminder);
boolean okRepetition = validate(inputRepetition);
boolean okDate = validate(inputDate);
if(okTitle && (okLocation || okDuration || okReminder || okRepetition || okDate)){
setEnabled(true);
}else{
setEnabled(false);
}
代码段B
setEnabled(
validate(inputTitle) &&
( validate(inputLocation) || validate(inputDuration) || validate(inputReminder) || validate(inputRepetition) || validate(inputDate) )
);
答案 0 :(得分:2)
在这些情况下,通常情况下,输入在95%的时间内有效和/或验证方法很快:如果是这样的话,任何一种方法都可以正常工作。
如果输入通常无效和/或如果验证方法很慢并且您经常调用那段代码,那么您可能想要使用第二种方法,并确保首先测试无效的最可靠原因,快速退出条件代码。
答案 1 :(得分:1)
与编译器无关,代码的执行方式取决于运行时的输入值。
Snippet B肯定会比片段A更好地表现性能,因为A会执行所有的validate()调用,但B会在条件满足时停止。
当我年轻时,由于性能优势,我肯定更喜欢B而不是A.现在,如果validate()方法不是真的“昂贵”调用,我肯定会选择A,因为它比B更易读,更容易维护。
答案 2 :(得分:1)
编译器会将代码段A视为代码片段B
不,由于short circuiting,它们不是等效的代码。如果你在if语句中有validate(...)
个调用,那么它就是等价的,可以比较字节码,看看编译器是否有同样的想法
使用javac Test.java && java Test && javap -c Test
public class Test
{
public static void main(String[] args)
{
int a = 5;
System.out.println(a > 2 && (a < 6 || a < 4));
}
}
打印true
和字节码:
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
2: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
5: iload_1
6: iconst_2
7: if_icmple 25
10: iload_1
11: bipush 6
13: if_icmplt 21
16: iload_1
17: iconst_4
18: if_icmpge 25
21: iconst_1
22: goto 26
25: iconst_0
26: invokevirtual #3 // Method java/io/PrintStream.println:(Z)V
29: return
}
public class Test
{
public static void main(String[] args)
{
int a = 5;
if(a > 2 && (a < 6 || a < 4))
System.out.println(true);
else
System.out.println(false);
}
}
按预期打印true
,字节码:
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
2: iload_1
3: iconst_2
4: if_icmple 28
7: iload_1
8: bipush 6
10: if_icmplt 18
13: iload_1
14: iconst_4
15: if_icmpge 28
18: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
21: iconst_1
22: invokevirtual #3 // Method java/io/PrintStream.println:(Z)V
25: goto 35
28: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
31: iconst_0
32: invokevirtual #3 // Method java/io/PrintStream.println:(Z)V
35: return
}
因此,即使逻辑流相同,它也会生成较少的字节码以避免使用if语句
(对于这个编译器,无论如何,使用Oracle的jdk8)