【问题标题】:compiler error when using Google guava from scala code从 Scala 代码中使用 Google guava 时出现编译器错误
【发布时间】:2018-02-20 19:07:41
【问题描述】:

我正在使用 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
  • Scala 2.11.5

【问题讨论】:

  • 好的,这显然不适用于Int with AnyRef。那么...当您将声明替换为 val cache: LoadingCache[Int, String] = 时会发生什么?在这种情况下发布编译器错误不是更有意义吗?您是否出于某种原因故意写下了“LoadingCache[Int with AnyRef, String]”,还是只是不完善的IDE插入的某种工件?
  • 如果我将它更改为 LoadingCache[Int, String] 它也不会编译。
  • 是的,“它也不会编译”,但它更接近问题的根本原因。我已经在下面解释了这两个问题,您可能对第二部分的解决方案更感兴趣。
  • 更高版本的 Scala 和 Guava 仍会出现类似问题:Scala Guava type mismatch issue

标签: scala caching compiler-errors guava google-guava-cache


【解决方案1】:

1 不是Int with AnyRef

您问题中的编译错误与 Guava 无关。这个 sn-p 这里会产生同样的错误:

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 引起的:由于IntAnyVal 的子类型,所以交集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 的 Int 无缝协作,因为无论如何 scala 都会将 Ints 自动装箱到 java.lang.Integer


类似错误的答案:

  1. Scala Guava type mismatch issue

【讨论】:

  • 请参阅stackoverflow.com/questions/1269170/… 了解更多关于拳击以及 Scala 和 Java 之间的区别
  • Integer 可以正常工作,但是将 scala Int 转换为 java.lang.Integer 很棘手
  • @Sammers 在什么意义上“棘手”?我想不出任何会变得棘手的例子,即使我故意故意让它变得棘手。在 Scala 中,Intjava.lang.Integer 完全透明地来回转换。你能举一个具体的例子让它变得“棘手”吗?
猜你喜欢
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 2019-11-14
相关资源
最近更新 更多