bin*_*ADa 6 scala type-erasure
偶然发现了
def foo(f: Int => Unit) {}
def foo(f: Long => Unit) {}
Run Code Online (Sandbox Code Playgroud)
由于没有编译method foo is defined twice.我知道上面只是一个简写
def foo(f: Function1[Int, Unit]) {}
def foo(f: Function1[Long, Unit]) {}
Run Code Online (Sandbox Code Playgroud)
并且在类型擦除之后,两种方法都具有相同的签名.
现在我已经阅读了在2.8.0 RC1中尝试专用的Function1/Function2!这Function1和Function2拥有@specialized的版本Int,Long并Double在Scala 2.8.这无疑意味着,Function[Int, Unit]并且Function[Long, Unit]有独立的类文件在JVM的水平.
那么两个签名都不会有所不同吗?
问题是,第二种类型的参数会继续被删除吗?但同样的问题
class Bar[@specialized T]
def foo(f: Bar[Int]) {}
def foo(f: Bar[Long]) {}
Run Code Online (Sandbox Code Playgroud)
它没有编译.
@specialized与类型擦除无关,至少在这种情况下.这意味着将使用位置中的本机类型生成类的额外版本.这显着节省了装箱/拆箱.
所以你定义一个类,如:
class MyClass[@specialized(Int) T] {
def foobar(t: T) = {}
}
Run Code Online (Sandbox Code Playgroud)
并且你得到两个类作为输出,(大约):
class Foobar[java.lang.Object] {
def foobar(t: java.lang.Object) = {}
}
class Foobar[int] {
def foobar(t: int) = {}
}
Run Code Online (Sandbox Code Playgroud)
您需要有两个类的实现,因为您不能总是保证将调用具有正确本机类型的实现.scala编译器将选择要调用的编译器.请注意,java编译器不知道这种特化正在发生,因此必须调用unspecialized方法.
实际上,输出如下(通过JAD):
public class MyClass implements ScalaObject {
public void foobar(Object obj) { }
public void foobar$mcI$sp(int t) {
foobar(BoxesRunTime.boxToInteger(t));
}
public MyClass() { }
}
public class MyClass$mcI$sp extends MyClass {
public void foobar(int t) {
foobar$mcI$sp(t);
}
public void foobar$mcI$sp(int i) { }
public volatile void foobar(Object t) {
foobar(BoxesRunTime.unboxToInt(t));
}
public MyClass$mcI$sp() {}
}
Run Code Online (Sandbox Code Playgroud)
所以你的类型擦除问题不会被@specialized修复.