ว่าด้วยเรื่อง “Optional” ใน Java
ใน Java 8 ได้มีคลาสใหม่ที่ชื่อว่า Optional ใน java.util
ซึ่งเป็นคลาสที่เอามาใช้แทนค่าที่ “มีอยู่” หรือ “ไม่มีอยู่” หรือค่า NULL นั้นเอง จุดประสงค์หลักของคลาสนี้คือใช้ค่า optional แทนที่จะอ้างอิง null เพื่อแก้ปัญหา NullPointerException
ตัวอย่างเช่น เราประกาศตัวแปรอ้างอิง (reference variable) แต่ไม่ได้กำหนดค่าอ้างอิงให้หรือค่าตั้งต้นเป็น null เมื่อเราใช้งาน method ของตัวแปรนี้จะได้ error เป็น java.lang.NullPointerException
public class Demo {
public static void main(String[] args) {
String hello = null;
hello.length();
}
}Output:
Exception in thread "main" java.lang.NullPointerException
ดังนั้นคลาส Optional จะมาช่วยแก้ปัญหานี้ โดยที่ Optional จะห่อหุ่ม (wrapper) object ที่เราต้องการและสามารถดำเนินการต่างๆ กับ object นั้นได้
Creating Optional object
เราสามารถสร้าง Optional object ได้กลายวิธี เริ่มด้วยการสร้าง Optional ว่างเปล่าด้วย method empty()
จะได้ Optional.empty
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.empty();
System.out.println(opt);
}
}Output:
Optional.empty
สามารถสร้าง Optional object ที่มีค่าด้วย method of(T value)
ซึ่งจะได้ Optional object ของ value
นั้นๆ
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.of("Hello");
System.out.println(opt);
}
}output:
Optional[Hello]
แต่ถ้าเราไม่แน่ใจว่าค่าที่เราจะสร้างด้วย Optional นั้นเป็นค่าว่างเปล่าหรือ null
หรือไม่ สามารถใช้ method ofNullable(T value)
public class Demo {
public static void main(String[] args) {
Optional<String> opt;
opt = Optional.ofNullable(null);
System.out.println(opt);
opt = Optional.ofNullable("Hello");
System.out.println(opt);
}
}output:
Optional.empty
Optional[Hello]
จะเห็นได้ว่าเราสามารถใช้ ofNullable
สร้าง Optional object จากค่าที่เป็น null
หรือ ค่าที่มีค่า ถ้าค่าเป็น null
จะได้ Optional.empty แต่ถ้าค่ามีค่าจะได้ Optional ของค่านั้นๆ
Checking Value
เมื่อสร้าง Optional object แล้วสามารถตรวจสอบการมีอยู่ของค่าที่อยู่ใน Optional object ได้ด้วย method isPresent()
public class Demo {
public static void main(String[] args) {
Optional<String> opt;
opt = Optional.ofNullable(null);
System.out.println(opt.isPresent());
opt = Optional.ofNullable("Hello");
System.out.println(opt.isPresent());
}
}output:
false
true
หรือในทางกลับกันใช้ methodisEmpty()
(ใน Java 11 เท่านั้น)
public class Demo {
public static void main(String[] args) {
Optional<String> opt;
opt = Optional.ofNullable(null);
System.out.println(opt.isEmpty());
opt = Optional.ofNullable("Hello");
System.out.println(opt.isEmpty());
}
}output:
true
false
Conditional Action
เราสามารถตรวจสอบเงื่อนไขและดำเนินการบางอย่างกับ Optional object ได้ด้วย method ifPresent()
โดยที่จะดำเนินการก็ต่อเมื่อ Optional นั้นมีค่าแต่ถ้าไม่มีค่าก็จะไม่ทำอะไร
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable("Hello");
opt.ifPresent(c -> System.out.println(c.length()));
}
}output:
5
จากตัวอย่างจะเห็นได้ว่าจะดำเนินการ print
ขนาดของ String ออกมาถ้า Optional opt
มีค่า
ใน Java 9 ได้เพิ่ม method ifPersentOrElse()
เพื่อเพิ่มเติมจัดการเงื่อนไขถ้า Optional ไม่มีค่า ด้วย Runnable
action
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.empty();
opt.ifPresentOrElse(c -> System.out.println(c.length()),
() -> System.out.println("Other"));
}
}output:
Other
Return Value
เมื่อห่อหุ่มค่าต่างๆ ด้วย Optional แล้ว จะเอาค่านั้นออกมาได้ด้วย method get()
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable("Hello");
System.out.println(opt.get());
}
}output:
Hello
Default Value
ถ้าเราใช้ method get()
เพื่อเอาค่าของ Optional object ออกมา แต่ถ้าค่านั้นเป็น null
ก็จะไม่ต่างอะไรจากไม่ใช้ Optional แต่เราสามารถกำหนดค่าเริ่มต้นให้ถ้าเจอค่าเป็น null
ด้วย method orElse(T other)
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable(null);
System.out.println(opt.orElse("Hello"));
}
}output:
Hello
หรือเราสามรถดำเนินการอย่างอื่นนอกเหนือจาก return ค่ากลับเฉยๆ ด้วย method orElseGet()
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable(null);
System.out.println(opt.orElseGet(() -> "Hello"));
}
}output:
Hello
ใน Java 9 ได้เพิ่ม method or()
ขึ้นมาเพื่อดำเนินการและ return ค่าเป็น Optional สำหรับ Optoinal ที่มีค่าจะ return เป็นค่าเดิม
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable("Hello");
Optional<String> defaultOpt = Optional.of("Default");
System.out.println(opt.or(() -> defaultOpt));
}
}output:
Optional[Hello]
สำหรับ Optional ที่ไม่มีค่า จะ return เป็นค่าใน or()
statement
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.empty();
Optional<String> defaultOpt = Optional.of("Default");
System.out.println(opt.or(() -> defaultOpt));
}
}output:
Optional[Default]
Exception
ถ้าเราไม่ต้องการจะ return หรือว่าดำเนินการอะไรหลังจากตรวจสอบว่าค่าเป็น null
สามารถ throw Exception
ออกมาได้เช่นกัน
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable(null);
opt.orElseThrow(IllegalArgumentException::new);
}
}output:
java.lang.IllegalArgumentException
Conditional Return
เราสามารถตรวจสอบค่าที่ return ของ Optional object ได้ด้วย method filter()
โดยใช้เพื่อแยกค่าที่เราต้องการและเอาค่าที่เราไม่ต้องการออกไปด้วยเงื่อนไข
public class Demo {
public static void main(String[] args) {
boolean present;
Optional<String> opt = Optional.ofNullable("Hello");
present = opt.filter(c -> c == "Hello").isPresent();
System.out.println(present);
present = opt.filter(c -> c == "Other").isPresent();
System.out.println(present);
}
}output:
true
false
Transforming Value
เราสามารถเปลี่ยนแปลงค่าใน Optional object ที่มีค่าได้ด้วย method map()
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable("Hello");
System.out.println(opt.map(String::toUpperCase).get());
}
}output:
HELLO
แต่ก็มี method flatMap()
ที่คล้าย map()
แต่ใช้ดำเนินการกับค่าที่เป็น Optional
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable("Hello");
Optional<Optional<String>> optOfOpt = Optional.of(opt);
System.out.println(optOfOpt.flatMap(
c -> c.map(String::toUpperCase)).get());
}
}output:
HELLO
Stream
ใน Java 9 สามารถแปลง Optional object ไปเป็น Stream ได้และสามาถดำเนินการในแบบ Stream ได้เลย
public class Demo {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable("Hello");
System.out.println(opt.stream().map(String::toUpperCase)
.collect(Collectors.toList()));
}
}output:
[HELLO]