Optional 클래스는 Java 8에서 도입되었습니다. Optional 클래스의 목적은 null 참조 대신 Optional value로 표현되는 형식의 솔루션을 제공하는데 있습니다.
Optional 클래스를 사용하기 위해선 클래스를 import 해줘야 합니다.
import java.util.Optional;
1. 기본틀
예시)
import java.util.Optional;
public class prac1 {
public static void main(String[] args) {
// String 인스턴스를 저장한 Optional 인스턴스 생성, of 메소드 호출
Optional<String> os1 = Optional.of(new String("Toy1"));
// String 인스턴스를 저장한 Optional 인스턴스 생성, ofNullable 메소드 호출
Optional<String> os2 = Optional.ofNullable(new String("Toy2"));
if(os1.isPresent()) // 내용물 존재하면 isPresent는 true를 반환
System.out.println(os1.get()); // get을 통한 내용물 반환
if(os2.isPresent())
System.out.println(os2.get());
}
}
결과)
Toy1
Toy2
메소드 of와 ofNullable의 차이점은 null이 인자로 전달 될수 있는지입니다. of 메소드에서 null을 인자로 전달할 경우 NullPointerException이 발생합니다.
2. 람다식 사용
예시)
import java.util.Optional;
public class prac1 {
public static void main(String[] args) {
// String 인스턴스를 저장한 Optional 인스턴스 생성, of 메소드 호출
Optional<String> os1 = Optional.of(new String("Toy1"));
// String 인스턴스를 저장한 Optional 인스턴스 생성, ofNullable 메소드 호출
Optional<String> os2 = Optional.ofNullable(new String("Toy2"));
os1.ifPresent(s -> System.out.println(s)); // 람다식 버전
os2.ifPresent(System.out::println); // 메소드 참조 버전
}
}
결과)
Toy1
Toy2
람다식을 사용해서 다음과 같이 코드를 줄일 수 있습니다.
os1에 인스턴스가 저장하고 있는 내용물이 있으면, 이 내용물이 인자로 전달되면서 람다식이 실행됩니다.
3. if~else문을 대신할 수 있는 optional 클래스
예시)
import java.util.Optional;
class ContInfo {
String phone;
String adrs;
public ContInfo(String ph, String ad) {
phone = ph;
adrs = ad;
}
public String getPhone() { return phone; }
public String getAdrs() { return adrs; }
}
public class prac1 {
public static void main(String[] args) {
ContInfo ci = new ContInfo(null, "Republic of Korea");
String phone;
String addr;
if(ci.phone != null)
phone = ci.getPhone();
else
phone = "There is no phone number.";
if(ci.adrs != null)
addr = ci.getAdrs();
else
addr = "There is no address.";
System.out.println(phone);
System.out.println(addr);
}
}
결과)
There is no phone number.
Republic of Korea
String phone;과 String adrs는 null이 될 수 있습니다. 전화번호 정보가 없을 수 있고, 주소 정보가 없을 수 있기 때문입니다.
따라서 멤버가 null인 경우와 아닌 경우를 구분하기 위해선 if~else문장이 필요합니다. 하지만 map메소드를 이용하면 if~else문을 사용하지 않을 수 있습니다.
3-1. map메소드
예시)
import java.util.Optional;
public class prac1 {
public static void main(String[] args) {
Optional<String> os1 = Optional.of("Optional String");
Optional<String> os2 = os1.map(s -> s.toUpperCase()); // #1
System.out.println(os2.get());
Optional<String> os3 = os1.map(s -> s.replace(' ', '_')) // #2
.map(s -> s.toLowerCase());
System.out.println(os3.get());
}
}
결과)
OPTIONAL STRING
optional_string
#1 은 다음과 같은 의미의 코드입니다.
String apply(String s) {
return s.toUpperCase();
}
#2는 다음의 코드를 분리시켜서 적은것입니다.
Optional<String> os3 = os1.map(s -> s.replace(' ', '_')).map(s -> s.toLowerCase());
replace()메소드가 먼저 실행된 후 toLowerCase()메소드가 후에 실행됩니다.
3-2. orElse메소드
Optional 클래스에는 Optional 인스턴스에 저장된 내용물을 반환하는 get 메소드가 존재합니다. 그리고 이와 유사한 기능의 orElse 메소드도 존재합니다. orElse메소드도 인스턴스에 저장된 내용물을 반환합니다.
하지만, 저장된 내용물이 없을 때, 대신해서 반환할 대상을 지정할 수 있다는 점에서 get 메소드와 차이가 있습니다.
예시)
import java.util.Optional;
public class prac1 {
public static void main(String[] args) {
Optional<String> os1 = Optional.empty();
Optional<String> os2 = Optional.of("So Basic");
String s1 = os1.map(s -> s.toString())
.orElse("Empty");
String s2 = os2.map(s -> s.toString())
.orElse("Empty");
System.out.println(s1);
System.out.println(s2);
}
}
결과)
Empty
So Basic
empty메소드를 호출하면 저장하고 있는 내용물이 없는, 빈 Optional 인스턴스가 생성되어 반환됩니다.
empty메소드는 아래 코드와 같은 의미입니다.
Optional<String> os1 = Optional.empty();
Optional<String> os1 = Optional.ofNullable(null);
3-3. flatMap 메소드
예시)
import java.util.Optional;
public class prac1 {
public static void main(String[] args) {
Optional<String> os1 = Optional.of("Optional String");
Optional<String> os2 = os1.map(s -> s.toUpperCase());
System.out.println(os2.get());
Optional<String> os3 = os1.flatMap(s -> Optional.of(s.toLowerCase()));
System.out.println(os3.get());
}
}
결과)
OPTIONAL STRING
optional string
비슷한 기능을 수행하는 두 메소드 map과 flatMap의 차이는 map은 람다식이 반환하는 내용물을 Optional 인스턴스로 감싸는 일을 알아서 해주지만, flatMap은 알아서 해 주지 않기 때문에 이 과정을 람다식이 포함하고 있어야 합니다.
'[WEB] > [Java]' 카테고리의 다른 글
[Java] HashMap을 이용한 전체출력(iterator, entrySet(), .forEach()) (0) | 2023.02.14 |
---|---|
[Java] 자바 참조변수 (0) | 2022.10.06 |
[Java] 자바 static의 의미와 사용방법 (0) | 2022.09.29 |
[Java] 윈도우 자바 환경변수 설정방법 (0) | 2022.09.29 |
[Java] 자바 컬렉션 2 (0) | 2022.09.25 |