【问题标题】:Inconsistent behaviour with Null Type in ScalaScala 中 Null 类型的行为不一致
【发布时间】:2013-10-04 09:47:24
【问题描述】:

根据scala docs

Null 是所有引用类型的子类型;

所以理论上,在这个例子中,我们可以假设NullFoo(引用类型)的子类型,并且我们应该能够尝试在@987654328 类型的实例上调用bar 方法@。实际上我们不能,并且代码 sn-p 在编译时失败,错误为value bar is not a member of Null


case class Foo(bar: String)

val n: Null = null
n.bar

Try it


我认为我们在编译时捕获它是有道理的,因为 scala 文档也是 say [Null's] only instance is the null reference,但我认为更好的错误消息是 Calling bar on type Null can only result in a NullPointerException

我的问题是关于以下代码 sn-p,它在编译时不会失败,而是在运行时失败,并显示 NullPointerException


val n: Null = null
n.toString

Try it


我假设这是因为 Null 类型并没有真正继承所有其他引用类型,并且只继承 AnyRef,但是有什么理由不应该引发编译时错误(或至少警告)此代码只能导致NullPointerException?调用null.barnull.toString 行为不同是故意的吗?

【问题讨论】:

    标签: scala null


    【解决方案1】:

    Null is a subtype of all reference types; - 意思是这样的:

    val n: Foo = null
    n.bar //throws NPE
    
    val a: String = null
    a.charAt(0) //NPE again
    

    所以你可以说Null 是所有引用类型的子类型。

    编辑:

    val n: Null = null 
    n.bar 
    

    部分不正确。根据 Scala 文档:

    abstract final class Null extends AnyRef
    

    AnyRef 没有bar。不能这么说吧?

    val n: AnyRef = ""
    n.charAt(0) //won't compile
    

    【讨论】:

    • 但这两个陈述肯定有冲突吗?在this 子类型Type B is a subtype of A if every function that can be invoked on an object of type A can also be invoked on an object of type B. 的定义中,如果我的示例如果你不能在类型Null 上调用.bar,那么类型Null 不是子类型Bar
    • 好吧,我不确定,但似乎这个表达式 (val n: Foo = null) 转换为类似“让 Null 成为 Foo 的子类型”等 @987654338 @ 转换为简单的Null。考虑两个类 - Foo(bar: String)Bar(foo: String)。这种情况如果你写val n: Null = null应该是哪个子类型?
    • 它应该是FooBar 的子类型,但这是一个好点;在 Scala 中,多类继承是不可能的,所以不可能。我一直将子类型化和继承视为同一事物,但在 Scala 中可能需要将它们视为不同的事物。
    猜你喜欢
    • 2016-07-27
    • 1970-01-01
    • 2013-03-18
    • 2015-04-30
    • 2011-03-29
    • 2013-07-19
    • 2016-03-10
    • 2021-01-04
    • 2012-12-21
    相关资源
    最近更新 更多