使用 Scala 删除警告消息 "on-variable type argument Int in type ... is unchecked"

Removing the warning message "on-variable type argument Int in type ... is unchecked" with Scala

我有一个函数,仅当输入是四个整数的元组时才计算元组值。

def add(v:Any) = {
    if (v.isInstanceOf[(Int, Int, Int, Int)]) {
        val v2 = v.asInstanceOf[(Int, Int, Int, Int)]
        println(v2._1 + v2._2 + v2._3 + v2._4)
    } else {
        println("NOP")
    }
}

object Main extends App {
    add((1,1,1,1))
    add((1,2))
}

Main.main(args)

它正在运行,但我收到了 "non-variable type argument ... is unchekced" 警告。

warning: non-variable type argument Int in type (Int, Int, Int, Int) is 
unchecked since it is eliminated by erasure
if (v.isInstanceOf[(Int, Int, Int, Int)]) {

为什么会出现此错误,删除此警告消息的最佳方法可能是什么?

这是编译时type erasure造成的,可以通过TypeTag解决:

import scala.reflect.runtime.universe._
def add[T](v:T)(implicit t: TypeTag[T]) = {
    if ( t.tpe =:= typeOf[(Int, Int, Int, Int)]) {
        val v2 = v.asInstanceOf[(Int, Int, Int, Int)]
        println(v2._1 + v2._2 + v2._3 + v2._4)
    } else {
        println("NOP")
    }
}

您可以用模式匹配替换 instanceOfs 并用 @unchecked

抑制警告
def add(v: Any) = v match {
  case t: (Int, Int, Int, Int) @unchecked =>
    println(t._1 + t._2 + t._3 + t._4)
  case _ =>
    println("NOP")
}

如果您传递的 Tuple4 不是 (Int, Int, Int, Int),您将得到 ClassCastException

错误清楚地表明,由于类型擦除,通用类型的元组将被删除,因此编译器无法确保这将在运行时工作,它只会查看是否传递了 Tuple4,而不是传递了什么包含。

我提出的解决方案会给你带来麻烦,如果函数可能会被调用而不是 (Int, Int, Int, Int) Tuple4,那么你应该继续 TypeTags,否则它看起来更干净,不需要反射。

如果您确实需要检查参数是否为四个 Int 的元组,正确的方法是检查每个组件:

def add(v: Any) = v match {
  case (i1: Int, i2: Int, i3: Int, i4: Int) =>
    println(i1 + i2 + i3 + i4)
  case _ =>
    println("NOP")
}