par*_*tic 12 autoboxing scala specialized-annotation
为了性能和安全性,我想实现一个固定大小的向量,它既是不可变的又是专用的(我需要快速的算术).我的第一个想法是使用@specialized注释(因为我需要整数和实数).
这是第一次尝试:
package so
class Vec[@specialized A] private[so] ( ary: Array[A] ) {
def apply( i: Int ) = ary(i)
}
Run Code Online (Sandbox Code Playgroud)
但是,当我分析生成的字节码时javap,我可以看到元素仍然是盒装的.例如:
public double apply$mcD$sp(int);
Code:
0: aload_0
1: iload_1
2: invokevirtual #33; //Method apply:(I)Ljava/lang/Object;
5: invokestatic #83; //Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D
8: dreturn
Run Code Online (Sandbox Code Playgroud)
看起来数组并不是专门的,这似乎很愚蠢,因为数组专门用于JVM.
我还能做些什么来实现我的目标吗?
您可能正在查看编译为Vec.class的代码.根据这个线程,专门化发生在子类中.这可以在REPL中验证:
scala> class Vec[@specialized A] ( ary: Array[A] ) {
| def apply( i: Int ) = ary(i)
| }
defined class Vec
scala> new Vec( Array[Int](1) ).getClass
res0: java.lang.Class[_ <: Vec[Int]] = class Vec$mcI$sp
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样,Int它正在使用子类Vec$mcI$sp.如果你在该类上运行javap,你会发现它正确地使代码专门化.这是Vec$mcI$sp.class使用javap时apply方法的样子:
public int apply(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual #13 // Method apply$mcI$sp:(I)I
5: ireturn
Run Code Online (Sandbox Code Playgroud)
我认为这是你想要的Int.