抽象类型 T 未被检查,因为它被擦除消除了

abstract type T is unchecked since it is eliminated by erasure

我正在编写一个扩展 Java class 的 Scala class。我必须扩展这个抽象 Java class 因为它包含一些转换器,我需要编写一个我自己的转换器,我可以插入他们的框架。所以下面方法的签名是强加给我的:当我说我的 class 扩展了它们的抽象 class 时,它是由 Eclipse 自动生成的。如果我尝试修改方法签名,class 将无法编译,因为 "it does not implement the abstract method from the parent".

方法的实现当然是我的选择——但我发现我无法满足类型系统的限制。

我需要做一些非常简单的事情:将 "None" 视为 null,将 return 其他任何东西都按原样处理。但我发现我无法以类型安全的方式执行此操作。如果我编写如下所示的代码,我会收到一条警告说 "abstract type T is unchecked since it is eliminated by erasure"。我怎样才能消除它?

我还想知道如果应用擦除后我的代码会是什么样子,即第二个 "if" 条件会是什么样子。

凭直觉,我知道当输入为 Any 时我无法保证 return T - 这就是编译器不满意的原因。实际上,这会起作用,因为我们只是读取字符串和 returning 字符串 - 但是方法签名是继承声明强加给我的。

  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]
  }

如何实现这个方法?

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

  1. 在Java中实施:

    @SuppressWarnings("unchecked") @覆盖 public T 执行(对象值){ 如果(值== null || "None".equals(String.valueOf(值)))return null; else return (T) 值; }

  2. 在Scala中实现并添加@unchecked

    def execute[T](值:任意):T = { 如果(值== null || 值== "None")null.asInstanceOf[T] else if (value.isInstanceOf[T @unchecked]) value.asInstanceOf[T] 否则 null.asInstanceOf[T] }

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

感谢 Alec 的建议!

您的 Java 解决方案不包含测试 value instanceof T,因此您在 Scala 解决方案中不需要 isInstanceOf[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 == "None"

IMO,编译器应该为 asInstanceOf[T] 而不仅仅是 isInstanceOf[T] 发出警告;在这种情况下,Java 实际上比 Scala 更安全,因为 1) 它确实为演员表发出警告; 2) instanceof 检查将是错误而不是警告。

附带说明一下,虽然您 可以 摆脱警告,但具有这样签名的方法的存在强烈表明作者不理解 Java 泛型很好,我会非常小心地依赖那个库。