2

我正在使用 Scala 代码中的 Google Guava。当我尝试使用 Int 作为示例中的键类型时会出现问题:

CacheBuilder.newBuilder()
    .maximumSize(2)
    .expireAfterWrite(24, TimeUnit.HOURS)
    .build(
      new CacheLoader[Int, String] {
        def load(path: Int): String = {
          path + "hello"
        }
      }
    )

看起来不错,但所创建对象的推断类型是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"
            }
          }
        )

当我尝试获取本例中的元素时会发生错误:

cache.get(1)

Scala 编译器错误:

[ERROR] error: type mismatch;
[INFO]  found   : Int(1)
[INFO]  required: Int
[INFO]   cache.get(1)
[INFO]             ^

有人可以指出为什么会出现这样的错误以及我做错了什么吗?

环境:

  • 谷歌番石榴 15.0
  • 斯卡拉 2.11.5
4

1 回答 1

4

关于1不是一个Int with AnyRef

您问题中的编译错误与番石榴没有任何关系。此处的此代码段会产生相同的错误:

val h = new scala.collection.mutable.HashMap[Int with AnyRef, String]
h(3) = "hello"
println("Get 3: " + h.get(3))

error: type mismatch;
found   : Int(3)
required: Int

这是由Int with AnyRef: 因为Int是 的子类型AnyVal,所以交集Int with AnyRef是空的,根本不存在具有该类型的任何实例。


现在到问题的根本原因。

问题是,当您调用 时.build(),scala 编译器找不到可以用作 的版本.build[Int, String],因为没有未装箱整数的版本。因此,编译器会推断.build[AnyRef with Int, String]并构建一个不可用的缓存结构。

为避免这种情况,请使用java.lang.Integer代替Int. 这里使用 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))

它应该与 scala 无缝工作,因为无论如何Intscala 自动装箱Intjava.lang.Integer


类似错误的答案:

  1. Scala Guava 类型不匹配问题
于 2018-02-20T20:00:31.303 回答