为什么将成员变量的擦除警告声明为元组?

时间:2011-03-07 18:37:12

标签: scala compiler-warnings type-erasure

看看这个Scala类:

class Example {
  val (x, y): (Int, Int) = (1, 2)
}

对此进行编译会产生警告:

Example.scala:2: warning: non variable type-argument Int in type pattern
               (Int, Int) is unchecked since it is eliminated by erasure
    val (x, y): (Int, Int) = (1, 2)
                ^

删除显式类型注释会消除此警告:

class Example {
  val (x, y) = (1, 2)
}

为什么我会收到警告,为什么删除显式类型注释会删除它?至于我没有看到任何真正的变化,xy仍然是类型Int而没有类型注释。

2 个答案:

答案 0 :(得分:13)

您可以将示例重写为:

class Example {
  val Tuple2(x, y): Tuple2[Int, Int] = Tuple2(1, 2)
}

此模式匹配实际上包含2个匹配项 - 现在说:采用Tuple2[Int, Int]类型的右侧对象,并在unapply[Int, Int]随播广告对象上调用方法Tuple2。然后,unapply[Int, Int]将验证对象是否确实具有Tuple2类型,并且其结果值将用于将值绑定到变量xy

之后,此模式匹配包含: Tuple2[Int, Int],因此它会尝试动态执行isInstanceOf[Tuple2[Int, Int]]检查,以查看该对象是否还具有类型Tuple2[Int, Int]。但是,泛型类型信息在运行时被擦除,因此编译器警告它无法实际生成验证对象是否为类型参数[Int, Int]实例化的代码。

以同样的方式,在以下模式匹配中:

val a: AnyRef = (1, 2)
a match {
  case t2: Tuple[Int, Int] => 
}

你会收到类似的警告。

答案 1 :(得分:5)

我认为你问题的简短回答是:

class Example {
  val (x: Int, y: Int) = (1, 2)
}

因为(Int, Int) 不是类型,而(x: Int, y: Int)是有效的模式表达式。