Tags:

Những tính năng mới của Optional trong Java 9

Optional class lần đầu được giới thiệu trong Java 8 giúp các lập trình viên giảm thiểu đáng kể việc sinh ra lỗi NullPointerException. Trong phiên bản Java 9 lần này, nhà phát triển đã nâng cấp một số tính năng với mục đích hướng đến việc dễ sử dụng và tiện lợi hơn.

Optional Trong Java 8

Được giới thiệu trong Java 8, Optional là một wrapper object có thể chứa dữ liệu của một kiểu dữ liệu bất kỳ hoặc mang giá trị NULL tương ứng. 

Thông thường thì các developer chúng ta khai báo và sử dụng object rất hay khuyên kiểm tra NOT NULL trước khi sử dụng dẫn đến NullPointerException. Đối với bản thân mình cảm thấy việc lúc nào cũng check null thật sự là rất nhàm chán, có khi nhìn vào mã nguồn thấy xấu hẳn đi.

Optional is coming, với Optional dùng để wrapper bên ngoài object, các bạn yên tâm rằng các bạn không thể quên được kiểm tra NOT NULL được đâu. Vì khi thao tác với Optional thì các hàm Optional cung cấp sẵn để có thể truy xuất được giá trị bên trong chứ không thể đi trực tiếp được. 

Optional<String > opt = Optional.of("shareprogramming.net");

opt.ifPresent(s -> System.out.println(s.length())); // 20

Như các bạn có thể thấy rằng, ifPresent dùng để kiểm tra nếu object bên trong NOT NULL thì mới thực thi đoạn code được triển khai bên trong.

Optional trong Java 9

Trong Java 9, Oracle Corp đã giới thiệu thêm 3 method mới vào Optional class:

  • stream()
  • ifPresentOrElse()
  • or()

Chúng ta sẽ tìm hiểu từng method này và làm các ví dụ để có thể hiểu rõ hơn về nó.

Java 9 Optional Stream

Stream API trong Java trước đây có thể hoạt động trên các collection và tỏ ra rất mạnh về tính linh hoạt. Trong phiên bản mới lần này stream() method cũng đã được thêm vào Optional class cho phép chúng ta triển khai các stream api trên đó.

@Test
public void givenOptionalOfSome_whenToStream_thenShouldTreatItAsOneElementStream() {
    // given
    Optional<String> value = Optional.of("a");

    // when
    List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());

    // then
    assertThat(collect).hasSameElementsAs(List.of("A"));
}

Mặt khác, nếu Optional rỗng,  việc gọi phương thức stream () trên nó sẽ tạo một Stream rỗng.

@Test
public void givenOptionalOfNone_whenToStream_thenShouldTreatItAsZeroElementStream() {
    // given
    Optional<String> value = Optional.empty();

    // when
    List<String> collect = value.stream()
      .map(String::toUpperCase)
      .collect(Collectors.toList());

    // then
    assertThat(collect).isEmpty();
}

Optional or() method

Đôi khi trong trường hợp Optional là một giá trị NULL, chúng ta muốn thực thi một hành động khác cũng trả về một Optional object..

Optional trong Java 8 chỉ có 2 method orElse()orElseGet() nhưng chúng trả một một object thay vì một Optional wrapper, điều này có thể gây khó khăn trong một số trường hợp chúng ta cần trả về một Optional. Đó là lý do của sự xuất hiện or() method.

Ví dụ dưới đây chúng ta sử dụng or() method để kiểm tra nếu value là một Optional Empty thì sẽ sẽ trả về defaultValue Optional cho result.

Tuy nhiên kết quả sẽ là defaultValue sẽ không được áp dụng trong trường hợp này vì value là một Optional NOT EMPTY.

@Test
public void givenOptional_whenPresent_thenShouldTakeAValueFromIt() {
    //given
    String expected = "properValue";
    Optional<String> value = Optional.of(expected);
    Optional<String> defaultValue = Optional.of("default");

    //when
    Optional<String> result = value.or(() -> defaultValue);

    //then
    assertThat(result.get()).isEqualTo(expected);
}

Ở ví dụ 2 defaultValue sẽ được áp dụng vì value lần này là một Optional.empty.

@Test
public void givenOptional_whenEmpty_thenShouldTakeAValueFromOr() {
    // given
    String defaultString = "default";
    Optional<String> value = Optional.empty();
    Optional<String> defaultValue = Optional.of(defaultString);

    // when
    Optional<String> result = value.or(() -> defaultValue);

    // then
    assertThat(result.get()).isEqualTo(defaultString);
}

Optional ifPresentOrElse method

Nếu chúng ta có một Optional instance, thông thước nếu chúng ta muốn thực thi một hành động nào đó dựa trên giá trị mà nó có, hoặc nếu Optional Empty thì chúng ta lại muốn thực thi một hành động khác.

Method ifPresentOrElse() được sinh ra để đáp ứng nhu cầu trên, chúng ta có thể truyền vào một Consumer implement là tham số thứ nhất sẽ được gọi khi Optional có giá trị và một Runnable sẽ được gọi khi Optional empty.

Ví dụ đầu tiên, Consumer sẽ được gọi vì Optional NOT NULL.

@Test
public void givenOptional_whenPresent_thenShouldExecuteProperCallback() {
    // given
    Optional<String> value = Optional.of("properValue");
    AtomicInteger successCounter = new AtomicInteger(0);
    AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

    // when
    value.ifPresentOrElse(
      v -> successCounter.incrementAndGet(), 
      onEmptyOptionalCounter::incrementAndGet);

    // then
    assertThat(successCounter.get()).isEqualTo(1);
    assertThat(onEmptyOptionalCounter.get()).isEqualTo(0);
}

Trong ví dụ 2 này, callback thứ 2 sẽ được gọi vì Optional empty.

@Test
public void givenOptional_whenNotPresent_thenShouldExecuteProperCallback() {
    // given
    Optional<String> value = Optional.empty();
    AtomicInteger successCounter = new AtomicInteger(0);
    AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

    // when
    value.ifPresentOrElse(
      v -> successCounter.incrementAndGet(), 
      onEmptyOptionalCounter::incrementAndGet);

    // then
    assertThat(successCounter.get()).isEqualTo(0);
    assertThat(onEmptyOptionalCounter.get()).isEqualTo(1);
}

Kết bài

Như vậy chúng ta có thể thấy trong phiên bản Java 9 lần này Optional đã được thêm một số tính năng mới rất tiện lợi và dễ sử dụng. Hỗ trợ tốt hơn trong quá trình phát triển ứng dụng của chúng ta. Còn chờ gì mà không nâng lên Java 9 nào.

Nguồn tham khảo

https://www.baeldung.com/java-9-optional

https://www.journaldev.com/13121/java-9-features-with-examples

 

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x