我不想写很多样板代码,所以我决定为lazy-init编写泛型方法。
import java.util._
import concurrent.ConcurrentHashMap
object GenericsTest {
val cache: ConcurrentHashMap[Long,
ConcurrentHashMap[Long,
ConcurrentHashMap[Long,
ConcurrentHashMap[Long, Long]]]] = new ConcurrentHashMap()
def main(args: Array[String]) {
val x = get(cache, 1)(() => new ConcurrentHashMap())
val y = get(x, 1)(() => new ConcurrentHashMap())
val z = get(y, 1)(() => new ConcurrentHashMap())
}
def get[B, A](map: ConcurrentHashMap[A, B], a: A)(factory: () => B): B = {
if (map.containsKey(a)) {
map.get(a)
} else {
val b = factory()
map.put(a, factory())
b
}
}
}
此示例仅使用硬编码长但不使用通用 A 运行,可能是什么问题?也许有另一种方法可以做这样的事情?
答案 0 :(得分:1)
错误在这一行:
val x = get(cache, 1)(() => new ConcurrentHashMap())
问题是1的类型是 Int 。
我们有这种方法签名:
get[A, B](map: ConcurrentHashMap[A, B], a: A)(factory: () => B): B
在有问题的调用中传递的参数类型是(B是长嵌套类型,它现在不相关):
ConcurrentHashMap[Long, B] and Int
所以编译器计算 A 必须是 Long 和 Int 最接近的共同祖先,它是 AnyVal ,所以最后它将使用传递的参数类型为:
ConcurrentHashMap[AnyVal, B] and AnyVal
但ConcurrentHashMap在其第一个类型参数中是不变的,因此 cache val不能用作 ConcurrentHashMap [AnyVal,B] ,所以编译器给出了这个错误信息(删除了长嵌套类型参数部分,它现在不重要):
found : java.util.concurrent.ConcurrentHashMap[Long, ...]
required: java.util.concurrent.ConcurrentHashMap[AnyVal, ...]
Note: Long <: AnyVal, but Java-defined class ConcurrentHashMap is invariant in type K.
要解决此问题,您需要将第二个参数传递为 Long :
val x = get(cache, 1L)(() => new ConcurrentHashMap())
val y = get(x, 1L)(() => new ConcurrentHashMap())
val z = get(y, 1L)(() => new ConcurrentHashMap())