Scala: шаблон абстрактного типа A не отмечен, поскольку он устраняется стиранием

Я пишу функцию, которая может перехватывать исключения только определенного типа.

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
    }
}

Что означает способ обхода типа jvm в этом случае?

Ответ 1

Вы можете использовать ClassTag как в этом ответе.

Но я бы предпочел такой подход:

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

Использование:

myFunc{ case _: MyException => }

Используя 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) =>
  }
}

Следует также отметить, что в целом следуешь использовать Try с recover метода: 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]'
}

Ответ 2

Для каждой проверки типа (например, в 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
    }
}