Java 에서 Character 객체가 Null 인지 확인하는 방법

JavaBeginner
지금 연습하기

소개

이 랩에서는 Java 의 Character 래퍼 클래스를 사용할 때 잠재적인 null 값을 처리하는 방법을 살펴봅니다. 기본형 char 타입과 달리, Character 객체는 null이 될 수 있으며, 이를 처리하지 못하면 NullPointerException 오류가 발생할 수 있습니다. Character 객체가 null 인지 확인하고, null 검사를 다른 문자 속성 검사와 결합하며, 안전한 null 처리를 위해 Optional 클래스를 활용하는 방법을 배우게 됩니다.

실용적인 예제를 통해 null Character 객체를 효과적으로 관리하고, 일반적인 런타임 오류를 방지하며, 애플리케이션의 신뢰성을 향상시키는 견고한 Java 코드를 작성하는 실질적인 경험을 얻을 수 있습니다.

Character 래퍼의 Null 확인

이 단계에서는 Java 의 Character 래퍼 클래스를 사용할 때 잠재적인 null 값을 처리하는 방법을 살펴봅니다. 기본형 char 타입은 null이 될 수 없지만, 객체인 Character 래퍼 클래스는 null이 될 수 있습니다. null 값을 처리하는 것은 Java 에서 흔히 발생하는 NullPointerException 오류를 방지하고 프로그램이 충돌하는 것을 막는 데 매우 중요합니다.

먼저 nullCharacter 객체에서 메서드를 사용하려고 할 때 NullPointerException이 어떻게 발생하는지 보여주는 간단한 Java 프로그램을 만들어 보겠습니다.

  1. WebIDE 편집기에서 HelloJava.java 파일을 엽니다 (아직 열려 있지 않은 경우).

  2. 파일의 전체 내용을 다음 코드로 바꿉니다.

    public class HelloJava {
        public static void main(String[] args) {
            Character myChar = null;
    
            // This line will cause a NullPointerException if myChar is null
            // System.out.println("Is myChar a letter? " + Character.isLetter(myChar));
        }
    }

    이 코드에서:

    • myChar라는 Character 변수를 선언하고 명시적으로 null로 설정합니다.
    • 주석 처리된 줄 System.out.println("Is myChar a letter? " + Character.isLetter(myChar));null 인수를 사용하여 정적 메서드 Character.isLetter()를 호출하려고 시도합니다. Character.isLetter()는 정적 메서드이지만, null Character 객체를 전달하면 메서드가 내부적으로 Character 객체를 기본형 char 값으로 언박싱하려고 시도하기 때문에 NullPointerException이 발생합니다. 이는 null의 경우 불가능합니다.
  3. 파일을 저장합니다 (Ctrl+S 또는 Cmd+S).

  4. 이제 프로그램을 컴파일해 보겠습니다. WebIDE 하단의 터미널을 열고 다음을 실행합니다.

    javac HelloJava.java

    컴파일이 성공하면 출력이 표시되지 않습니다.

  5. 이제 프로그램을 실행해 보겠습니다. 터미널에서 다음을 실행합니다.

    java HelloJava

    오류를 발생시킬 줄이 주석 처리되어 있으므로 프로그램은 출력이나 오류 없이 실행됩니다. 이는 단순히 Characternull로 선언하는 것만으로는 즉각적인 문제가 발생하지 않음을 보여줍니다. 문제는 해당 객체에 대한 작업을 수행하려고 할 때 발생합니다.

다음 단계에서는 문제가 있는 줄의 주석을 해제하고 NullPointerException을 관찰합니다.

Null 및 문자 확인 결합

이전 단계에서 Character 객체를 사용할 때 NullPointerException이 어떻게 발생할 수 있는지 확인했습니다. 이제 오류를 발생시키는 줄의 주석을 해제하고 예외가 발생하는 것을 살펴보겠습니다. 그런 다음, null 검사를 문자 검사와 결합하여 이를 방지하는 일반적인 방법을 배우겠습니다.

  1. WebIDE 편집기에서 HelloJava.java 파일을 엽니다.

  2. Character.isLetter()를 호출하는 줄의 주석을 해제합니다. 이제 코드는 다음과 같아야 합니다.

    public class HelloJava {
        public static void main(String[] args) {
            Character myChar = null;
    
            // This line will cause a NullPointerException if myChar is null
            System.out.println("Is myChar a letter? " + Character.isLetter(myChar));
        }
    }
  3. 파일을 저장합니다 (Ctrl+S 또는 Cmd+S).

  4. 터미널에서 수정된 프로그램을 컴파일합니다.

    javac HelloJava.java

    다시, 컴파일이 성공하면 출력이 표시되지 않아야 합니다.

  5. 이제 프로그램을 실행합니다.

    java HelloJava

    다음과 유사한 출력이 표시되어 NullPointerException을 나타냅니다.

    Exception in thread "main" java.lang.NullPointerException
        at java.base/java.lang.Character.isLetter(Character.java:xxxx)
        at HelloJava.main(HelloJava.java:x)

    이 오류는 myCharnull이고 Character.isLetter() 메서드가 null 객체에서 작동할 수 없기 때문에 발생합니다.

  6. NullPointerException을 방지하기 위해 Character.isLetter()를 호출하기 전에 myCharnull인지 확인하는 검사를 추가할 수 있습니다. 이를 위해 if 문을 사용할 수 있습니다. HelloJava.java 파일을 수정하여 이 검사를 포함합니다.

    public class HelloJava {
        public static void main(String[] args) {
            Character myChar = null;
    
            if (myChar != null && Character.isLetter(myChar)) {
                System.out.println("myChar is a letter.");
            } else {
                System.out.println("myChar is not a letter or is null.");
            }
        }
    }

    이 업데이트된 코드에서:

    • && (논리 AND 연산자) 로 결합된 두 개의 조건이 있는 if 문을 사용합니다.
    • 첫 번째 조건인 myChar != nullmyCharnull아닌지 확인합니다.
    • 두 번째 조건인 Character.isLetter(myChar)myChar가 문자인지 확인합니다.
    • && 연산자는 "단락 평가"를 수행합니다. 즉, 첫 번째 조건 (myChar != null) 이 false 이면 두 번째 조건 (Character.isLetter(myChar)) 은 평가되지 않습니다. 이렇게 하면 NullPointerException을 방지할 수 있습니다. myChar가 null 이 아닌 경우에만 Character.isLetter()를 호출하려고 시도하기 때문입니다.
  7. 파일을 저장합니다.

  8. 프로그램을 다시 컴파일합니다.

    javac HelloJava.java
  9. 프로그램을 실행합니다.

    java HelloJava

    이번에는 프로그램이 오류 없이 실행되고 다음을 출력해야 합니다.

    myChar is not a letter or is null.

    이는 myCharnull이므로 if 문의 첫 번째 조건 (myChar != null) 이 false 이고 else 블록이 실행되기 때문입니다.

객체의 메서드나 속성에 액세스하기 전에 null을 확인하는 이 접근 방식은 NullPointerException을 방지하기 위한 Java 의 기본적인 기술입니다.

Null 안전성을 위한 Optional 사용

이전 단계에서는 객체를 사용하기 전에 명시적으로 객체가 null인지 확인하여 NullPointerException을 방지하는 방법을 배웠습니다. 효과적이긴 하지만, 이 방법은 때때로 null 검사로 코드가 복잡해질 수 있습니다. Java 8 은 잠재적으로 null 값을 보다 기능적이고 표현적인 방식으로 처리하기 위해 Optional 클래스를 도입했습니다.

Optional은 null 이 아닌 값을 포함할 수도 있고 포함하지 않을 수도 있는 컨테이너 객체입니다. 값이 있으면 isPresent()true를 반환하고 get()은 값을 반환합니다. 값이 없으면 객체는 비어 있는 것으로 간주되고 isPresent()false를 반환합니다. 빈 Optional에서 get()을 호출하면 NoSuchElementException이 발생합니다.

null Character의 가능성을 처리하기 위해 예제를 Optional<Character>를 사용하도록 리팩터링해 보겠습니다.

  1. WebIDE 편집기에서 HelloJava.java 파일을 엽니다.

  2. 파일의 전체 내용을 다음 코드로 바꿉니다.

    import java.util.Optional;
    
    public class HelloJava {
        public static void main(String[] args) {
            Character myChar = null; // Still potentially null
    
            // Create an Optional from the potentially null Character
            Optional<Character> optionalChar = Optional.ofNullable(myChar);
    
            // Use Optional methods to check and process the value
            if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) {
                 System.out.println("myChar is a letter.");
            } else {
                 System.out.println("myChar is not a letter or is null.");
            }
    
            // Another way using Optional's functional methods (more advanced)
            // optionalChar.filter(Character::isLetter)
            //             .ifPresentOrElse(
            //                 c -> System.out.println("myChar is a letter (using Optional methods)."),
            //                 () -> System.out.println("myChar is not a letter or is null (using Optional methods).")
            //             );
        }
    }

    이 코드에서:

    • Optional 클래스를 가져옵니다.
    • 여전히 myChar를 잠재적으로 null로 선언합니다.
    • Optional<Character> optionalChar = Optional.ofNullable(myChar);Optional 객체를 생성합니다. Optional.ofNullable()은 값이 null 일 수 있는 경우에 사용됩니다. myChar가 null 이면 optionalChar는 빈 Optional이 됩니다. myChar에 값이 있으면 optionalChar는 해당 값을 포함합니다.
    • 그런 다음 optionalChar.isPresent()를 사용하여 Optional에 값이 있는지 확인한 다음 optionalChar.get()으로 값을 가져와 Character.isLetter()에 전달합니다. 이는 이전 null 검사와 유사하지만 Optional API 를 사용합니다.
    • 주석 처리된 섹션은 filterifPresentOrElse와 같은 함수형 메서드를 사용하여 Optional을 사용하는 보다 고급적인 방법을 보여줍니다. 이는 특정 시나리오에서 코드를 더 간결하게 만들 수 있습니다. 이 소개 랩에서는 이 고급 사용법에 초점을 맞추지 않지만, 이를 알고 있는 것이 좋습니다.
  3. 파일을 저장합니다.

  4. 프로그램을 컴파일합니다.

    javac HelloJava.java
  5. 프로그램을 실행합니다.

    java HelloJava

    출력은 이전 단계와 동일해야 합니다.

    myChar is not a letter or is null.

    이는 Optional.ofNullable()isPresent()를 사용하여 null 케이스를 올바르게 처리함을 확인합니다.

이제 myChar를 null 이 아닌 문자로 변경하여 프로그램이 어떻게 동작하는지 살펴보겠습니다.

  1. HelloJava.java 파일을 수정하여 myChar를 문자, 예를 들어 'A'로 설정합니다.

    import java.util.Optional;
    
    public class HelloJava {
        public static void main(String[] args) {
            Character myChar = 'A'; // Now myChar has a value
    
            // Create an Optional from the potentially null Character
            Optional<Character> optionalChar = Optional.ofNullable(myChar);
    
            // Use Optional methods to check and process the value
            if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) {
                 System.out.println("myChar is a letter.");
            } else {
                 System.out.println("myChar is not a letter or is null.");
            }
        }
    }
  2. 파일을 저장합니다.

  3. 프로그램을 컴파일합니다.

    javac HelloJava.java
  4. 프로그램을 실행합니다.

    java HelloJava

    이번에는 출력은 다음과 같아야 합니다.

    myChar is a letter.

    이는 myChar에 값이 있을 때 optionalChar.isPresent()true를 반환하고 Character.isLetter() 검사가 올바르게 수행됨을 보여줍니다.

Optional을 사용하면 코드를 더 읽기 쉽게 만들고 값이 없을 수 있음을 명시적으로 나타내어 예상치 못한 NullPointerException의 발생 가능성을 줄일 수 있습니다.

요약

이 랩에서는 Java 에서 Character 래퍼 클래스를 사용할 때 잠재적인 null 값을 처리하는 방법을 배웠습니다. Character.isLetter()와 같은 정적 메서드를 사용하더라도 null Character 객체에서 메서드를 사용하려고 할 때 NullPointerException이 어떻게 발생할 수 있는지 시연하는 것으로 시작했습니다. 이는 프로그램 충돌을 방지하기 위해 Character 객체에 대한 작업을 수행하기 전에 명시적으로 null을 확인하는 것의 중요성을 강조했습니다.