3

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

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

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

我还想知道如果我的代码在应用到它后会是什么样子,即第二个“if”条件会是什么样子。

直观地说,我知道当输入为 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]
  }

我怎样才能实现这个方法?

4

2 回答 2

2

您的 Java 解决方案不包含 test value instanceof T,因此您不需要isInstanceOf[T]Scala 解决方案。你应该删除它,因为检查没有做任何事情:它擦除到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]
}

value == null || value.toString == "None"根据的定义,条件可以简化为String.valueOf

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

作为旁注,虽然您可以摆脱警告,但具有这样签名的方法的存在强烈表明作者对 Java 泛型的理解不够好,我会非常小心地依赖该库。

于 2016-08-06T03:56:35.110 回答
1

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

  1. 用Java实现:

    @SuppressWarnings("unchecked") @Override public T execute(Object value) { if (value == null || "None".equals(String.valueOf(value))) return null; 否则返回(T)值;}

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

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

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

感谢亚历克的建议!

于 2016-08-05T22:01:20.817 回答