在 2.11 中,字符串和数组的大小仍然是包装的。
你应该训练你的手指打字s.length
and arr.length
.
这并不难,因为字符串和数组都有长度。
从 Java 转向 Scala 的人经常会决定是否使用上面的方法java.lang.String
或方便的增强。因为在我们被要求之前我们有一个有限的“决策预算”用甜甜圈补充它 http://seriouspony.com/blog/2013/7/24/your-app-makes-me-fat在休息室里,作为政策问题,值得提前做出一些决定。
如果大家在午餐或吃甜甜圈时没有更好的话题可以讨论:
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。
It's GenSeqLike
介绍了length
并指定它“产生相同的结果”size
. SeqLike
就是这样实现的。
实际上,String
获得一个size
方法通过增广到SeqLike
, 具体来说,StringLike
。这就需要包裹起来。事实上,预测哪些调用需要包装或分派到扩展方法并不容易。
例如,length
以不需要包装的方式定义。那是因为StringOps
是一个值类。事实上,它编译为String.length
.
但是,那apply
方法上StringOps
,定义为调用charAt
模仿数组 apply,尽管以相同的方式定义,但调用扩展方法。
(当然,一些操作码和分配在 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
, or 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
and 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