Подтвердить что ты не робот

Является ли это правильным способом инициализации нулевых ссылок в Scala?

Скажем, у меня есть экземпляр MyObject, который не инициализирован:

var a:MyObject = null

- это правильный способ инициализировать его нулевым?

4b9b3361

Ответ 1

Альтернативы

Используйте null в качестве последнего средства. Как уже упоминалось, Option заменяет большинство применений null. Если вы используете null для реализации отложенной инициализации поля с некоторым дорогостоящим вычислением, вы должны использовать lazy val.

Каноническая инициализация до нуля

Тем не менее, Scala поддерживает null. Я лично использую его в сочетании с Spring Injection of Dependency.

Ваш код отлично работает. Однако я предлагаю вам использовать 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

Дополнительно

Использование 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 }

Вы можете добавить неявный параметр в качестве доказательства того, что t имеет значение NULL - подтип AnyRef не подтип NotNull Это не полностью испеченный, даже в Scala 2.8, поэтому просто подумайте об этом сейчас.

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

Ответ 2

Канонический ответ не использует null. Вместо этого используйте тип опции:

var a = None : Option[MyObject]

Если вы хотите установить его:

a = Some(foo)

И когда вы хотите прочитать из него, проверьте на None:

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

Ответ 3

Как уже упоминалось Дэвидом и ретроном, рекомендуется использовать Option в большинстве случаев, поскольку Option делает более очевидным, что вам приходится обрабатывать ситуацию без результата. Однако для возврата Some(x) требуется создание объекта, а вызов .get или .getOrElse может быть дороже, чем if-statement. Таким образом, при использовании высокопроизводительного кода использование Option не всегда является лучшей стратегией (особенно в коде поиска, где вы можете найти значение очень много раз и не хотите, соответственно, много создания объектов). Опять же, если вы делаете что-то вроде возврата текста всей веб-страницы (которая может отсутствовать), нет причин не использовать параметр.

Кроме того, просто чтобы добавить к методу retron для дженериков с null, вы можете сделать это в полном объеме, если вы действительно имеете в виду, что это должно быть null:

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

и это работает в 2.7 и 2.8. Это немного менее общий, чем метод <:<, потому что он не подчиняется NotNull AFAIK, но в противном случае делает именно то, что вы надеялись бы сделать.

Ответ 4

Я столкнулся с этим вопросом, так как scalastyle сказал мне не использовать null при инициализации объекта в моем тесте с помощью null.

Мое решение без изменения какого-либо типа, удовлетворяющего scalastyle:

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