有是的差异。使用元组的方法实际上是调用一个提取器(unapply
方法),这会在运行时产生成本。第二种方法肯定更快。
要了解差异,请参阅两种方法的反编译,以显示两种方法。你可以清楚地看到第一种方法如何导致更多的操作。
这里需要注意的一点很重要,第一个表达式需要自动装箱到java.lang.Integer
(因为Tuple2
接受对象),而第二个表达式使用的是没有装箱的值。
public void m1(java.lang.String);
Code:
0: new #16 // class scala/Tuple2
3: dup
4: aload_1
5: invokevirtual #22 // Method java/lang/String.length:()I
8: invokestatic #28 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
11: aload_1
12: iconst_1
13: iconst_2
14: invokevirtual #32 // Method java/lang/String.substring:(II)Ljava/lang/String;
17: invokespecial #35 // Method scala/Tuple2."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
20: astore_3
21: aload_3
22: ifnull 75
25: aload_3
26: invokevirtual #38 // Method scala/Tuple2._1$mcI$sp:()I
29: istore 4
31: aload_3
32: invokevirtual #42 // Method scala/Tuple2._2:()Ljava/lang/Object;
35: checkcast #18 // class java/lang/String
38: astore 5
40: new #16 // class scala/Tuple2
43: dup
44: iload 4
46: invokestatic #28 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
49: aload 5
51: invokespecial #35 // Method scala/Tuple2."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
54: astore 6
56: aload 6
58: astore_2
59: aload_2
60: invokevirtual #38 // Method scala/Tuple2._1$mcI$sp:()I
63: istore 7
65: aload_2
66: invokevirtual #42 // Method scala/Tuple2._2:()Ljava/lang/Object;
69: checkcast #18 // class java/lang/String
72: astore 8
74: return
75: new #44 // class scala/MatchError
78: dup
79: aload_3
80: invokespecial #47 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V
83: athrow
public void m2(java.lang.String);
Code:
0: aload_1
1: invokevirtual #22 // Method java/lang/String.length:()I
4: istore_2
5: aload_1
6: iconst_1
7: iconst_2
8: invokevirtual #32 // Method java/lang/String.substring:(II)Ljava/lang/String;
11: astore_3
12: return
}
字节代码不能说明整个故事。你必须看看JVM优化器对这件事做了什么。它可能完全可以优化它。这并不难:Scala.js优化器可以做到这一点,所以如果JVM也做到这一点,我不会感到惊讶。 – sjrd 2014-09-22 04:41:01
@sjrd感谢您的留言。 JVM可能可以优化其中的一部分。在该行的10000个调用之后,它应该能够摆脱'throw'指令,也许还有演员阵容。但是,请注意,我没有提到性能存在差异。我不得不衡量它说。我只是指出了理论上的差异,帮助人们更好地理解Scala是如何工作的,揭示了编译器隐藏的东西。 – 2014-09-22 09:20:32
对不起,我说我没有提到性能,但我确实做到了。其实,我不认为JVM可以优化整个表达式。在编译阶段,Scala.js应该能够做到这一点。但是由于Scala编译器没有这样做,我不认为JVM会忽略分配对象和装箱值的指令。请检查我的拳击更新。 – 2014-09-22 09:27:20