【问题标题】:Type mismatch generics with classOf Scala与 classOf Scala 类型不匹配的泛型
【发布时间】:2020-01-05 17:13:30
【问题描述】:

我有一个方法应该根据配置标志 format 动态地将字段成员转换为特定类型。

此标志format,接受以下类型值之一:

object Types {
    val Str = "string"
    val IntNum1 = "int"
    val IntNum2 = "integer"
    val DoubleNum = "double"
    val LongNum = "long"
}

一种选择是使用反射。另一种选择是使用模式匹配(我正在尝试使用的方法)

String 类型的方法如下:

private def getValClassIfStr(format: String): Class[String] = {
    format.toLowerCase match {
        case Types.Str => classOf[String]
        case _ => null
    }
}

这是从AnyVal 扩展的数值类型的方法,但无法编译:

private def getValueClass[T <: AnyVal](format: String): Try[Class[T]] = {
    format.toLowerCase match {
        case Types.IntNum1 || Types.IntNum2 => Success(classOf[Int])
        case Types.DoubleNum => Success(classOf[Double])
        case Types.LongNum => Success(classOf[Long])
        case _ => Failure(new Exception)
    }
}

第二种方法无法编译,因为: Type mismatch: required Try[Class[T]] found Try[Class[Int]]

我不明白,给定T &lt;: AnyVal

有什么想法吗?如果这是一种不好的方法,那么“干净”的替代方案会是什么?

【问题讨论】:

标签: scala generics types


【解决方案1】:

我认为,将返回值中的Class[T] 替换为Class[AnyVal] 后,这不起作用的原因会变得更清楚:

type mismatch;
 found   : Class[Int](classOf[scala.Int])
 required: Class[AnyVal]
Note: Int <: AnyVal, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: AnyVal`. (SLS 3.2.10)

换句话说,任何对getValueClass[T] 的调用都必须由编译器填充T = AnyVal,因为format 仅在运行时进行评估。然而,这是不可能的,因为Class[T] 是不变的,因此您不能将Class[Int]Class[Double] 作为Class[AnyVal] 返回,因为对于不变的容器没有子类型关系。

演示:

var x: Class[AnyVal] = _
x = classOf[Int]
// Boom

【讨论】:

  • 感谢您的回答,很有帮助。
猜你喜欢
  • 2015-04-09
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
相关资源
最近更新 更多