2011-03-12 94 views
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 [AnyRef, 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打包的版本)。
+2

安裝2.8與提取'.tgz'文件並將'bin'子目錄添加到'$ PATH'環境變量一樣簡單。除非你有一些特定的遺留代碼阻止你升級,否則我會強烈建議你儘早這樣做。否則,你錯過了一年的改進和錯誤修復。 – 2011-03-12 18:21:10

回答

3

你可以嘗試刪除你的自定義包裝開始。 (2.8.1)Scala標準庫已經包含一個包裝器,用於更通俗地使用Java集合類型,在scala.collection.JavaConverters中。 (注:進口不需要scala.前綴時,這一點)

我還做processMap的方法,而不是一個功能,並新增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) 
} 

注意asScala方法上倒數第二行...

在處理Java/Scala互操作時,通常最好是儘早從Java轉換爲Scala集合,並儘可能晚地轉換回來。

+0

接受這個答案,因爲我升級到Scala 2.8.1.final。將Scala作爲我的項目的顯式依賴關係一樣容易,因爲它是我正在使用的所有Java庫。 – dave4420 2011-03-13 15:07:54

0

您必須使用Scala 2.7.X.如果您使用2.8.1,您的示例與地圖[_,_]工作正常。

如果您需要使用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) 
} 
+0

我正在使用Scala 2.7.7,是的。 – dave4420 2011-03-12 18:16:14