私はscalaで本当に奇妙な振る舞いに遭遇しました。エラーが発生しやすいコードと「有効な例外」のリストを引数として取るジェネリックメソッドを作成しました。「有効な例外」がスローされたときにコードを再試行しながら、コードを実行する必要があります。
この方法はうまく機能し、私はいくつかの場所でそれを使用しています。
しかし、その後、メソッド呼び出しの1つがコンパイルに失敗しました。
原因は、例外リストの初期化でした。
他の原因がないことを確認するために、REPLで試してみましたが、結果を自分で確認できます。
me@my-lap:~$ scala -cp /path/to/maven/repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar:/path/to/maven/repository/commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.jar:/path/to/maven/repository/me/my-utils/1.0-SNAPSHOT/my-utils-1.0-SNAPSHOT.jar:/path/to/maven/repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_17).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import org.apache.http.conn.{HttpHostConnectException,ConnectTimeoutException}
import org.apache.http.conn.{HttpHostConnectException, ConnectTimeoutException}
scala> import me.util.exceptions.RetryException
import me.util.exceptions.RetryException
scala> val validEx = classOf[ConnectTimeoutException] :: classOf[RetryException] :: classOf[HttpHostConnectException] :: Nil
<console>:9: error: inferred type arguments [java.lang.Class[_ >: _1 with org.apache.http.conn.ConnectTimeoutException <: java.lang.Exception]] do not conform to method ::'s type parameter bounds [B >: java.lang.Class[_ >: org.apache.http.conn.HttpHostConnectException with me.util.exceptions.RetryException <: java.lang.Exception]]
val validEx = classOf[ConnectTimeoutException] :: classOf[RetryException] :: classOf[HttpHostConnectException] :: Nil
^
3つの例外タイプすべてからリストを初期化すると、コードはこの奇妙なエラーで失敗します。だから私はそれらの3からの2つの例外のすべてのサブセットで初期化しようとしました:
scala> val validEx = classOf[ConnectTimeoutException] :: classOf[RetryException] :: Nil
validEx: List[java.lang.Class[_ >: me.util.exceptions.RetryException with org.apache.http.conn.ConnectTimeoutException <: java.lang.Exception]] = List(class org.apache.http.conn.ConnectTimeoutException, class me.util.exceptions.RetryException)
scala> val validEx = classOf[ConnectTimeoutException] :: classOf[HttpHostConnectException] :: Nil
validEx: List[java.lang.Class[_ >: org.apache.http.conn.HttpHostConnectException with org.apache.http.conn.ConnectTimeoutException <: java.io.IOException]] = List(class org.apache.http.conn.ConnectTimeoutException, class org.apache.http.conn.HttpHostConnectException)
scala> val validEx = classOf[RetryException] :: classOf[HttpHostConnectException] :: Nil
validEx: List[java.lang.Class[_ >: org.apache.http.conn.HttpHostConnectException with me.util.exceptions.RetryException <: java.lang.Exception]] = List(class me.util.exceptions.RetryException, class org.apache.http.conn.HttpHostConnectException)
そしてそれはうまくいきました!また、演算子List()
を使用する代わりに、3つの例外タイプすべてのリストを作成しようとしました。::
そしてそれはまた働いた:
scala> val validEx = List(classOf[ConnectTimeoutException], classOf[RetryException], classOf[HttpHostConnectException])
validEx: List[java.lang.Class[_ >: org.apache.http.conn.HttpHostConnectException with me.util.exceptions.RetryException with org.apache.http.conn.ConnectTimeoutException <: java.lang.Exception]] = List(class org.apache.http.conn.ConnectTimeoutException, class me.util.exceptions.RetryException, class org.apache.http.conn.HttpHostConnectException)
ところで、の実装RetryException
は次のとおりです。
class RetryException extends Exception {}
では、なぜそれが起こったのですか?それはscalaの::
オペレーターのバグですか?
そして、なぜコンパイラーは:よりも良いタイプを推測できなかったのですか:(List[java.lang.Class[_ >: org.apache.http.conn.HttpHostConnectException with me.util.exceptions.RetryException with org.apache.http.conn.ConnectTimeoutException <: java.lang.Exception]]
私のメソッドはタイプの引数を除いています:validExceptions: List[Class[_ <: java.lang.Throwable]]
これははるかに簡潔なタイプです。コンパイラーを除いて次のようなものを理解します:List[Class[_ <: java.lang.Exception]]
(私はScalaバージョン2.9.2(Java7 oracle 1.7.0_17)を搭載したubuntu12.0464ビットで実行しています