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

时间:2010-03-13 21:38:21

标签: scala null

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

var a:MyObject = null

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

4 个答案:

答案 0 :(得分:60)

替代

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

Canonical初始化为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

高级

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

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 }

您可以添加隐式参数作为T可以为空的证据 - AnyRef的子类型而不是NotNull的子类型这不是完全baked,甚至在Scala 2.8中,所以现在只考虑它的好奇心。

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

答案 1 :(得分:31)

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

var a = None : Option[MyObject]

如果要设置它:

a = Some(foo)

当你想要阅读它时,测试无:

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

答案 2 :(得分:8)

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

另外,只是在null上添加反义词对泛型的点,如果你真的认为它应该是null,你可以用一种完全无法实现的方式:

class A[T >: Null] { var t: T = null }

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

答案 3 :(得分:0)

我遇到过这个问题,因为scalastyle告诉我在使用null在我的测试中初始化对象时不使用null。

我的解决方案没有改变任何满足scalastyle的类型:

var a: MyObject = (None: Option[MyObject]).orNull