코딩 공부/Java

[Java] Chpater 3 - 02) Optional - null 을 다루는 법

sintory-04 2025. 2. 26. 19:35

    1️⃣ Optional

    • Optional 객체는 null 을 안전하게 다루게 해주는 객체입니다.
    • null은 프로그래밍에서 값이 없음 또는 참조하지 않음 을 나타내는 키워드
    • null 을 직접 다루는 대신 Optional 을 사용하면 NullPointerException 을 방지할 수 있습니다.

    Optional 이 필요한 이유

    • camp.getStudent()null 을 반환할 수 있는 메서드입니다.
    • 학생이 없는 경우 null을 반환하면 NPE(NullPointerException)가 발생합니다.
    • null인 객체에서 student.getName()을 호출하는 것은 존재하지 않는 객체의 메서드를 실행하려는 것입니다.

    NullPointerException 을 방지해야 하는 이유

    • NPE 예외는 런타임 예외이고 컴파일러가 잡아주지 못합니다.
    • 예외가 발생했을 때 처리해 주지 않으면 프로그램이 종료됩니다.
    public class Student {
    
        // 속성
        private String name;
    
        // 생성자
    
        // 기능
        public String getName() {
            return this.name;
        }
    }
    public class Camp {
    
        // 속성
        private Student student;
    
        // 생성자
    
        // 기능: ⚠️ null 을 반환할 수 있는 메서드
        public Student getStudent() {
            return student;
        }
    
        public void setStudent(Student student) {
                this.student = student;    
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
    
            Camp camp = new Camp();
            Student student = camp.getStudent(); // ⚠️ student 에는 null 이 담김
            // ⚠️ 아래 코드에서 NPE 발생! 컴파일러가 잡아주지 않음
            String studentName = student.getName(); // 🔥 NPE 발생 -> 프로그램 종료
            System.out.println("studentName = " + studentName);
        }
    }

    ✅ NULL 을 직접 처리의 한계

    • if문을 활용해서 null 처리를 할 수 있지만 모든 코드에서 null 이 발생할 가능성을 미리 예측하고 처리하는 것은 현실적으로 어렵습니다.

    2️⃣ Optional 활용하기

    • Optional 객체는 값이 있을 수도 있고 없을 수도 있는 컨테이너라고 생각하시면 됩니다.
    • Optional 객체를 메서드 반환 자료형에 선언해서 해당 메서드가 null 이 반환될 가능성을 명확하게 전달할 수 있습니다.
    • Optional.ofNullable() 을 사용하여 null 이 반환될 수 있는 객체를 감쌉니다.
    • 활용할 때는 isPresent() 와 같은 Optional API 를 통해 안전하게 null 처리를 할 수 있습니다.

    isPresent() 활용 방법

    • Optional 내부의 값이 존재할 경우에 true 반환합니다.
    • 내부 값이 null 일 경우 false 를 반환합니다.
    import java.util.Optional;
    
    public class Camp {
    
        // 속성
        private Student student;
    
        // 생성자
    
        // 기능
        // ✅ null 이 반환될 수 있음을 명확하게 표시
        public Optional<Student> getStudent() {
            return Optional.ofNullable(student);
        }
    
        public void setStudent(Student student) {
                this.student = student;    
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
    
            Camp camp = new Camp();
    
            // isPresent() 활용시 true 를 반환하고 싶을때 활용
            // Student newStudent = new Student();
            // camp.setStudent(newStudent);
    
            //  Optional 객체 반환받음
            Optional<Student> studentOptional = camp.getStudent();
    
            // Optional 객체의 기능 활용
            boolean flag = studentOptional.isPresent(); // false 반환
            if (flag) {
                // 존재할 경우
                Student student = studentOptional.get(); // ✅ 안전하게 Student 객체 가져오기
                String studentName = student.getName();
                System.out.println("studentName = " + studentName);
    
            } else {
                // null 일 경우
                System.out.println("학생이 없습니다.");
            }
        }
    }

    orElseGet() 활용 방법

    • orElseGet()은 값이 없을 때만 기본값을 제공하는 로직을 실행하는 메서드입니다.
    • orElseGet()을 제대로 활용하려면 람다 표현식을 이해해야 합니다.
    • 하지만 이 부분은 이후 수업에서 다룰 예정이므로 지금은 메서드를 매개변수로 전달한다 정도로 이해하셔도 충분합니다.
    import java.util.Optional;
    
    public class Camp {
    
        // 속성
        private Student student;
    
        // 생성자
    
        // 기능
        // ✅ null 이 반환될 수 있음을 명확하게 표시
        public Optional<Student> getStudent() {
            return Optional.ofNullable(student);
        }
    }
    import java.util.Optional;
    
    public class Main {
        public static void main(String[] args) {
            Camp camp = new Camp();
    
            // ✅ Optional 객체의 기능 활용 (orElseGet 사용)
            Student student = camp.getStudent()
                                  .orElseGet(() -> new Student("미등록 학생"));
    
            System.out.println("studentName = " + student.getName());
        }
    }