NULL Kotlin против Java необязательно

В этом посте мы рассмотрим, как тип Optional сравнивается и переводится с nullable типами в Kotlin.

Необязательные/нулевые свойства и типы возврата

В Java свойство Optional может быть объявлено следующим образом:

public interface Person {
  String getName();  
  Optional<Integer> getAge();
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Вместо того чтобы использовать тип Optional, в Kotlin мы просто объявим свойство act как nullable:

interface Person { 
  val name : String 
  val age : Int? 
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Optional.map() против оператора безопасного вызова

Метод map() типа Optional можно использовать для доступа к свойствам инкапсулированного экземпляра “empty-safe” способом.

public interface Car {
  Person getDriver();
}
Optional<Car> car = getNextCarIfPresent();

Optional<Integer> driversAge =
    car.map(Car::getDriver).flatMap(Person::getAge);
Войдите в полноэкранный режим Выход из полноэкранного режима

Этот фрагмент кода извлекает водителя необязательного автомобиля, а затем извлекает необязательный возраст этого водителя. Поскольку и автомобиль, и возраст являются необязательными, мы вынуждены использовать метод flatMap() для получения возраста водителя. В Kotlin мы можем использовать встроенный оператор безопасного вызова ?. для доступа к свойствам типов Nullable:

interface Car {
  val driver: Person
}
val car: Car? = getNextCarIfPresent()

val driversAge: Int? = car?.driver?.age
Войдите в полноэкранный режим Выход из полноэкранного режима

Optional.map() против функции let()

Иногда мы хотим использовать внешний метод в безопасной цепочке вызовов на типе Optional. С типом Optional в Java для этой цели можно использовать тот же метод map():

Optional<DriversLicence> driversLicence =
    car.map(Car::getDriver).map(licenceService::getDriversLicence);
Войдите в полноэкранный режим Выход из полноэкранного режима

В Kotlin для достижения той же цели нам придется использовать функцию let() из stdlib для вызова внешних функций в цепочке операторов безопасного вызова.

val driversLicence: DriversLicence? = car?.driver?.let {
    licenceService.getDriversLicence(it) 
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Optional.orElse() против оператора Элвиса

Когда мы извлекаем значение, заключенное в Optional, мы обычно хотим предоставить запасное значение. Это достигается с помощью метода *orElse()* типа Optional :

boolean isOfLegalAge =
    car.map(Car::getDriver).flatMap(Person::getAge).orElse(0) > 18;
Войдите в полноэкранный режим Выход из полноэкранного режима

Если строка вызова карты возвращает непустой возраст, он будет использован. В противном случае будет использовано резервное значение 0. В Kotlin для этой цели есть оператор elvis ?::

val isOfLegalAge: Boolean = car?.driver?.age ?: 0 > 18
Войдите в полноэкранный режим Выход из полноэкранного режима

Функция optional.filter() против функции takeIf()

Дополнительный тип предоставляет метод filter(), который можно использовать для проверки условия на инкапсулированное значение. Если условие удовлетворяется инкапсулированным значением, метод фильтрации вернет тот же объект Optional. В противном случае будет возвращен пустой объект Optional.

Optional<Person> illegalDriver =
    car.map(Car::getDriver).filter(p -> p.getAge().orElse(0) < 18);
Войдите в полноэкранный режим Выход из полноэкранного режима

В Kotlin мы используем функцию takeIf() из stdlib и в итоге получаем гораздо меньше кода:

val ilegalDriver: Pessoa? = carro?.motorista ?. takeIf { it.idade ?: 0 < 18 }
Войдите в полноэкранный режим Выход из полноэкранного режима

Функция Optional.ifPresent() против функции let()

В конце преобразования и фильтрации необязательного значения мы обычно хотим использовать инкапсулированное значение в каком-либо расчете или коде. Для этого тип Optional предоставляет метод ifPresent():

car.map(Car::getDriver) 
    .filter(person -> person.getAge().orElse(0) < 18) 
    . ifPresent (illegalDriver -> { 
        checkIdentity(illegalDriver); 
        putInJail(illegalDriver); 
    });
Войдите в полноэкранный режим Выход из полноэкранного режима

В Kotlin мы снова использовали бы для этого функцию let():

car?.driver?.takeIf { it.age ?: 0 < 18 }?.let { illegalDriver ->
  checkIdentity(illegalDriver)
  putInJail(illegalDriver)
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Kotlin предоставляет множество встроенных операторов и функций stdlib, которые упрощают работу с nullable типами. Их использование приводит к созданию короткого, лаконичного и читабельного кода, особенно при объединении в длинные строки вызовов.

Помимо более читабельного кода, типы nullable в Kotlin имеют ряд преимуществ перед типом Optional в Java.

Во-первых, при использовании nullable-типов в Kotlin¹ нет никаких накладных расходов во время выполнения. В отличие от Optional, не создается объект-обертка для связывания фактического значения.

Во-вторых, нулевые типы в Kotlin обеспечивают нулевую безопасность во время компиляции. Их небезопасное использование приведет к ошибке компиляции. С другой стороны, использование типа Optional небезопасным образом не проверяется компилятором и приведет к исключению во время выполнения.

a menos que estejamos lidando com tipos primitivos anuláveis, caso em que a versão em caixa do tipo primitivo é usada no nível da JVM.

Ссылка

https://docs.google.com/spreadsheets/d/1P2gMRuu36pSDW4fdwE-fLN9fcA_ZboIU2Q5VtgixBNo/edit#gid=0

https://www.zup.com.br/blog/java-vs-kotlin-vantagens-desvantagens

Оцените статью
Procodings.ru
Добавить комментарий