Scala:抽象类型模式A未被选中,因为它被擦除消除了

tmp*_*ies 16 generics functional-programming scala type-erasure scala-template

我正在编写可以捕获特定类型的异常的函数.

def myFunc[A <: Exception]() {
    try {
        println("Hello world") // or something else
    } catch {
        case a: A => // warning: abstract type pattern A is unchecked since it is eliminated by erasure
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下绕过jvm类型擦除的正确方法是什么?

sen*_*nia 23

你可以ClassTag这个答案中使用.

但我更喜欢这种方法:

def myFunc(recover: PartialFunction[Throwable, Unit]): Unit = {
  try {
    println("Hello world") // or something else
  } catch {
    recover
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

myFunc{ case _: MyException => }
Run Code Online (Sandbox Code Playgroud)

使用ClassTag:

import scala.reflect.{ClassTag, classTag}

def myFunc[A <: Exception: ClassTag](): Unit = {
  try {
    println("Hello world") // or something else
  } catch {
    case a if classTag[A].runtimeClass.isInstance(a) =>
  }
}
Run Code Online (Sandbox Code Playgroud)

另请注意,通常您应该使用Trywith recovermethod:Try将仅捕获NonFatal异常.

def myFunc(recover: PartialFunction[Throwable, Unit]) = {
  Try {
    println("Hello world") // or something else
  } recover {
    recover
  }.get // you could drop .get here to return `Try[Unit]`
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*lis 5

对于每种类型检查(例如case a: A),JVM需要相应的class对象来执行检查。在您的情况下,JVM没有类对象,因为A它是变量类型参数。但是,您可以A通过将隐式传递给Manifest[A]来添加有关的其他信息myFunc。简而言之,您可以将: Manifest类型声明添加到A

def myFunc[A <: Exception : Manifest]() {
    try {
        println("Hello world") // or something else
    } catch {
        case a: A => // warning: abstract type pattern A is unchecked since it is eliminated by erasure
    }
}
Run Code Online (Sandbox Code Playgroud)