下面哪个代码段(A和B在下面)更高效(性能更好)?为什么?
此外:
validate()方法调用,以便在“需要时”调用它们,即在计算if-语句中的每个单独条件时?换句话说,编译器会把代码片段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) )
);发布于 2017-12-06 16:29:53
编译器会把代码片段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语句。
(无论如何,这个编译器使用甲骨文的jdk8)
发布于 2017-12-06 16:00:12
在这些情况下,输入通常是有效的,95%的时间和/或验证方法是快速的:如果是这样的话,这两种方法都能正常工作。
如果输入经常无效和/或如果验证方法很慢,并且经常调用该代码,那么您可能希望使用第二种方法,并确保首先测试最有可能的无效原因,以便快速退出条件代码。
发布于 2017-12-06 16:07:16
与编译器无关,代码的执行方式取决于运行时的输入值。
Snippet肯定会比snippet更好的性能,因为A将执行所有calls ()调用,但是B将在满足条件时停止。
当我年轻的时候,我肯定会更喜欢B而不是A,因为我的表现优势。现在,如果validate()方法不是真正的“昂贵”调用,我肯定会选择A,因为它比B更易读和更容易维护。
https://stackoverflow.com/questions/47678473
复制相似问题