Это правильный способ инициализации нулевых ссылок в Scala? - PullRequest
50 голосов
/ 14 марта 2010

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

var a:MyObject = null

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

Ответы [ 4 ]

61 голосов
/ 14 марта 2010

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

Используйте 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

Advanced

Использование 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 обнуляем - подтип AnyRef не подтип NotNull Это не полностью запеченный , даже в Scala 2.8, так что пока просто посчитайте это любопытным.

scala> class A[T](implicit ev: Null <:< T) { var t: T = null }           
defined class A
32 голосов
/ 14 марта 2010

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

var a = None : Option[MyObject]

Когда вы хотите установить:

a = Some(foo)

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

a match {
  case None => Console.println("not here")
  case Some(value) => Console.println("got: "+value)
}
8 голосов
/ 14 марта 2010

Как уже упоминали Дэвид и ретроним, в большинстве случаев рекомендуется использовать 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, но в остальном он делает именно то, на что вы надеетесь.

0 голосов
/ 15 февраля 2017

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

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

var a: MyObject = (None: Option[MyObject]).orNull
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...