假设我有一个未初始化的MyObject
实例:
var a:MyObject = null
这是将它初始化为null的正确方法吗?
答案 0 :(得分:60)
使用null
作为最后的手段。如前所述,Option
取代了大多数null的用法。如果您使用null
通过一些昂贵的计算来实现字段的延迟初始化,则应使用lazy val
。
那就是说,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