我有下面的Scala代码。
此函数定义类型参数类型EntityManager
,它是spring.jpa.properties.javax.persistence.lock.timeout=600
的子类。它将B
转换为A
。
java.util.List[A]
编译该程序时,出现以下错误。
java.util.List[B]
我的程序出了什么问题。我该如何解决该错误
答案 0 :(得分:3)
使用java.util.stream.Stream.map
时似乎发生了类型擦除(从Animal到?0),无论传入的是B还是具体类型,可能是由于Scala类型推断与Java类型推断之间的不兼容。
在调用Java方法时,您仍然需要泛型类型推断,则需要专门传递泛型类型:
def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
那么您就可以成功进行操作了:
scala> def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
convertLowerBound: [B <: Animal](a: java.util.List[Animal])java.util.List[B]
scala> convertLowerBound[Cat](a)
res30: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
另一方面,您的转换并没有真正的用处,因为在运行时,所有通用类型都将被删除,因此编译后List [A]或List [B]将相同(它们将成为对象列表)您可以看一下已编译的字节码)。您可以直接在列表上直接投射,而不是在每个元素上直接投射
:def convertLowerBound[B <: Animal : TypeTag] (a: JList[Animal]) = a.asInstanceOf[JList[B]]
然后您可以成功完成用例:
scala> a.add(new Cat())
res16: Boolean = true
scala> convertLowerBound[Cat](a)
res17: java.util.List[Cat] = [Cat@6325af19]
但是,如果类型不匹配,例如您在列表中添加了Dog并尝试将其投射为Cat列表,只有在您尝试访问元素时才会发生错误:
scala> a.add(new Dog())
res19: Boolean = true
scala> convertLowerBound[Cat](a)
res20: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
scala> convertLowerBound[Cat](a).get(1)
java.lang.ClassCastException: Dog cannot be cast to Cat
... 28 elided