NULL Kotlin vs. Java Optional
Tags: kotlin, java
Published: 2022-05-27 20:04:02

Neste post veremos como o tipo **Optional** compara e traduz para tipos **nullable** em **Kotlin**.

##  Optional/Nullable Propriedades e tipos de retorno 

Em Java, uma propriedade **Optional** pode ser declarada da seguinte forma:

```java
public interface Person {
  String getName();  
  Optional<Integer> getAge();
}
```

Em vez de usar o tipo **Optional**, em **Kotlin** vamos apenas declarar a propriedade age como anulável:

```kotlin
interface Person { 
  val name : String 
  val age : Int? 
}
```

##  Optional.map() vs. Safe-Call Operator 

O método *map()* do tipo Optional pode ser usado para acessar as propriedades da instância encapsulada de uma maneira “`empty-safe`”.

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

Optional<Integer> driversAge =
    car.map(Car::getDriver).flatMap(Person::getAge);
```

Este trecho de código recupera o motorista de um carro opcional e, em seguida, recupera a idade opcional desse motorista. Como ambos, o carro e a idade são opcionais, somos forçados a usar o método *flatMap()* ao recuperar a idade do motorista. Em Kotlin, podemos usar o **operador de chamada segura embutido ?.** para acessar propriedades de tipos  Nullable :

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

val driversAge: Int? = car?.driver?.age
```

##  Optional.map() vs. let() Function 

Às vezes, queremos usar um método externo dentro da cadeia de chamadas seguras no tipo Optional. Com o tipo Optional do Java, o mesmo método *`map()`* pode ser usado para esta finalidade:

```java
Optional<DriversLicence> driversLicence =
    car.map(Car::getDriver).map(licenceService::getDriversLicence);
```

Em Kotlin, teremos que usar a função *let()* do stdlib para invocar funções externas dentro de uma cadeia de operadores de chamada segura para atingir o mesmo objetivo.

```java
val driversLicence: DriversLicence? = car?.driver?.let {
    licenceService.getDriversLicence(it) 
}
```

##  Optional.orElse() vs. Elvis Operator 

Quando recuperamos o valor encapsulado por um Optional, geralmente queremos fornecer um valor de fallback. Isso é obtido usando o método `*orElse()*` do tipo Opcional :

```java
boolean isOfLegalAge =
    car.map(Car::getDriver).flatMap(Person::getAge).orElse(0) > 18;
```

Quando a cadeia de chamadas de *mapa* retornar uma idade não vazia, ela será usada. Caso contrário, o valor de fallback fornecido *0* será usado. Kotlin tem o **elvis Operator ?:** para este propósito:

```java
val isOfLegalAge: Boolean = car?.driver?.age ?: 0 > 18
```

##  Optional.filter() vs. takeIf() Function 

O tipo opcional fornece o método *`filter()`* , que pode ser usado para verificar uma condição no valor encapsulado. Se a condição for satisfeita pelo valor encapsulado, o método de filtro retornará o mesmo objeto Optional. Caso contrário, retornará um objeto Optional vazio.

```java
Optional<Person> illegalDriver =
    car.map(Car::getDriver).filter(p -> p.getAge().orElse(0) < 18);
```

Em Kotlin, usamos a função *takeIf()* do stdlib e acabamos com muito menos código:

```java
val ilegalDriver: Pessoa? = carro?.motorista ?. takeIf { it.idade ?: 0 < 18 }
```

##  Optional.ifPresent() vs. let() Function 

Ao final da conversão e filtragem do valor Optional, geralmente queremos usar o valor encapsulado em algum cálculo ou código. Para isso, o tipo Optional fornece o método *`ifPresent()`* :

```java
car.map(Car::getDriver) 
    .filter(person -> person.getAge().orElse(0) < 18) 
    . ifPresent (illegalDriver -> { 
        checkIdentity(illegalDriver); 
        putInJail(illegalDriver); 
    });
```

Em Kotlin, usaríamos novamente a função *let()* para isso:

```java
car?.driver?.takeIf { it.age ?: 0 < 18 }?.let { illegalDriver ->
  checkIdentity(illegalDriver)
  putInJail(illegalDriver)
}
```

Kotlin fornece uma variedade de operadores integrados e funções stdlib que simplificam o manuseio de tipos anuláveis. Usá-los leva a um código curto, conciso e legível, especialmente quando combinado em cadeias de chamadas mais longas.

Além do código mais legível, os tipos anuláveis do Kotlin têm várias vantagens sobre o tipo Optional do Java.

Primeiro, não há sobrecarga de tempo de execução envolvida ao usar tipos anuláveis em Kotlin¹. Ao contrário de Opcional, nenhum objeto wrapper é criado para agrupar o valor real.

Em segundo lugar, os tipos anuláveis em Kotlin fornecem segurança nula em tempo de compilação. Usá-los de maneira não segura levará a um erro em tempo de compilação. Por outro lado, usar o tipo Optional de maneira não segura não é verificado pelo compilador e levará a uma exceção de tempo de execução.

*`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.`*

## Referência

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

[https://www.zup.com.br/blog/java-vs-kotlin-vantagens-desvantagens](https://www.zup.com.br/blog/java-vs-kotlin-vantagens-desvantagens)