我知道这些方法可能被认为是“等效的”或“同义词”,尽管不是“相同的”,根据诸如调用 collection.size 或 collection.length 的最佳 Scala 约定和Scala 缓冲区:大小或长度?.
但这是否意味着它们是相同的?
不要向我提供意见或一成不变的轻率概念。告诉我什么时候它们实际上不一样。
用硬科学支持你的主张!
字节码就足够了。我对特定于 JIT 的优化不太感兴趣。
我对世界的当前状态特别感兴趣,即最近里程碑中的 Scala 2.11。
我知道这些方法可能被认为是“等效的”或“同义词”,尽管不是“相同的”,根据诸如调用 collection.size 或 collection.length 的最佳 Scala 约定和Scala 缓冲区:大小或长度?.
但这是否意味着它们是相同的?
不要向我提供意见或一成不变的轻率概念。告诉我什么时候它们实际上不一样。
用硬科学支持你的主张!
字节码就足够了。我对特定于 JIT 的优化不太感兴趣。
我对世界的当前状态特别感兴趣,即最近里程碑中的 Scala 2.11。
在 2.11 中,String 和 Array 仍然被包装成大小。
你应该训练你的手指打字s.length
和arr.length
。
这并不难,因为字符串和数组都有长度。
从 Java 来到 Scala 的人通常会决定是使用方法java.lang.String
还是方便的扩充。由于在我们被要求用休息室的甜甜圈补充它之前,我们有一个有限的“决策预算” ,因此值得提前做出一些这样的决定作为政策问题。
如果一个人在午餐或甜甜圈上没有什么好讨论的:
22: invokevirtual #41 // Method scala/Predef$.augmentString:(Ljava/lang/String;)Ljava/lang/String;
25: invokespecial #44 // Method scala/collection/immutable/StringOps."<init>":(Ljava/lang/String;)V
28: invokevirtual #47 // Method scala/collection/immutable/StringOps.size:()I
18: invokevirtual #39 // Method scala/Predef$.intArrayOps:([I)Lscala/collection/mutable/ArrayOps;
21: invokeinterface #44, 1 // InterfaceMethod scala/collection/mutable/ArrayOps.size:()I
等等,等等,使用 -optimise 你可能会丢失augmentString。
它GenSeqLike
引入length
并指定它“产生相同的结果”作为size
. SeqLike
以这种方式实现它。
实际上,通过对 a 的扩充来String
获得一个方法,特别是. 这需要包装。事实上,预测哪些调用需要包装或分派到扩展方法并不容易。size
SeqLike
StringLike
例如,length
以不需要包装的方式定义。那是因为StringOps
它是一个值类。事实上,它编译为String.length
.
然而,定义为模拟数组 apply的调用的apply
on 方法虽然以相同的方式定义,但调用了扩展方法。StringOps
charAt
(当然,在 JIT 编译之后,一些操作码和分配可能意义不大。)
scala> val s = "hello"
s: String = hello
scala> val n = s.length ; val i = s.size ; val c = s(4) ; s.slice(0,4)
n: Int = 5
i: Int = 5
c: Char = o
res0: String = hell
scala> :javap -prv -
public $line4.$read$$iw$$iw$();
flags: ACC_PUBLIC
Code:
stack=5, locals=7, args_size=1
0: aload_0
1: invokespecial #32 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #34 // Field MODULE$:L$line4/$read$$iw$$iw$;
8: aload_0
9: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
12: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
length
:
15: invokevirtual #47 // Method java/lang/String.length:()I
18: putfield #22 // Field n:I
21: aload_0
new StringOps
, 或StringOops
:
22: new #49 // class scala/collection/immutable/StringOps
25: dup
26: getstatic #54 // Field scala/Predef$.MODULE$:Lscala/Predef$;
29: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
32: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
35: astore_2
36: astore_1
37: aload_2
StringOps.size
:
38: invokespecial #57 // Method scala/collection/immutable/StringOps."<init>":(Ljava/lang/String;)V
41: invokevirtual #60 // Method scala/collection/immutable/StringOps.size:()I
44: putfield #25 // Field i:I
47: aload_0
48: getstatic #65 // Field scala/collection/immutable/StringOps$.MODULE$:Lscala/collection/immutable/StringOps$;
51: getstatic #54 // Field scala/Predef$.MODULE$:Lscala/Predef$;
54: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
57: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
60: astore 4
62: astore_3
63: aload 4
65: iconst_4
apply
扩展方法:
66: invokevirtual #69 // Method scala/collection/immutable/StringOps$.apply$extension:(Ljava/lang/String;I)C
69: putfield #28 // Field c:C
72: aload_0
73: getstatic #65 // Field scala/collection/immutable/StringOps$.MODULE$:Lscala/collection/immutable/StringOps$;
76: getstatic #54 // Field scala/Predef$.MODULE$:Lscala/Predef$;
79: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
82: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
85: astore 6
87: astore 5
89: aload 6
91: iconst_0
92: iconst_4
和slice
:
93: invokevirtual #73 // Method scala/collection/immutable/StringOps$.slice$extension:(Ljava/lang/String;II)Ljava/lang/String;
96: putfield #31 // Field res0:Ljava/lang/String;
99: return