java.lang.String cannot be cast to scala.runtime.Nothing Scala中的Nothing类型

经常在写Rdd的时候, 如:  val OWNER_ID=row.getAs("OWNER_ID")  等,

运行是可能会报异常 : java.lang.String cannot be cast to scala.runtime.Nothing

后检查后发现,其实应该保证类型一致,应该写成: val OWNER_ID=row.getAs[String]("OWNER_ID")

那么,问题来了, 为啥会有上面的异常出现。查询结果,觉得这篇文章有点意思,就摘抄过来了,

已做为学习,若侵犯您的版权,请在下评论@dy9776 , 我会尽快处理删除掉。

摘抄如下:

    1. Nothing是什么

      Nothing是一个类型(type)。就像Int、String一样是一个类型,比如值3是Int型的,值"abc"是String型的,与Int、String不同的是,不存在Nothing类型的值。

      Nothing这个类型(Type)还有个特点,他是Bottom Type,所谓Bottom type就是他是所有其他类型的子类型(Sub Type) (The bottom type is a subtype of all types.)。 所以可以认为Nothing是Int的子类型,Nothing也是String的子类型。下面摘自Scala Reference 3.5.2 Conformance

      For every value type T , scala.Nothing <: T <: scala.Any
      For every type constructor T (with any number of type parameters), scala.Nothing <: T <: scala.Any

    2. Nothing意义何在
      1. 意义之一:用于类型参数(covariant parameterized types)。
        首先,Scala的泛型是不允许不加类型参数的。 以下摘自Programming In Scala, 2nd Edition, Chapter 19 Type Parameterization

        Unlike Java, which allows raw types, Scala requires that you specify type parameters.
        (不像Java那样允许raw type,Scala必须指定类型参数)

        所以以下两行会出错:Error: type List takes type parameters

        type myList = List
        val li: List = List(1)

        改写成如下可以通过编译:

        type myList = List[String]
        val li: List[Int] = List(1)

        因为List(1)有一个Int型的元素:1,所以他的类型是List[Int]。嗯,make sense,一个List的类型取决于这个List里面的元素。所以List(“abc”)那么就是List[String]型,List(“abc”, 1)就是List[Any],因为"abc"和1都是Any型的子类型。类型推导就是这么工作的。

        那么List()呢?一个空的List,他是什么类型呢?肯定不是List[Int],因为里面并没有Int,也不是List[Any],因为里面啥都没有,没有理由推导出任何一个其他类型,于是这个List()只能是List[Nothing]。

        scala> val l = List()
        l: List[Nothing] = List()

        Nil就是继承自List[Nothing]的。所以才可以做1 :: Nil和"abc” :: Nil。也正因为Nil是List[Nothing],Nothing是bottome type,List是协变的,所以1 :: Nill才会被推导成List[Int],“abc” :: Nil会被推导成List[String]

        case object Nil extends List[Nothing] {
        override def isEmpty = true
        def head: Nothing =
        throw new NoSuchElementException("head of empty list")
        def tail: List[Nothing] =
        throw new NoSuchElementException("tail of empty list")
        }

        小实验,下面可以编译执行吗?ml1的类型是什么呢?

        val ml: List[String] = List()
        val ml1 = 2 :: ml

        意义之二,代表非正常退出。比如抛异常。这个也很make sense,异常嘛,肯定啥都返回不了,类型只有是Nothing了。

        scala> def e = throw new Exception("s")
        e: Nothing

        上文中的Nil的head方法也是一个例子。这里也体现了Nothing的Bottom Type的好处。

        scala> def er(p: Boolean) = if(p) 1 else throw new Exception("yeah")
        er: (p: Boolean)Int

        类型推导观察了下程序,发现这个er方法有2种可能的返回类型,一种是Int,一种是Nothing。由于Nothing是Bottom Type,所以Nothing是Int的子类,所以认为这2种可能返回的类型都是Int,所以推导出er方法的返回值是Int。

      说了这么多,Doc上就几句话:

      Nothing is - together with scala.Null - at the bottom of Scala's type hierarchy.

      Nothing is a subtype of every other type (including scala.Null); there exist no instances of this type. Although type Nothing is uninhabited, it is nevertheless useful in several ways. For instance, the Scala library defines a value scala.collection.immutable.Nil of type List[Nothing]. Because lists are covariant in Scala, this makes scala.collection.immutable.Nil an instance of List[T], for any element of type T.

      Another usage for Nothing is the return type for methods which never return normally. One example is method error in scala.sys, which always throws an exception.

      总结,Nothing是一个Bottom类型,不存在任何值属于Nothing类型。主要有2个用处,用于类型参数和代表非正常退出。

      参考资料:
      1: http://en.wikipedia.org/wiki/Bottom_type
      2: http://www.scala-lang.org/docu/files/ScalaReference.pdf
      3: http://www.scala-lang.org/api/2.10.4/index.html#scala.Nothing
      4: Programming In Scala, 2nd Edition

看完后,有点小明白了!

上一篇:pymysql.err.InternalError: 1075


下一篇:render方法渲染组件和在webpack中导入vue