Java 其中";如果;构造更快-语句还是三元运算符?
java-classic中有两种类型的Java 其中";如果;构造更快-语句还是三元运算符?,java,performance,if-statement,shorthand,premature-optimization,Java,Performance,If Statement,Shorthand,Premature Optimization,java-classic中有两种类型的if语句:if{}else{}和速记:exp?值1:值2。一个比另一个快还是一样 声明: int x; if (expression) { x = 1; } else { x = 2; } 三元运算符: int x = (expression) ? 1 : 2; 两者都不是-它们将编译为相同的字节码。您的两个示例都可能编译为相同或几乎相同的字节码,因此性能应该没有差异 如果执行速度有所不同,您仍然应该使用最惯用的版本(第二个版本用于根据简单条件和
if
语句:if{}else{}
和速记:exp?值1:值2
。一个比另一个快还是一样
声明:
int x;
if (expression) {
x = 1;
} else {
x = 2;
}
三元运算符:
int x = (expression) ? 1 : 2;
两者都不是-它们将编译为相同的字节码。您的两个示例都可能编译为相同或几乎相同的字节码,因此性能应该没有差异
如果执行速度有所不同,您仍然应该使用最惯用的版本(第二个版本用于根据简单条件和两个简单子表达式分配单个变量,第一个版本用于执行更复杂的操作或不适合单行的操作) 这些都是一样的。它们都相当快,通常在10-30纳秒左右。(取决于使用模式)此时间段对您重要吗 你应该做你认为最清楚的事情。这里只有一种类型的“如果”陈述。另一个是条件表达式。至于哪一个性能更好:它们可以编译成相同的字节码,我希望它们的行为相同——或者非常接近,以至于在性能方面你肯定不想选择其中一个 有时,
if
语句更可读,有时条件运算符更可读。特别是,我建议在两个操作数简单且无副作用时使用条件运算符,而如果两个分支的主要用途是它们的副作用,我可能会使用if
语句
下面是一个示例程序和字节码:
public class Test {
public static void main(String[] args) {
int x;
if (args.length > 0) {
x = 1;
} else {
x = 2;
}
}
public static void main2(String[] args) {
int x = (args.length > 0) ? 1 : 2;
}
}
使用javap-c测试反编译字节码
:
public class Test extends java.lang.Object {
public Test();
Code:
0: aload_0
1: invokespecial #1
4: return
public static void main(java.lang.String[]
Code:
0: aload_0
1: arraylength
2: ifle 10
5: iconst_1
6: istore_1
7: goto 12
10: iconst_2
11: istore_1
12: return
public static void main2(java.lang.String[
Code:
0: aload_0
1: arraylength
2: ifle 9
5: iconst_1
6: goto 10
9: iconst_2
10: istore_1
11: return
}
正如你所看到的,字节码在这里有一个细微的差别——不管
历史记录是否发生在分支中(与我之前有严重缺陷的尝试不同:),但如果抖动以不同的本机代码结束,我会非常惊讶。只是为了补充所有其他答案:
第二个表达式通常称为三级/三值运算符/语句。它可能非常有用,因为它返回一个表达式。有时,对于典型的简短语句,它会使代码更清晰。三元运算符比if-else条件更快
public class TerinaryTest {
public static void main(String[] args)
{
int j = 2,i = 0;
Date d1 = new Date();
for(long l=1;l<100000000;l++)
if(i==1) j=1;
else j=0;
Date d2 = new Date();
for(long l=1;l<100000000;l++)
j=i==1?1:0;
Date d3 = new Date();
System.out.println("Time for if-else: " + (d2.getTime()-d1.getTime()));
System.out.println("Time for ternary: " + (d3.getTime()-d2.getTime()));
}
}
公共类TerinaryTest{
公共静态void main(字符串[]args)
{
int j=2,i=0;
日期d1=新日期();
对于(长l=1;我猜这绝对没有区别。只是语法。除非编译器有点邪恶(或其他东西),我错了,对吗(micro)基准测试?分享结果。两者都会得到jit'ed。不会有任何区别。而且不要费心去反编译这些东西。HotSpot做的第一件事就是去掉javac应用的所有优化。它们不是以不同的速度存在的。它们是为不同的目的而存在的。我相信你理解各州之间的区别ts和表达式。语句执行操作。表达式生成值。如果
用于语句。?
用于表达式。+1因为对这个问题的回答值得一读,即使原始问题的意图是错误的。s/conditional statement/conditional expression/我猜你不是指f或者main
和main2
完全相同?令人印象深刻。我直到现在才知道你可以编译字节码。@Kyle:我编译了Java,然后用javap反编译。@Kyle:完全一样。我原以为字节码是一样的。事实上,它几乎是一样的:)这在实践中是一个很好的例子:在Java中,如果我必须根据表达式的结果生成一个字符串final,我可以使用三元语法final String,它的table=(Integer.parseInt(clientId)>500)?“serverClients”:“offlineClients”;然后我可以在需要最终表的位置使用表达式的值。以下内容将是非法的:最终字符串whichTable=“”;if(Integer.parseInt(clientId)>500){whichTable=“serverClients”;}else{whichTable=“offlineClients”;}@jamesperich在final
字段的情况下,可以使用构造函数块来设置值(尽管条件运算符看起来比IMO好10亿倍),并且对于局部变量,您可以在以后的代码块中第一次使用之前分配一个值。我认为三元数比if else
更具优势的唯一情况是调用super(…)
或this(…)
在构造函数中。我在运行示例时得到了完全相反的结果,这表明结果是不可靠的。不幸的是,您陷入了微基准标记陷阱——要正确地进行微基准标记是出了名的困难。对于几个示例,您可以在这里看到:您的特定示例至少受到这些问题的影响问题:4次测试是远远不够的,您总是以相同的顺序运行测试(第一次,如果有,第二次),在运行测试之前不预热JVM,等等。