Jini's Blog

Ing...

  • Home
  • Business
    • Internet
    • Market
    • Stock
  • Parent Category
    • Child Category 1
      • Sub Child Category 1
      • Sub Child Category 2
      • Sub Child Category 3
    • Child Category 2
    • Child Category 3
    • Child Category 4
  • Featured
  • Health
    • Childcare
    • Doctors
  • Home
  • Business
    • Internet
    • Market
    • Stock
  • Downloads
    • Dvd
    • Games
    • Software
      • Office
  • Parent Category
    • Child Category 1
      • Sub Child Category 1
      • Sub Child Category 2
      • Sub Child Category 3
    • Child Category 2
    • Child Category 3
    • Child Category 4
  • Featured
  • Health
    • Childcare
    • Doctors
  • Uncategorized

26 Reasons Why Using Optional Correctly Is Not Optional

 Jini     오후 2:04     JAVA, optional     No comments   

1. Never Assign Null to an Optional Variable

Avoid:


// AVOID
public Optional<Cart> fetchCart() {
 Optional<Cart> emptyCart = null;
 ...
}

Prefer:


// PREFER
public Optional<Cart> fetchCart() {
 Optional<Cart> emptyCart = Optional.empty();
 ...
}


2. Ensure That an Optional Has a Value Before Calling Optional.get()

Avoid:


// AVOID
Optional<Cart> cart = ... ; // this is prone to be empty
...
// if "cart"is empty then this code will throw a java.util.NoSuchElementException
Cart myCart = cart.get();

Prefer:


// PREFER
if (cart.isPresent()) {
 Cart myCart = cart.get();
 ... // do something with "myCart"
} else {
 ... // do something that doesn't call cart.get()
}


3. When No Value Is Present, Set/Return an Already-Constructed Default Object Via the Optional.orElse() Method

use orElse() only when the parameter (the default
object) is already constructed.

Avoid:


// AVOID
public static final String USER_STATUS = "UNKNOWN";
...
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  
  if (status.isPresent()) {
    return status.get();
  } else {
    return USER_STATUS;
  }
}

Prefer:


// PREFER
public static final String USER_STATUS = "UNKNOWN";
...
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  return status.orElse(USER_STATUS);
}


4. When No Value Is Present, Set/Return a Non-Existent Default Object Via the Optional.orElseGet() Method

The important thing here is that the parameter of orElseGet() is a Java 8, Supplier. This means that the Supplier method passed as an argument is only executed
when an Optional value is not present.

Avoid:


// AVOID
public String computeStatus() {
  ... // some code used to compute status
}
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  
  if (status.isPresent()) {
    return status.get();
  } else {
    return computeStatus();
  }
}    

Also, Avoid:


// AVOID
public String computeStatus() {
  ... // some code used to compute status
}
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  // computeStatus() is called even if "status" is not empty
  return status.orElse(computeStatus()); 
}

Prefer:


// PREFER
public String computeStatus() {
  ... // some code used to compute status
}
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  // computeStatus() is called only if "status" is empty
  return status.orElseGet(this::computeStatus);
}


5. When No Value Is Present, Throw a java.util.NoSuchElementException Exception Via orElseThrow() Since Java 10

Avoid:


// AVOID
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  
  if (status.isPresent()) {
    return status.get();
  } else {
    throw new NoSuchElementException(); 
  }
}    

Prefer:


// PREFER
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  return status.orElseThrow();
}

6. When No Value Is Present, Throw an Explicit Exception Via orElseThrow(Supplier<? extends X>
exceptionSupplier)

Avoid:


// AVOID
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  
  if (status.isPresent()) {
    return status.get();
  } else {
    throw new IllegalStateException(); 
  }
}
    

Prefer:


// PREFER
public String findUserStatus(long id) {
  Optional<String> status = ... ; // prone to return an empty Optional
  return status.orElseThrow(IllegalStateException::new);
}    
    

7. When You Have an Optional and Need a Null Reference, Use orElse(null)

Avoid:


// AVOID
Method myMethod = ... ;
...
// contains an instance of MyClass or empty if "myMethod" is static
Optional<MyClass> instanceMyClass = ... ;
...
if (instanceMyClass.isPresent()) {
  myMethod.invoke(instanceMyClass.get(), ...); 
} else {
  myMethod.invoke(null, ...); 
}        

Prefer:


// PREFER
Method myMethod = ... ;
...
// contains an instance of MyClass or empty if "myMethod" is static
Optional<MyClass> instanceMyClass = ... ;
...
myMethod.invoke(instanceMyClass.orElse(null), ...);        


8. Consume an Optional if it Is Present. Do Nothing if it Is Not Present. This Is a Job For
Optional.ifPresent().

Avoid:


// AVOID
Optional<String> status = ... ;
...
if (status.isPresent()) {
  System.out.println("Status: " + status.get());
}        
        

Prefer:


// PREFER
Optional<String> status ... ;
...
status.ifPresent(System.out::println);                


9. Consume an Optional if it Is Present. If it Is Not Present, Then Execute an Empty-Based Action. This Is a Job
For Optional.ifPresentElse(), Java 9.

Avoid:


// AVOID
Optional<String> status = ... ;

if(status.isPresent()) {
  System.out.println("Status: " + status.get());
} else {
  System.out.println("Status not found");
}

Prefer:


// PREFER
Optional<String> status = ... ;

status.ifPresentOrElse(
  System.out::println, 
  () -> System.out.println("Status not found")
);   


10. When the Value Is Present, Set/Return That Optional. When No Value Is Present, Set/Return the Other
Optional. This Is a Job For Optional.or(), Java 9.

Avoid:


// AVOID
public Optional<String> fetchStatus() {
  Optional<String> status = ... ;
  Optional<String> defaultStatus = Optional.of("PENDING");
  
  if (status.isPresent()) {
    return status;
  } else {
    return defaultStatus;
  } 
}

Also, Avoid:


// AVOID
public Optional<String> fetchStatus() {

  Optional<String> status = ... ;
  
  return status.orElseGet(() -> Optional.<String>of("PENDING"));
}

Prefer:


// PREFER
public Optional<String> fetchStatus() {
  Optional<String> status = ... ;
  Optional<String> defaultStatus = Optional.of("PENDING");
  
  return status.or(() -> defaultStatus);
  
  // or, without defining "defaultStatus"
  return status.or(() -> Optional.of("PENDING"));
}


11. Optional.orElse/ orElseXXX Are a Perfect Replacement for isPresent()-get() Pair in Lambdas

Sample 1

Avoid:


// AVOID
List<Product> products = ... ;
Optional<Product> product = products.stream()
  .filter(p -> p.getPrice() < price)
  .findFirst();
  
if (product.isPresent()) {
  return product.get().getName();
} else {
  return "NOT FOUND";
}
        

Also, Avoid:


// AVOID
List<Product> products = ... ;

Optional<Product> product = products.stream()
  .filter(p -> p.getPrice() < price)
  .findFirst();
  
return product.map(Product::getName)
  .orElse("NOT FOUND");    
    

Prefer:


// PREFER
List<Product> products = ... ;

return products.stream()
  .filter(p -> p.getPrice() < price)
  .findFirst()
  .map(Product::getName)
  .orElse("NOT FOUND");
    

Sample 2

Avoid:


// AVOID
Optional<Cart> cart = ... ;
Product product = ... ;
...
if(!cart.isPresent() || 
  !cart.get().getItems().contains(product)) {
  throw new NoSuchElementException();
}
    

Prefer:


// PREFER
Optional<Cart> cart = ... ;
Product product = ... ;
...
cart.filter(c -> c.getItems().contains(product)).orElseThrow();        
    


12. Avoid Chaining Optional’s Methods With the Single Purpose of Getting a Value

Avoid:


// AVOID
public String fetchStatus() {
  String status = ... ;
  return Optional.ofNullable(status).orElse("PENDING");
}
    

Prefer:


// PREFER
public String fetchStatus() {
  String status = ... ;
  return status == null ? "PENDING" : status;
}
    


13. Do Not Declare Any Field of Type Optional

Avoid:


// AVOID
public class Customer {
  [access_modifier] [static] [final] Optional<String> zip;
  [access_modifier] [static] [final] Optional<String> zip = Optional.empty();
  ...
}    
    

Prefer:


// PREFER
public class Customer {
  [access_modifier] [static] [final] String zip;
  [access_modifier] [static] [final] String zip = "";
  ...
}
    


14. Do Not Use Optional in Constructors Arguments

Avoid:


// AVOID
public class Customer {
  private final String name;               // cannot be null
  private final Optional<String> postcode; // optional field, thus may be null
  
  public Customer(String name, Optional<String> postcode) {
    this.name = Objects.requireNonNull(name, () -> "Name cannot be null");
    this.postcode = postcode;
  }
  
  public Optional<String> getPostcode() {
    return postcode;
  }
  ...
}
    

Prefer:


// PREFER
public class Customer {
  private final String name;     // cannot be null
  private final String postcode; // optional field, thus may be null
  
  public Cart(String name, String postcode) {
    this.name = Objects.requireNonNull(name, () -> "Name cannot be null");
    this.postcode = postcode;
  }
  
  public Optional<String> getPostcode() {
    return Optional.ofNullable(postcode);
  }
  ...
}
    


15. Do Not Use Optional in Setters Arguments

Avoid:


// AVOID
@Entity
public class Customer implements Serializable {
  private static final long serialVersionUID = 1L;
  ...

  @Column(name="customer_zip")
  private Optional<String> postcode; // optional field, thus may be null
  public Optional<String> getPostcode() {
    return postcode;
  }
  
  public void setPostcode(Optional<String> postcode) {
    this.postcode = postcode;
  }
  ...
}
    

Prefer:


// PREFER
@Entity
  public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;
  ...
  @Column(name="customer_zip")
  private String postcode; // optional field, thus may be null
  public Optional<String> getPostcode() {
    return Optional.ofNullable(postcode);
  }

  public void setPostcode(String postcode) {
    this.postcode = postcode;
  }
  ...
}
    


16. Do Not Use Optional in Methods Arguments

Avoid:


// AVOID

public void renderCustomer(Cart cart, Optional<Renderer> renderer,
                            Optional<String> name) { 
  if (cart == null) {
    throw new IllegalArgumentException("Cart cannot be null");
  }
  
  Renderer customerRenderer = renderer.orElseThrow(
    () -> new IllegalArgumentException("Renderer cannot be null")
  ); 
  
  String customerName = name.orElseGet(() -> "anonymous"); 
  ...
}

// call the method - don't do this
renderCustomer(cart, Optional.<Renderer>of(CoolRenderer::new), Optional.empty());
    

Prefer:


// PREFER
public void renderCustomer(Cart cart, Renderer renderer, String name) {
  if (cart == null) {
    throw new IllegalArgumentException("Cart cannot be null");
  }

  if (renderer == null) {
    throw new IllegalArgumentException("Renderer cannot be null");
  }

  String customerName = Objects.requireNonNullElseGet(name, () -> "anonymous");
  ...
}
// call this method
renderCustomer(cart, new CoolRenderer(), null);
    

Also, Prefer:


// PREFER
public void renderCustomer(Cart cart, Renderer renderer, String name) {
  Objects.requireNonNull(cart, "Cart cannot be null"); 
  Objects.requireNonNull(renderer, "Renderer cannot be null"); 
  String customerName = Objects.requireNonNullElseGet(name, () -> "anonymous");
  ...
}

// call this method
renderCustomer(cart, new CoolRenderer(), null);
    


17. Do Not Use Optional to Return Empty Collections or Arrays

Avoid:


// AVOID
public Optional<List<String>> fetchCartItems(long id) {
  Cart cart = ... ; 
  List<String> items = cart.getItems(); // this may return null
  return Optional.ofNullable(items);
}
    

Prefer:


// PREFER
public List<String> fetchCartItems(long id) {
  Cart cart = ... ; 
  List<String> items = cart.getItems(); // this may return null
  return items == null ? Collections.emptyList() : items;
}
    


18. Avoid Using Optional in Collections

Avoid:


// AVOID
Map<String, Optional<String>> items = new HashMap<>();
items.put("I1", Optional.ofNullable(...));
items.put("I2", Optional.ofNullable(...));
...
Optional<String> item = items.get("I1");

if (item == null) {
  System.out.println("This key cannot be found");
  
} else {
  String unwrappedItem = item.orElse("NOT FOUND");
  System.out.println("Key found, Item: " + unwrappedItem);
}
    

Prefer:


//PREFER
Map<String, String> items = new HashMap<>();
items.put("I1", "Shoes");
items.put("I2", null);
...
// get an item
String item = get(items, "I1");  // Shoes
String item = get(items, "I2");  // null
String item = get(items, "I3");  // NOT FOUND

private static String get(Map<String, String> map, String key) {
  return map.getOrDefault(key, "NOT FOUND");
}
    


19. Do Not Confuse Optional.of() and Optional.ofNullable()

Avoid:


// AVOID
public Optional<String> fetchItemName(long id) {
  String itemName = ... ; // this may result in null
  ...
  return Optional.of(itemName); // this throws NPE if "itemName" is null :(
}
    

Prefer:


// PREFER
public Optional<String> fetchItemName(long id) {
  String itemName = ... ; // this may result in null
  ...
  return Optional.ofNullable(itemName); // no risk for NPE 
}
    


20. Avoid Optional and Choose Non-Generic OptionalInt, OptionalLong, or OptionalDouble

Avoid:


// AVOID
Optional<Integer> price = Optional.of(50);
Optional<Long> price = Optional.of(50L);
Optional<Double> price = Optional.of(50.43d);
    

Prefer:


// PREFER
OptionalInt price = OptionalInt.of(50);           // unwrap via getAsInt()
OptionalLong price = OptionalLong.of(50L);        // unwrap via getAsLong()
OptionalDouble price = OptionalDouble.of(50.43d); // unwrap via getAsDouble()
    


21. There Is No Need to Unwrap Optionals for Asserting Equality

Avoid:


// AVOID
Optional<String> actualItem = Optional.of("Shoes");
Optional<String> expectedItem = Optional.of("Shoes"); 
assertEquals(expectedItem.get(), actualItem.get());
    

Prefer:


// PREFER
Optional<String> actualItem = Optional.of("Shoes");
Optional<String> expectedItem = Optional.of("Shoes"); 
assertEquals(expectedItem, actualItem);
    


22. Transform Values Via Map() and flatMap()

Using map()

Example1

Avoid:


// AVOID
Optional<String> lowername ...; // may be empty
// transform name to upper case
Optional<String> uppername;

if (lowername.isPresent()) {
  uppername = Optional.of(lowername.get().toUpperCase());
} else {
  uppername = Optional.empty();
}
    

Prefer:


// PREFER
Optional lowername ...; // may be empty
// transform name to upper case
Optional uppername = lowername.map(String::toUpperCase);
    

Example2

Avoid:


// AVOID
List<Product> products = ... ;
Optional<Product> product = products.stream()
  .filter(p -> p.getPrice() < 50)
  .findFirst();

String name;
if (product.isPresent()) {
  name = product.get().getName().toUpperCase();
} else {
  name = "NOT FOUND";
}

// getName() return a non-null String
public String getName() {
  return name;
}
    

Prefer:


// PREFER
List<Product> products = ... ;

String name = products.stream()
  .filter(p -> p.getPrice() < 50)
  .findFirst()
  .map(Product::getName)
  .map(String::toUpperCase)
  .orElse("NOT FOUND");

// getName() return a String
public String getName() {
  return name;
}
  

Using flatMap()

Avoid:


// AVOID
List<Product> products = ... ;

Optional<Product> product = products.stream()
  .filter(p -> p.getPrice() < 50)
  .findFirst();

String name = null;
if (product.isPresent()) {
  name = product.get().getName().orElse("NOT FOUND").toUpperCase();
}

// getName() return an Optional
public Optional<String> getName() {
  return Optional.ofNullable(name);
}    
    

Prefer:


// PREFER

List<Product> products = ... ;

String name = products.stream()
  .filter(p -> p.getPrice() < 50)
  .findFirst()
  .flatMap(Product::getName)
  .map(String::toUpperCase)
  .orElse("NOT FOUND");

// getName() return an Optional
public Optional<String> getName() {
  return Optional.ofNullable(name);
}    
    


23. Reject Wrapped Values Based on a Predefined Rule Using filter()

Avoid:


// AVOID
public boolean validatePasswordLength(User userId) {
  Optional<String> password = ...; // User password
  
  if (password.isPresent()) {
    return password.get().length() > 5;
  }
  return false;
}
    

Prefer:


// PREFER
public boolean validatePasswordLength(User userId) {
  Optional<String> password = ...; // User password
  return password.filter((p) -> p.length() > 5).isPresent();
}
    


24. Do We Need to Chain the Optional API With the Stream API?

Practically, Optional.stream() allows us to replace filter() and map() with flatMap().

Avoid:


// AVOID
public List<Product> getProductList(List<String> productId) {
  return productId.stream()
    .map(this::fetchProductById)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(toList());
}

public Optional<Product> fetchProductById(String id) {
  return Optional.ofNullable(...);
}
    

Prefer:


// PREFER
public List<Product> getProductList(List<String> productId) {
  return productId.stream()
    .map(this::fetchProductById)
    .flatMap(Optional::stream)
    .collect(toList());
}

public Optional<Product> fetchProductById(String id) {
  return Optional.ofNullable(...);
}
    


25. Avoid Using Identity-Sensitive Operations on Optionals

Avoid:


// AVOID
Product product = new Product();
Optional<Product> op1 = Optional.of(product);
Optional<Product> op2 = Optional.of(product);
// op1 == op2 => false, expected true
if (op1 == op2) { ...
    

Prefer:


// PREFER
Product product = new Product();
Optional<Product> op1 = Optional.of(product);
Optional<Product> op2 = Optional.of(product);
// op1.equals(op2) => true,expected true
if (op1.equals(op2)) { ...
    


26. Return a boolean If The Optional Is Empty. Prefer Java 11, Optional.isEmpty()

Avoid:


// AVOID (Java 11+)
public Optional<String> fetchCartItems(long id) {
  Cart cart = ... ; // this may be null
  ... 
  return Optional.ofNullable(cart);
}

public boolean cartIsEmpty(long id) {
  Optional<String> cart = fetchCartItems(id);
  return !cart.isPresent();
}
    

Prefer:


// PREFER (Java 11+)
public Optional<String> fetchCartItems(long id) {
  Cart cart = ... ; // this may be null
  ... 
  return Optional.ofNullable(cart);
}

public boolean cartIsEmpty(long id) {
  Optional<String> cart = fetchCartItems(id);
  return cart.isEmpty();
}
    

[출처]
https://dzone.com/articles/using-optional-correctly-is-not-optional
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
이메일로 전송BlogThis!X에 공유Facebook에서 공유
최근 게시물 이전 게시물 홈

0 Comments:

댓글 쓰기

Popular Posts

  • Redmine Text Format
    1. 글자색상 변경 %{color:red}dev% 2. 음영색상 변경 %{background:lightgreen} lightgreen% 3. 문단 넘버링(띄어쓰기 주의) # 큰 제목 ## 큰제목의 하위 제목 # 두번째 큰 제목 # ...
  • 오라클 한글깨짐 현상해결
    1. 레지스트리 편집기 실행 : 시작 -> 실행 -> regedit 2. HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE 하위 경로 폴더중 이름이 "NLS_LANG"인 속성의 데이터 확인 3. "...
  • 오브젝트 : 코드로 이해하는 객체지향 설계
    오브젝트 - 코드로 이해하는 객체지향 설계 / 조영호 지음 / 위키북스 객체지향에 대해 그 동안 잊고 있었던 것들을 상기시켜주고 새로운 인사이트를 줬으며 그 동안의 설계에 대해 돌이켜 보게 해준 유익한 책. 객체 사이의 의존성을 완전히 없애는 것이 정...
  • New Features Java 1.7(JDK 1.7)
    ■ The New Objects Class   1) Objects.requireNonNull(T), Objects.requireNonNull(T, String)     #. 아래 Person 객체 생성시 newLastName이나 newFirstNa...
  • MongoDB Array Query(With MongoTemplate)
    Mongo Collection 구조 컬렉션명 : bookstore { "_id": "1234567890", "books": [ { "bookId": ...

Recent Posts

Recent Posts Widget

Blog Archive

  • ►  2023 (4)
    • ►  3월 (1)
    • ►  2월 (1)
    • ►  1월 (2)
  • ►  2022 (1)
    • ►  2월 (1)
  • ▼  2020 (8)
    • ►  7월 (1)
    • ►  4월 (3)
    • ▼  3월 (4)
      • Blog Template
      • 구글 블로그 페이지 네비게이션 변경
      • 26 Reasons Why Using Optional Correctly Is Not Opt...
      • Why should one use Objects.requireNonNull()?
  • ►  2018 (1)
    • ►  7월 (1)
  • ►  2015 (1)
    • ►  5월 (1)
  • ►  2014 (5)
    • ►  8월 (1)
    • ►  7월 (1)
    • ►  6월 (1)
    • ►  5월 (1)
    • ►  1월 (1)
  • ►  2013 (10)
    • ►  12월 (1)
    • ►  11월 (1)
    • ►  9월 (2)
    • ►  8월 (3)
    • ►  7월 (3)
  • ►  2012 (1)
    • ►  3월 (1)

Categories

  • 객체지향 (1)
  • 도서요약 (1)
  • 문법에서 문장까지 (2)
  • 일상 (1)
  • 자기계발 (1)
  • 책 (1)
  • 키보드 (1)
  • 키크론 (1)
  • blogspot (2)
  • error (1)
  • exception (1)
  • GIT (1)
  • JAVA (6)
  • JUNIT (1)
  • K8 PRO RGB (1)
  • kafka (1)
  • markdown (1)
  • mongodb (2)
  • mongotemplate (1)
  • optional (1)
  • Oracle (4)
  • Redmine (1)
  • spring (1)
  • stackedit (1)
  • troubleshooting (1)
  • Visual Studio (1)
  • Webflux (1)

Unordered List

Pages

  • 홈

Text Widget

Categories

Tags

Facebook

  • Home
  • Features
  • _Multi DropDown
  • __DropDown 1
  • __DropDown 2
  • __DropDown 3
  • _ShortCodes
  • _SiteMap
  • _Error Page
  • Documentation
  • Video Documentation
  • Download This Template

Footer Menu Widget

  • Home
  • About
  • Contact Us

Social Plugin

JINI. Powered by Blogger.

Copyright © Jini's Blog | Powered by Blogger
Design by Hardeep Asrani | Blogger Theme by NewBloggerThemes.com | Distributed By Gooyaabi Templates