NULL
📌참조 변수가 아무 객체도 가리키지 않음을 나타내는 특수한 값입니다.
- 특징:
- 객체가 생성되지 않았거나, 특정 객체를 참조하지 않는 상태를 나타냅니다.
- 참조 타입(객체 타입)에만 사용할 수 있습니다. (예: String, Integer, 사용자 정의 클래스 등)
- 원시 타입(예: int, float)에는 사용할 수 없습니다.
- null 값의 변수로 메서드를 호출하려고 하면 **NullPointerException**이 발생합니다.
빈 공간 (Empty String)
- 의미: 길이가 0인 문자열로, 내용이 없는 문자열을 의미합니다.
- 표현: 빈 문자열은 "" (따옴표만 있는 문자열)로 표현됩니다.
- 특징:
- 문자열 객체가 존재하지만, 내용이 없습니다.
- 메모리에는 문자열 객체가 생성되며, 이는 null과 다릅니다.
- isEmpty() 메서드로 확인할 수 있습니다.
- NULL은 사용에 있어 주의가 필요한데 null이 반환되면 보통 nullPointerException이 발생하게 된다.
public class NullIsDanger {
public static void main(String[] args) {
SomeDBClient myDB = new SomeDBClient();
String userId = myDB.findUserIdByUsername("HelloWorldMan");
System.out.println("HelloWorldMan's user Id is : " + userId);
}
}
class SomeDBClient {
public String findUserIdByUsername(String username) {
// ... db에서 찾아오는 로직
String data = "DB Connection Result";
if (data != null) {
return data;
} else {
return null;
}
}
}
- 논리적으로도, 환경적으로도 null이 반환될 여지가 있음에도, null이 반환될 수 있음을 명시하지 않았습니다.
- 메인 함수 쪽에서, 사용할 때 null 체크를 하지 않아, 만약 null이 반환 된다면, nullPointerException이 발생하게 됩니다.
- 위 문제를 해결하는 방법은 크게 3가지인데
- 1. null이 반환될 여지를 명시하고, 그 메서드를 사용하는 사람이 조심하기
- 2. 결과값을 감싼 객체를 반환 = 결과값 + 성공 여부를 함께 반환 = 성공 못해도 값을 null로 반환하진 않는다.
- 3. java.util.Optiona 객체 사용
+ 감싼 객체 : 보통 반환은 1개의 데이터만 반환하지만 객체의 형태로 반환하면 여러 데이터를 담아 반환이 가능하다.
java.util.Optional
📌 Java 8에서 도입된 클래스입니다. 널(null) 값을 명시적으로 처리하기 위해 사용됩니다. Optional은 값이 있을 수도 있고 없을 수도 있다는 개념을 명확하게 표현하고, 널 포인터 예외(NullPointerException)를 방지하는 데 도움을 줍니다.
Optional 기본 정리
- Java8에서는 Optional<T> 클래스를 사용해 Null Pointer Exception을 방지할 수 있도록 도와줍니다.
- Optional<T>는 null이 올 수 있는 값을 감싸는 Wrapper 클래스입니다.
- Optional이 비어있더라도, 참조해도 Null Pointer Exception가 발생하지 않습니다.
- Optional은 객체를 생성하는데 오버헤드가 있을 수 있기 때문에 성능이 중요한 경우 과도한 사용을 피하는 것이 좋습니다.
- 모든 메서드에서 Optional을 사용해야 할 필요는 없으며, 주로 널 처리가 필요한 곳에서만 사용하는 것이 바람직합니다.
Optional 사용법
1. Optional 생성
- Optional.of(): 값이 반드시 존재할 때 사용합니다. 만약 null을 넣으려 하면 NullPointerException이 발생합니다.
- Optional.ofNullable(): 값이 null일 수도 있는 경우에 사용합니다.
- Optional.empty(): 빈 Optional 객체를 생성합니다. (값이 없음을 나타냄)
Optional<String> presentValue = Optional.of("Hello");
Optional<String> nullableValue = Optional.ofNullable(null); // null이 될 수 있음
Optional<String> emptyValue = Optional.empty(); // 빈 Optional
2. 값 존재 여부 확인
- isPresent(): 값이 존재하면 true, 그렇지 않으면 false를 반환합니다.
- ifPresent(): 값이 존재하면 해당 값을 처리하는 람다를 실행합니다.
Optional<String> value = Optional.of("Hello");
// 값이 존재하는지 확인
if (value.isPresent()) {
System.out.println(value.get()); // 값이 존재하면 출력
}
// 값이 존재하면 처리하는 방식
value.ifPresent(v -> System.out.println("Value: " + v));
3. 값을 안전하게 얻기
- get(): Optional에 값이 존재하면 해당 값을 반환합니다. 값이 없으면 NoSuchElementException을 발생시킵니다.
- orElse(): 값이 존재하면 해당 값을 반환하고, 없으면 기본값을 반환합니다.
- orElseGet(): 값이 존재하면 해당 값을 반환하고, 없으면 제공된 Supplier로 기본값을 생성하여 반환합니다.
- orElseThrow(): 값이 없으면 예외를 던집니다.
Optional<String> value = Optional.ofNullable("Hello");
// 값이 없으면 예외를 던짐
String result = value.orElseThrow(() -> new IllegalArgumentException("Value is missing"));
// 값이 없으면 기본값을 반환
String result2 = value.orElse("Default Value");
// 값이 없으면 Supplier로 기본값을 생성
String result3 = value.orElseGet(() -> "Generated Value");
4. 값 변환
- map(): Optional에 값이 있을 때, 해당 값에 연산을 적용하여 새로운 Optional을 반환합니다.
- flatMap(): map()과 유사하지만, 결과가 또 다른 Optional일 때 사용됩니다. (중첩된 Optional을 평평하게 만들어줍니다.)
Optional<String> value = Optional.of("Hello");
// 값이 있을 때 대문자로 변환
Optional<String> upperCaseValue = value.map(String::toUpperCase);
System.out.println(upperCaseValue.get()); // HELLO
// flatMap 예시
Optional<String> result = value.flatMap(v -> Optional.of(v + " World"));
System.out.println(result.get()); // Hello World
5. 필터링
- filter(): Optional에 값이 있을 때, 특정 조건을 만족하는 값만 남기고 필터링합니다.
Optional<String> value = Optional.of("Hello");
// 값이 "Hello"인 경우에만 값 반환
Optional<String> filteredValue = value.filter(v -> v.equals("Hello"));
filteredValue.ifPresent(System.out::println); // Hello
< 예시 >
public class OptionalExample {
public static void main(String[] args) {
Optional<String> name = Optional.ofNullable(getName());
// 값이 있으면 출력
name.ifPresent(System.out::println);
// 값이 없으면 기본값 반환
String defaultName = name.orElse("Default Name");
System.out.println("Name: " + defaultName);
// 값이 없으면 예외 던지기
String forcedName = name.orElseThrow(() -> new RuntimeException("Name is missing"));
}
public static String getName() {
// 값이 없으면 null을 반환
return null;
}
}
'Back-End (Web) > JAVA' 카테고리의 다른 글
[JAVA] 자바의 정렬 (0) | 2024.11.21 |
---|---|
[JAVA] 응용 정리 (1) | 2024.11.15 |
[JAVA] 쓰레드 & 람다 함수 & 스트림 (3) | 2024.11.13 |
[JAVA] Generic (3) | 2024.11.12 |
[JAVA] 오류 및 예외에 대한 이해 (1) | 2024.11.12 |