Почему не обязательно использовать переменные экземпляра? - PullRequest
7 голосов
/ 05 июня 2019

Я много читал о случаях, когда следует использовать Optional.

На многих страницах, которые я прочитал, говорится, что Optional не следует использовать для закрытых переменных экземпляра и вместо этого должно возвращаться получателями.

Я бы подумал, что иметь частные переменные экземпляра как необязательные все равно будет полезно.Если кто-нибудь посмотрит на мой код, он увидит, что значение может быть пустым, вместо того, чтобы проверять документацию, чтобы узнать, можно ли вернуть null.

В Scala null никогда не используется и используется только для взаимодействия с Java.Рекомендуется всегда использовать необязательный параметр, если значение может быть нулевым.Этот подход имеет гораздо больше смысла для меня.

Вот страница с упоминанием этого:

https://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html

Вот пример кода.

private final String addressLine;  // never null
private final String city;         // never null
private final String postcode;     // optional, thus may be null

// normal getters
public String getAddressLine() { return addressLine; }
public String getCity() { return city; }

// special getter for optional field
public Optional<String> getPostcode() {
  return Optional.ofNullable(postcode);
}

Единственное преимущество, которое я вижу, состоит в том, что если вы хотите сериализовать объект, то теперь это возможно, поскольку он не хранит необязательные в переменной.

Недостатком является то, что выНе знаю, почтовый индекс может быть нулевым, пока вы не проверите тип возвращаемого значения получателя.Если вы новичок в коде, вы можете пропустить это добавление, расширить класс, вызывая исключение нулевого указателя.

Здесь задается вопрос о Option в Scala.

Когда использовать Option

Почему существует разница между Java и Scala в том, как следует использовать опцию?

Ответы [ 4 ]

9 голосов
/ 05 июня 2019

Не все Java-разработчики даже согласны с подходом, который вы описали. Пожалуйста, проверьте этот пост от создателя Lombok.

Я полагаю, что причина использования другого подхода к использованию Optional в Java заключается в том, что сообщество Java до этого не доживало до Java 8, поэтому большинство людей привыкли к null . С одной стороны, множество новых API (например, findAny из Stream) возвращают Optional, но все же многие стандартные библиотечные методы просто возвращают null , поэтому вам всегда нужно помнить любой из них для переноса ваша функция вызывает Optional.ofNullable или проверьте, не является ли значение не нулевым.

Optional был добавлен в Java 8, но его не рекомендуется использовать в качестве полей класса, поскольку Optional не реализует Serializable (а сериализация Java используется в качестве механизма сериализации по умолчанию во многих средах или системах, таких как Akka, Искра, Кафка и др.).

С другой стороны, Option очень тесно связан со стандартной библиотекой Scala. Насколько мне известно, ни один из стандартных библиотечных API Scala не возвращает null , но Option, и не рекомендуется вообще использовать null в вашем коде Scala. Вы даже можете настроить свой проект так, чтобы он не компилировался, если null используется используется .

Option также Serializable, и его обычно используют в качестве полей класса для значений, которые могут быть пустыми.

Если вы хотите использовать подобный подход в своем коде Java, отметьте Option из Vavr . Он сериализуем, поэтому его можно безопасно использовать в качестве полей, а также он имеет два подкласса None и Some (аналогично Option в Scala), поэтому его можно использовать при сопоставлении с образцом Вавра:

Match(option).of(
    Case($Some($()), "defined"),
    Case($None(), "empty")
);
5 голосов
/ 05 июня 2019

В Scala Опция тесно интегрирована в API языка.

Представляет необязательные значения.Экземпляры Option являются экземпляром scala.Some или объектом None.Самый идиоматичный способ использования экземпляра scala.Option - это рассматривать его как коллекцию или монаду и использовать карту, flatMap, фильтр или foreach.

Как видно из приведенной выше цитаты,здесь нет null объяснения, потому что он должен использоваться как мондад или как коллекция.

В Java Необязательно используется, чтобы спасти нас от случаев NullPointerException, используя его как:

Контейнерный объект, который может содержать или не содержать ненулевое значение.Если значение присутствует, isPresent () вернет true, а get () вернет значение.

Язык программирования, который очень четко показывает пользователю, может ли переменная быть нулевой или нет, равен Kotlin , используя ?безопасный вызов , и показывает вам ошибки компиляции:

var a: String = "abc"
a = null // compilation error

var b: String? = "abc"
b = null // ok
print(b)
3 голосов
/ 05 июня 2019

Существует позиция, что Optional, как и Stream, является итеративным классом «event», не заслуживающим использования в качестве поля в «реальном» объекте.

Затем возникает недосказанность не быть сериализуемым (что можно обойти).

Однако мое мнение таково, что некоторые переменные могут быть необязательными , с количеством элементов 0 и 1. Так же, как список действителен. С полями List тенденция (IMHO) состоит в том, что изначально не разрешается быть нулевым, а всегда иметь (пустой) список.

В том же стиле кодирования Optional гарантирует, что используется только безопасный доступ, и, в частности, можно отобразить в стиле цепочки:

Optional<TextField> t = ...

String s = t.map(t::getText).orElse("N/A");
Optional<String> u = t.map(t::getText);
t.ifPresent(s -> { ... });

Особенно ifPresent гарантирует непреднамеренную работу с нулем.

Необязательная ценная спецификация.

0 голосов
/ 06 июня 2019

Одна из причин не использовать Optional для переменных экземпляра в том, что слишком просто для самой ссылки Optional быть null.Это нарушает подразумеваемый контракт около Optional, а именно, что вы никогда не должны создавать или встречать null ссылку на Optional.

class Foo {
    Optional<Bar> bar;
}

Foo f = new Foo();
if (f.bar.isPresent()) { // NullPointerException
    ...
}

Это самый простой способ создать класс с Optional поле в Java.В некотором смысле язык поощряет вас писать такой код.

С другой стороны, в Scala самый простой способ определить Foo - это

case class Foo(bar: Option[Bar])

, и это так легкосделать

case class Foo(bar: Option[Bar] = None)

оба из которых избегают NPE.

...