如果您能拥有一个紧凑且高效的解决方案,岂不是很好?事实证明你可以,考虑到 Scala 的@specialized
特征。首先警告:该功能存在一些问题,如果您尝试将其用于过于复杂的操作,则可能会损坏。但对于这个例子来说,它几乎是完美的。
The @specialized
注释为每个基本类型创建单独的类和/或方法,然后每当编译器确定基本类型是什么时调用它而不是泛型版本。唯一的缺点是它完全自动完成所有这些工作 - 您无需填写自己的方法。这有点遗憾,但您可以使用类型类来解决这个问题。
让我们看一些代码:
import java.nio.ByteBuffer
trait BufferWriter[@specialized(Byte,Int) A]{
def write(b: ByteBuffer, a: A): Unit
}
class ByteWriter extends BufferWriter[Byte] {
def write(b: ByteBuffer, a: Byte) { b.put(a) }
}
class IntWriter extends BufferWriter[Int] {
def write(b: ByteBuffer, a: Int) { b.putInt(a) }
}
object BufferWriters {
implicit val byteWriter = new ByteWriter
implicit val intWriter = new IntWriter
}
这给了我们一个BufferWriter
特征是通用的,但我们重写了我们想要的每个特定的原始类型(在本例中Byte
and Int
)并有适当的实施。专业化足够聪明,可以将这个显式版本与其通常用于专业化的隐藏版本联系起来。现在您已经有了自定义代码,但是如何使用它呢?这就是隐式值的用武之地(为了速度和清晰度,我这样做了):
import BufferWriters._
def write[@specialized(Byte,Int) A: BufferWriter](b: ByteBuffer, ar: Array[A]) {
val writer = implicitly[BufferWriter[A]]
var i = 0
while (i < ar.length) {
writer.write(b, ar(i))
i += 1
}
}
The A: BufferWriter
符号意味着为了调用它write
方法,你需要有一个隐式的BufferWriter[A]
便利。我们已经为他们提供了 valsBufferWriters
,所以我们应该设置。让我们看看这是否有效。
val b = ByteBuffer.allocate(6)
write(b, Array[Byte](1,2))
write(b, Array[Int](0x03040506))
scala> b.array
res3: Array[Byte] = Array(1, 2, 3, 4, 5, 6)
如果你把这些东西放在一个文件中并开始探索这些类javap -c -private
您将看到正在使用适当的原始方法。
(请注意,如果您不使用专门化,此策略仍然有效,但必须将循环内的值装箱才能将数组复制出来。)