Reputation: 1108
I m using Google Guava from a scala code. And an issue occurs when I m trying to use Int as a key type like in the example:
CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(24, TimeUnit.HOURS)
.build(
new CacheLoader[Int, String] {
def load(path: Int): String = {
path + "hello"
}
}
)
It seems to be fine, but the inferred type of created object is LoadingCache[Int with AnyRef, String]:
val cache: LoadingCache[Int with AnyRef, String] = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(24, TimeUnit.HOURS)
.build(
new CacheLoader[Int, String] {
def load(path: Int): String = {
path + "hello"
}
}
)
And the error occurs when I m trying to get an element like in this example:
cache.get(1)
Scala compiler error:
[ERROR] error: type mismatch;
[INFO] found : Int(1)
[INFO] required: Int
[INFO] cache.get(1)
[INFO] ^
Can someone point me out why such error appears and what I m doing wrong?
ENV:
Upvotes: 2
Views: 800
Reputation: 44957
1
not being an Int with AnyRef
The compile error in your question doesn't have anything to do with Guava. This snippet here produces the same error:
val h = new scala.collection.mutable.HashMap[Int with AnyRef, String]
h(3) = "hello"
println("Get 3: " + h.get(3))
gives
error: type mismatch;
found : Int(3)
required: Int
This is caused by the Int with AnyRef
: since Int
is subtype of AnyVal
, the intersection Int with AnyRef
is empty, there simply cannot exist any instances with that type.
The problem is that when you call .build()
, the scala compiler cannot find a version that would work as .build[Int, String]
, because there is no version for unboxed integers. So instead, the compiler infers .build[AnyRef with Int, String]
, and builds an unusable cache structure.
To avoid this, use java.lang.Integer
instead of Int
. This here compiles and runs with guava 15.0 scala 2.11:
import com.google.common.cache._
import java.util.concurrent._
val cache: LoadingCache[java.lang.Integer, String] = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(24, TimeUnit.HOURS)
.build[java.lang.Integer, String](
new CacheLoader[java.lang.Integer, String] {
def load(path: java.lang.Integer): String = {
path + "hello"
}
}
)
cache.put(42, "hello, world")
println(cache.get(42))
It should work seamlessly with scala's Int
, because scala autoboxes Int
s into java.lang.Integer
anyway.
Answers for similar errors:
Upvotes: 4