Java Optional: หลีกเลี่ยง NullPointerException อย่างถูกต้อง
#java13 เม.ย. 2569
NullPointerException ปัญหาคลาสสิก
NullPointerException (NPE) เป็น exception ที่พบบ่อยที่สุดใน Java Optional ช่วยให้จัดการ null values ได้อย่างปลอดภัย
สร้าง Optional
import java.util.Optional;
// Optional ที่มีค่า
Optional<String> name = Optional.of("สมชาย");
// Optional ที่อาจเป็น null
Optional<String> nullable = Optional.ofNullable(null);
// Optional ว่าง
Optional<String> empty = Optional.empty();
ตรวจสอบและดึงค่า
Optional<String> opt = Optional.of("Hello");
// isPresent / isEmpty
if (opt.isPresent()) {
System.out.println(opt.get());
}
// ifPresent
opt.ifPresent(value -> System.out.println(value));
// orElse - ค่า default
String result = opt.orElse("default");
// orElseGet - lazy evaluation
String result2 = opt.orElseGet(() -> computeDefault());
// orElseThrow
String result3 = opt.orElseThrow(() -> new RuntimeException("ไม่พบข้อมูล"));
Transformation
Optional<String> name = Optional.of(" สมชาย ");
// map
Optional<String> trimmed = name.map(String::trim);
Optional<Integer> length = name.map(String::length);
// flatMap
Optional<User> user = findUser(1);
Optional<String> email = user.flatMap(u -> Optional.ofNullable(u.getEmail()));
// filter
Optional<String> longName = name
.map(String::trim)
.filter(n -> n.length() > 3);
ตัวอย่างจริง
// ก่อน Optional
public String getUserCity(int userId) {
User user = userRepository.findById(userId);
if (user != null) {
Address address = user.getAddress();
if (address != null) {
return address.getCity();
}
}
return "ไม่ทราบ";
}
// หลัง Optional
public String getUserCity(int userId) {
return userRepository.findById(userId)
.map(User::getAddress)
.map(Address::getCity)
.orElse("ไม่ทราบ");
}
Repository Pattern
public interface UserRepository {
Optional<User> findById(int id);
Optional<User> findByEmail(String email);
}
// Service
public User getUser(int id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("ไม่พบ user id: " + id));
}
สิ่งที่ไม่ควรทำ
// ❌ ไม่ควรใช้ Optional เป็น field
private Optional<String> name; // ไม่ดี
// ❌ ไม่ควรใช้ Optional เป็น parameter
void process(Optional<String> name) {} // ไม่ดี
// ✅ ใช้ Optional เป็น return type
Optional<User> findUser(int id) { ... } // ดี
สรุป
Optional ช่วยให้โค้ดชัดเจนขึ้นว่าค่าอาจเป็น null ได้ ใช้ map, flatMap, orElse แทนการ check null ด้วย if ทำให้โค้ดกระชับและปลอดภัยขึ้นครับ