นากต้นฉบับถือค่าหลักผ่านประตู ขณะที่เครื่องสร้างค่าทดแทนด้านข้างยังดับอยู่

Java requireNonNullElseGet: สร้าง Default แบบ Lazy และห้าม Supplier คืน null

พี่โชว์Engineering

เมื่อ fallback ต้องอ่าน config หรือสร้าง object ราคาแพง Objects.requireNonNullElseGet จะเรียก supplier เฉพาะตอนค่าหลักเป็น null และรับประกันผลสุดท้ายไม่เป็น null ครับ

import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    static String choose(String configured, AtomicInteger calls) {
        return Objects.requireNonNullElseGet(configured, () -> {
            calls.incrementAndGet();
            return "safe-default";
        });
    }

    public static void main(String[] args) {
        AtomicInteger calls = new AtomicInteger();
        assert choose("custom", calls).equals("custom");
        assert calls.get() == 0 : calls.get();
        assert choose(null, calls).equals("safe-default");
        assert calls.get() == 1 : calls.get();
    }
}

ต่างจาก requireNonNullElse(primary, expensiveDefault()) ตรงที่แบบ Else ประเมิน argument ก่อนเข้า method จึงเสียต้นทุนแม้มีค่าหลักแล้ว ส่วน ElseGet เลื่อนงานไว้ใน supplier

ถ้า supplier เองเป็น null หรือคืน null method จะโยน NullPointerException ซึ่งเหมาะเมื่อ contract บอกว่าต้องมีค่าจริง แต่ไม่เหมาะกับ domain ที่ “ไม่มีค่า” เป็นสถานะปกติ กรณีนั้นใช้ Optional หรือ result type ที่สื่อสถานะตรงกว่า

Recap

  • ใช้ ElseGet เมื่อ fallback มีต้นทุนหรือ side effect
  • ทำ supplier ให้คืน non-null ตาม contract
  • เทสต์ว่า supplier ไม่ถูกเรียกเมื่อมีค่าหลัก
  • ใช้ type ที่สื่อ absence เมื่อ null เป็นสถานะธุรกิจ