抽象类型 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]
}
如何实现这个方法?
最后,我可以做以下两件事之一:
在Java中实施:
@SuppressWarnings("unchecked")
@覆盖
public T 执行(对象值){
如果(值== null || "None".equals(String.valueOf(值)))return null;
else return (T) 值;
}
在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 泛型很好,我会非常小心地依赖那个库。
我正在编写一个扩展 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]
}
如何实现这个方法?
最后,我可以做以下两件事之一:
在Java中实施:
@SuppressWarnings("unchecked") @覆盖 public T 执行(对象值){ 如果(值== null || "None".equals(String.valueOf(值)))return null; else return (T) 值; }
在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 泛型很好,我会非常小心地依赖那个库。