Scala 抽象类型T被取消选中,因为它是通过擦除消除的

Scala 抽象类型T被取消选中,因为它是通过擦除消除的,scala,inheritance,erasure,Scala,Inheritance,Erasure,我正在编写一个扩展Java类的Scala类。我必须扩展这个抽象Java类,因为它包含一些转换器,我需要自己编写一个转换器,可以插入到它们的框架中。因此,下面方法的签名是强加给我的:当我说我的类扩展了它们的抽象类时,它是由Eclipse自动生成的。如果我试图修改方法签名,该类将无法编译,因为“它没有从父级实现抽象方法” 当然,方法的实现是我的选择——但我发现我无法满足类型系统的约束 我需要做一些非常简单的事情:将“None”视为null,并按原样返回任何其他内容。但是我发现我不能用类型安全的方式来

我正在编写一个扩展Java类的Scala类。我必须扩展这个抽象Java类,因为它包含一些转换器,我需要自己编写一个转换器,可以插入到它们的框架中。因此,下面方法的签名是强加给我的:当我说我的类扩展了它们的抽象类时,它是由Eclipse自动生成的。如果我试图修改方法签名,该类将无法编译,因为“它没有从父级实现抽象方法”

当然,方法的实现是我的选择——但我发现我无法满足类型系统的约束

我需要做一些非常简单的事情:将“None”视为null,并按原样返回任何其他内容。但是我发现我不能用类型安全的方式来做这件事。如果我按如下所示编写代码,我会收到一条警告,说“抽象类型T未选中,因为它已通过擦除消除”。我怎样才能消除这种情况

我还想知道,一旦应用擦除,我的代码会是什么样子,即第二个“如果”条件会是什么样子

直觉上,我知道我不能保证在输入为Any时返回T,这就是编译器不高兴的原因。实际上,这是可行的,因为我们只是读取字符串并返回字符串——但是继承声明将方法签名强加给我

  def execute[T](value: Any): T = {
    if (value == null || value == "None") null.asInstanceOf[T]
    // Warning: abstract type T is unchecked since it is eliminated by erasure
    else if (value.isInstanceOf[T]) value.asInstanceOf[T]
    //            warning here: ^
    else null.asInstanceOf[T]
  }

如何实现此方法?

最后,我可以做以下两件事之一:

  • 用Java实现:

    @抑制警告(“未选中”) @凌驾 公共T执行(对象值){ 如果(value==null | |“None”.equals(String.valueOf(value)))返回null; else返回(T)值; }

  • 在Scala中实现并添加@unchecked

    def execute[T](值:任意):T={ 如果(值==null | |值==“无”)为null.asInstanceOf[T] else if(value.isInstanceOf[T@unchecked])value.asInstanceOf[T] else null.asInstanceOf[T] }

  • 我仍然想知道擦除后第二条if语句还剩下什么


    谢谢亚历克的建议

    您的Java解决方案不包含t的测试
    值实例,因此您不需要在Scala解决方案中安装[t]
    。您应该删除它,因为该检查不起任何作用:它会擦除到
    isInstanceOf[Object]
    ,这始终是真的,因此不会执行最后一个
    else
    分支。剩下的区别是,在Java中,您将
    String.valueOf(value)
    “None”
    进行比较,而不是
    value
    本身。因此,Java解决方案的等价物是

    def execute[T](value: Any): T = {
      (if (value == null || String.valueOf(value) == "None") null else value).asInstanceOf[T]
    }
    
    根据
    String.valueOf
    的定义,可以将条件简化为
    value==null | | value.toString==“无”

    在我看来,编译器应该针对
    asInstanceOf[T]
    发出警告,而不仅仅是针对
    isInstanceOf[T]
    ;在这种情况下,Java实际上比Scala更安全,因为1)它确实为强制转换提供了警告;2)
    instanceof
    检查将是一个错误而不是警告


    作为旁注,虽然您可以消除警告,但如果出现这样一个带有签名的方法,则强烈表明作者对Java泛型的理解不够透彻,我会非常小心地使用该库。

    也许这会有所帮助:。因为擦除会将第二个“if”语句变成“isInstanceOf[Object]”,这总是正确的,这实际上保证不会做程序员想要做的事情。我感到震惊的是,这是一个警告,而不是一个错误。我意识到这个问题不能用类型安全的方式解决,因为输入是Any,输出是T。我从Alexey的解决方案中意识到,一旦你开始做这样的事情,你基本上是在告诉编译器“相信我,在运行时这将被强制转换为T”,编译器的“类型安全保证”变成了“我看到程序员承诺了一个T“.那是你想要的吗?你所做的只是抑制警告…擦除仍然会得到你。如果你不能添加
    ClassTag
    Manifest
    ,你可能是SOL,必须使用Java实现。如果我看一下Java代码,我肯定它能做我想要的,因为我了解它的功能。几乎没有一个实现依赖于T。最后的cast可以忽略,我仍然得到了我想要的。在Scala中,我不明白擦除后第二个if语句变成了什么。我必须进行测试。因为我已经删除了我的答案(因为OP不能添加
    ClassTag
    Manifest
    ),所以答案就在这里,供将来参考
    def execute[t:ClassTag](value:Any):t=value match{case“None”=>null.asInstanceOf[t]case x:t=>x case\u=>null.asInstanceOf[t]}