我对Scala很新,但仍然不了解泛型。因此,我无法弄清楚为什么编译器会因类型不匹配错误而讨厌我。
我使用Google的Guava库创建一些简单的缓存,表示为Scala的ConcurrentMap。我想跟踪创建的缓存使用另一个缓存名称Map到ConcurrentMap(缓存)。这是我到目前为止编译但是缺少对缓存的跟踪(我已经注释掉了失败的位):
import scala.collection.mutable.ConcurrentMap
trait CacheManager {
def getCache[V <: AnyRef](
cacheName: String,
cacheListener: Option[CacheListener] = None): ConcurrentMap[String, V]
}
import scala.collection.JavaConversions._
import com.google.common.collect.MapMaker
import java.util.concurrent.{ConcurrentMap => JConcurrentMap, TimeUnit}
import org.slf4j.LoggerFactory
import com.google.common.cache.{RemovalNotification, RemovalListener, CacheBuilder}
import scala.collection.mutable.ConcurrentMap
class LocalCacheManager extends CacheManager {
private val logger = LoggerFactory.getLogger(classOf[LocalCacheManager])
private val caches /*: ConcurrentMap[String, ConcurrentMap[String, _ <: AnyRef]]*/ =
asScalaConcurrentMap[String, ConcurrentMap[String, _ <: AnyRef]](
new MapMaker().concurrencyLevel(4).makeMap[String, ConcurrentMap[String, _ <: AnyRef]]())
def getCache[V <: AnyRef](cacheName: String, cacheListener: Option[CacheListener] = None) = {
// caches.getOrElseUpdate(cacheName, {
val cache = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.softValues()
.expireAfterAccess(30, TimeUnit.MINUTES)
.build[String, V]()
asScalaConcurrentMap[String, V](cache.asMap())
// })
}
}
基本上,如果我尝试将Guava缓存添加到缓存(通过注释掉的caches.getOrElseUpdate),那么编译器会抱怨以下内容:
error: type mismatch;
found : scala.collection.mutable.ConcurrentMap[String,_$1] where type _$1 <: AnyRef
required: scala.collection.mutable.ConcurrentMap[String,V]
caches.getOrElseUpdate(cacheName, {
答案 0 :(得分:3)
由于您在检索缓存时提供类型信息,因此无需尝试并维护通配符类型。将值键入AnyRef然后在结尾处将V形式转换为V要简单得多。以下编译并应该有所帮助。此外,没有必要直接调用asScalaConcurrentMap,因为它很好......隐式。
import scala.collection.JavaConversions._
import com.google.common.collect.MapMaker
import java.util.concurrent.TimeUnit
import com.google.common.cache.CacheBuilder
import scala.collection.mutable.ConcurrentMap
trait CacheListener // not sure what this is doing yet.
trait CacheManager {
def getCache[V <: AnyRef](
cacheName: String,
cacheListener: Option[CacheListener] = None): ConcurrentMap[String, V]
}
class LocalCacheManager extends CacheManager {
private val caches: ConcurrentMap[String, ConcurrentMap[String, AnyRef]] =
new MapMaker().concurrencyLevel(4).makeMap[String, ConcurrentMap[String, AnyRef]]()
def getCache[V <: AnyRef](cacheName: String, cacheListener: Option[CacheListener] = None) =
caches.getOrElseUpdate(cacheName, {
CacheBuilder.newBuilder()
.concurrencyLevel(4)
.softValues()
.expireAfterAccess(30, TimeUnit.MINUTES)
.asInstanceOf[CacheBuilder[String, AnyRef ]]
.build[String, AnyRef ]()
.asMap()
}).asInstanceOf[ConcurrentMap[String, V]]
}