【问题标题】:Why this erasure warning with member variables declared as a tuple?为什么将成员变量声明为元组的擦除警告?
【发布时间】:2011-03-07 18:37:12
【问题描述】:

看看这个 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 类型,没有类型注释。

【问题讨论】:

    标签: scala compiler-warnings type-erasure


    【解决方案1】:

    您可以将示例重写为:

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

    这个模式匹配实际上由 2 个匹配组成 - 它现在说:获取类型为 Tuple2[Int, Int] 的右侧对象并在 Tuple2 伴随对象上调用方法 unapply[Int, Int]。然后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] => 
    }
    

    您会收到类似的警告。

    【讨论】:

    • 好的,所以如果我省略类型注释,在第二个匹配中它会尝试匹配 Tuple2[_, _] 而不是 Tuple2[Int, Int] 并且它不需要检查擦除的类型参数。所以这是元组特殊语法的一个不幸的副作用。
    【解决方案2】:

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

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

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

    【讨论】:

    • 谢谢,这是一个有用的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多