尽管有@specialized,但由于类型擦除导致重复的方法

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!Function1Function2拥有@specialized的版本Int,LongDouble在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)

它没有编译.

Mat*_*ell 6

@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修复.