加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-16 18:59:01 所属栏目:安全 来源:网络整理
导读:偶然发现了 def foo(f: Int = Unit) {}def foo(f: Long = Unit) {} 因为方法foo定义了两次而没有编译.我知道上面只是一个简写 def foo(f: Function1[Int,Unit]) {}def foo(f: Function1[Long,Unit]) {} 并且在类型擦除之后,两种方法都具有相同的签名. 现在我
偶然发现了

def foo(f: Int => Unit) {}
def foo(f: Long => Unit) {}

因为方法foo定义了两次而没有编译.我知道上面只是一个简写

def foo(f: Function1[Int,Unit]) {}
def foo(f: Function1[Long,Unit]) {}

并且在类型擦除之后,两种方法都具有相同的签名.

现在我已经在Try out specialized Function1/Function2 in 2.8.0 RC1!中读到,自Scala 2.8以来,Function1和Function2具有Int,Long和Double的@specialized版本.这肯定意味着Function [Int,Unit]和Function [Long,Unit]在JVM级别具有单独的类文件.

那么两个签名都不会有所不同吗?

问题是,第二种类型的参数会继续被删除吗?但同样的问题

class Bar[@specialized T]
def foo(f: Bar[Int]) {}
def foo(f: Bar[Long]) {}

它没有编译.

解决方法

@specialized与类型擦除无关,至少在这种情况下.这意味着将使用位置中的本机类型生成类的额外版本.这显着节省了装箱/拆箱.

所以你定义一个类,如:

class MyClass[@specialized(Int) T] {
  def foobar(t: T) = {}
}

并且你得到两个类作为输出,(大约):

class Foobar[java.lang.Object] {
  def foobar(t: java.lang.Object) = {}
}

class Foobar[int] {
  def foobar(t: int) = {}
}

您需要有两个类的实现,因为您不能总是保证将调用具有正确本机类型的实现. 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() {}
}

所以你的类型擦除问题不会被@specialized修复.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读