这是在Scala中初始化空引用的正确方法吗?

Geo*_*Geo 51 null scala

假设我有一个MyObject未初始化的实例:

var a:MyObject = null
Run Code Online (Sandbox Code Playgroud)

这是将它初始化为null的正确方法吗?

ret*_*nym 62

备择方案

使用null作为最后的手段.如前所述,Option替换大多数null的用法.如果您使用null一些昂贵的计算来实现字段的延迟初始化,则应使用a lazy val.

规范初始化为null

也就是说,Scala确实支持null.我个人将它与Spring Dependency Injection结合使用.

您的代码完全有效.但是,我建议您使用var t: T = _初始化t为默认值.如果T是基元,则获取特定于该类型的默认值.否则你会得到null.

这不仅更简洁,而且当你事先不知道T将会是什么时,这是必要的:

scala> class A[T] { var t: T = _ }
defined class A

scala> new A[String].t
res0: String = null

scala> new A[Object].t            
res1: java.lang.Object = null

scala> new A[Int].t   
res2: Int = 0

scala> new A[Byte].t
res3: Byte = 0

scala> new A[Boolean].t
res4: Boolean = false

scala> new A[Any].t   
res5: Any = null
Run Code Online (Sandbox Code Playgroud)

高级

var t: T= null如果T是无界的,则使用是编译错误:

scala> class A[T] { var t: T = null }
<console>:5: error: type mismatch;
 found   : Null(null)
 required: T
       class A[T] { var t: T = null }
Run Code Online (Sandbox Code Playgroud)

你可以添加一个隐式参数作为可以T为空的证据- AnyRef不是子类型的子类型即使在Scala 2.8中NotNull也没有完全烘焙,所以现在只考虑它是一个好奇心.

scala> class A[T](implicit ev: Null <:< T) { var t: T = null }           
defined class A
Run Code Online (Sandbox Code Playgroud)

  • 那是什么<:<那里的东西? (8认同)

Dav*_*haw 32

规范的答案是不要使用null.而是使用选项类型:

var a = None : Option[MyObject]
Run Code Online (Sandbox Code Playgroud)

如果要设置它:

a = Some(foo)
Run Code Online (Sandbox Code Playgroud)

当你想从中读取时,测试无:

a match {
  case None => Console.println("not here")
  case Some(value) => Console.println("got: "+value)
}
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,处理`Option`变量的规范方法不是**使用模式匹配,而是使用集合/ monad操作,如`map`,`getOrElse`,`flatMap`,`foreach`,` toList`,`filter`等.对于你给出的例子,模式匹配似乎是有意义的,因为你在每种情况下采取不同的行动,但在大多数真实场景中,`None`s可以被强制删除而不是明确的引用. (15认同)

Rex*_*err 8

正如David和反义词已经提到的那样,Option在大多数情况下使用它是一个好主意,因为Option更明显的是你必须处理无结果的情况.但是,返回Some(x)需要创建对象,并且调用.get或者.getOrElse比if语句更昂贵.因此,在高性能代码中,使用Option并不总是最好的策略(特别是在集合查找代码中,您可能会多次查找值并且不需要相应的对象创建).然后,如果你正在做一些事情,比如返回整个网页的文本(可能不存在),就没有理由使用Option.

另外,只是为了在泛型中添加反义词的null含义,你可以用一种完全出炉的方式做到这一点,如果你真的应该这样做null:

class A[T >: Null] { var t: T = null }
Run Code Online (Sandbox Code Playgroud)

这适用于2.7和2.8.它比<:<方法稍微不那么通用,因为它不遵守NotNullAFAIK,但它完全按照你希望的那样做.