我如何摆脱这种类型的警告/错误?

发布于 2024-10-21 11:26:30 字数 3924 浏览 4 评论 0原文

我有一个剧本。它运行时没有警告。

$ cat ~/tmp/so1.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [_, _] => {
    for (entry <- map) {
      entry match {
        case ("id", id: String) => System.out.println ("ID is " + id)
        case (n: String, v: String) => System.out.println (n + " = " + v)
      }
    }
  }
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so1.scala eg/default.yaml
(program output as expected)

我想将循环提取到它自己的函数中。所以我尝试这样做。

$ cat ~/tmp/so2.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val processMap = (map: java.util.Map [_, _]) => {
  for (entry <- map) {      // line 16
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [_, _] => processMap (map)
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so2.scala eg/default.yaml
(fragment of so2.scala):16: error: type mismatch;
 found   : map.type (with underlying type java.util.Map[_, _])
 required: java.util.Map[_$1,_$2] where type _$2, type _$1
  for (entry <- map) {
                 ^
one error found
!!!
discarding <script preamble>

循环位于其自己的函数中意味着它需要更具体的类型。好的。

我将尝试使用 java.util.Map [A​​nyRef, AnyRef] 而不是 java.util.Map [_, _]

$ cat ~/tmp/so3.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val processMap = (map: java.util.Map [AnyRef, AnyRef]) => {
  for (entry <- map) {
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [AnyRef, AnyRef] => processMap (map)      // line 26
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so3.scala eg/default.yaml
(fragment of so3.scala):26: warning: non variable type-argument AnyRef in type pattern is unchecked since it is eliminated by erasure
  case map: java.util.Map [AnyRef, AnyRef] => processMap (map)
                       ^
one warning found
!!!
discarding <script preamble>
(program output as expected)

所以现在它运行了,但它给了我一个警告。我该如何消除该警告?

注意:

  1. org.yaml.snakeyaml.Yaml 是用 Java 编写的,因此我无法使用类型清单。 (我可以吗?)
  2. 我的真实程序使用了多个 Java 库,因此当我对哪些类型做出可能错误的假设时,我希望得到警告 我被给予了。但是我如何告诉编译器“是的,我已经检查过了,它是正确的,不要再警告我”?
  3. 我使用的是 scala 2.7.7(因为这是与 Ubuntu 一起打包的版本)。

I have a script. It runs without warnings.

$ cat ~/tmp/so1.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [_, _] => {
    for (entry <- map) {
      entry match {
        case ("id", id: String) => System.out.println ("ID is " + id)
        case (n: String, v: String) => System.out.println (n + " = " + v)
      }
    }
  }
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so1.scala eg/default.yaml
(program output as expected)

I'd like to extract the loop into its own function. So I try that.

$ cat ~/tmp/so2.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val processMap = (map: java.util.Map [_, _]) => {
  for (entry <- map) {      // line 16
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [_, _] => processMap (map)
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so2.scala eg/default.yaml
(fragment of so2.scala):16: error: type mismatch;
 found   : map.type (with underlying type java.util.Map[_, _])
 required: java.util.Map[_$1,_$2] where type _$2, type _$1
  for (entry <- map) {
                 ^
one error found
!!!
discarding <script preamble>

The loop being in its own function means it requires a more specific type. Okay.

I'll try with java.util.Map [AnyRef, AnyRef] instead of java.util.Map [_, _].

$ cat ~/tmp/so3.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val processMap = (map: java.util.Map [AnyRef, AnyRef]) => {
  for (entry <- map) {
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [AnyRef, AnyRef] => processMap (map)      // line 26
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so3.scala eg/default.yaml
(fragment of so3.scala):26: warning: non variable type-argument AnyRef in type pattern is unchecked since it is eliminated by erasure
  case map: java.util.Map [AnyRef, AnyRef] => processMap (map)
                       ^
one warning found
!!!
discarding <script preamble>
(program output as expected)

So now it runs, but it gives me a warning. How do I eliminate that warning?

Notes:

  1. org.yaml.snakeyaml.Yaml is written in Java, so I can't use type manifests. (Can I?)
  2. My real program uses several Java libraries, so I want to be warned when I make possibly false assumptions about what types
    I'm being given. But how do I tell the compiler "yes, I've checked this, it's correct, don't warn me about it again"?
  3. I'm using scala 2.7.7 (because that's the version that's packaged with Ubuntu).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜光 2024-10-28 11:26:30

您可以尝试首先删除自定义包装器。 (2.8.1) Scala 标准库已在 scala.collection.JavaConverters 中包含一个包装器,以便更惯用地使用 Java 集合类型。 (注意:导入时不需要 scala. 前缀)

我还将 processMap 设为方法而不是函数,并添加类型参数:

import collection.JavaConverters._

def processMap[K,V](map: Map[K, V]): Unit = {
  for (entry <- map) {
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map[_, _] => processMap(map.asScala)
}

注意倒数第二行的 asScala 方法...

在处理 Java/Scala 互操作时,通常最好的做法是尽早从 Java 转换为 Scala 集合,并尽可能晚地转换回来。

You could try removing your custom wrapper to start with. The (2.8.1) Scala standard library already includes a wrapper to use Java collection types more idiomatically, in scala.collection.JavaConverters. (note: the scala. prefix is not needed when importing this)

I'd also make processMap a method instead of a function, and add type params:

import collection.JavaConverters._

def processMap[K,V](map: Map[K, V]): Unit = {
  for (entry <- map) {
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map[_, _] => processMap(map.asScala)
}

Note the asScala method on the second to last line...

When dealing with Java/Scala interop, it's generally a best practice to convert from Java to Scala collections at the earliest opportunity, and to convert back as late as possible.

柏拉图鍀咏恒 2024-10-28 11:26:30

您必须使用 Scala 2.7.X。如果您使用 2.8.1,您的 Map[_,_] 示例可以正常工作。

如果您需要使用 2.7.X,请尝试将 processMap 值转换为方法:
def processMap[K,V] = (map: java.util.Map[K,V]) =>; {...}
这似乎适合我编译,但请注意,我使用 YAML 库“存根”了这些部分。我用过:

val m1 = new java.util.HashMap[String,String]
m1.put("one", "1")
m1.put("id", "123")
m1.put("two", "2")

m1 match {
  case map: java.util.Map [_, _] => processMap (map)
}

You must be using Scala 2.7.X. If you use 2.8.1, your example with Map[_,_] works fine.

If you need to use 2.7.X, try converting your processMap value into a method:
def processMap[K,V] = (map: java.util.Map[K,V]) => {...}
That seemed to compile for me, but note that I "stubbed" the parts using the YAML library. I used:

val m1 = new java.util.HashMap[String,String]
m1.put("one", "1")
m1.put("id", "123")
m1.put("two", "2")

m1 match {
  case map: java.util.Map [_, _] => processMap (map)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文