FS_hansol
[JAVA] Optional, Collection, Generic 본문
Optional - null을 다루는 법
Optional이란?
- 값이 있을 수도 있고, 없을 수도 있는 상황을 안전하게 처리하기 위한 컨테이너 객체
Optional<String> name = Optional.of("한솔");
Optional<String> empty = Optional.empty(); // 값이 없음
- 왜 필요한가?
String name = null;
System.out.println(name.length()); // NullPointerException!
//이걸 Optional로 감싸면 `null`인지 먼저 체크하고 안전하게 처리 가능
방법 | 설명 | 예시 |
Optional.of(value) | null이 아닌 값만 허용 | Optional.of("hello") |
Optional.ofNullable(value) | null 가능 | Optional.ofNullable(maybeNull) |
Optional.empty() | 빈 Optional | Optional.empty() |
Optional<String> name = Optional.of("한솔");
Optional<String> maybeName = Optional.ofNullable(null);
Optional<String> none = Optional.empty();
Optional 값 꺼내기
문법 | 설명 |
get() | 값 꺼내기 (null이면 예외) 위험 |
isPresent() | 값 있으면 true |
ifPresent(consumer) | 값이 있으면 람다 실행 |
orElse(default) | 값 없으면 기본값 반환 |
orElseGet(() -> default) | orElse와 같지만 지연 실행 |
orElseThrow() | 값 없으면 예외 던짐 |
Optional<String> name = Optional.of("한솔");
// 1. get() → 위험 (null이면 예외 발생)
System.out.println(name.get()); // "한솔"
// 2. isPresent() → 값 있으면 true
if (name.isPresent()) {
System.out.println(name.get());
}
// 3. orElse() → 값 없으면 기본값
String result = name.orElse("기본값");
// 4. ifPresent() → 값 있으면 실행
name.ifPresent(n -> System.out.println("이름: " + n));
외우는 핵심 흐름
- Optional.of() : null x
- Optional.ofNullable() : null
- orElse(), ifPresent() : 값 없을 때 처리
- get()은 웬만하면 x
- 실습문제
// TODO_실습예제1: 기본 Optional 생성과 기본값 반환
// null이 될 수도 있는 사용자 이름
String rawName = null;
// 아래 빈칸을 채워서, 이름이 null이면 "게스트"를 출력하게 만들어라.
Optional<String> name = Optional._______(rawName);
System.out.println(name._______("게스트"));
//정답
Optional<String> name = Optional.ofNullable(rawName);
System.out.println(name.orElse("게스트"));
// `null`일 수도 있으니까 → `ofNullable`
// 값이 없으면 "게스트"를 대신 써야 하니까 → `orElse("게스트")`
값이 있는지 없는지 모르지만, System.out.println에 넣었는데 왜 orElse를 쓰는 건가? 그냥 get()으로 가져오면 안 되나??
- 이유: rawName = null일 수도 있기 때문
- Optional.ofNullable(null) → 내부적으로 비어 있는 Optional이 만들어짐
- 이 상태에서 name.get() 하면 → NoSuchElementException 발생 (NullPointerException 아님!)
Optional<String> name = Optional.ofNullable(rawName);
System.out.println(name.orElse("게스트")); // 안전
System.out.println(name.get()); // 위험
// orElse는 "비어 있으면 이걸 줘!" 라는 의미
// 내부에 값이 없을 경우
name.orElse("게스트"); // → "게스트" 리턴됨
//TODO_실습예제2: 값이 있을 때만 출력
Optional<String> city = Optional.of("서울");
// 값이 있을 때만 "사는 도시: 서울"이 출력되도록
// ifPresent()를 활용해서 작성해보자
// (힌트: 람다식 사용)
// 정답
city.ifPresent(c -> System.out.println("사는 도시: " + c));
//- `ifPresent(람다)`는 값이 있을 때만 안에 있는 코드를 실행
// 여기선 `"서울"`이 있으니까 실행됨!
왜 굳이 ifPresent()를 써서 람다식으로 출력?
- Optional.of("서울")은 값이 들어 있는 상태
Optional<String> city = Optional.of("서울");
// `city`는 `"서울"`이라는 값을 가지고 있다.
// 하지만 Optional문법은 무조건 안전하게 쓰는 걸 권장함.
//TODO_실습예제3: 예외 발생
Optional<String> email = Optional.ofNullable(null);
// 값이 없으면 IllegalArgumentException을 던지게 해라
// orElseThrow 사용
String result = email._____________________________;
//정답
String result = email.orElseThrow(() -> new IllegalArgumentException("이메일 없음"));
// `orElseThrow`: 값이 없으면 예외를 던짐
// 익명함수 `() -> new 예외()` 형태 기억해두기
컬렉션
컬렉션(Collection)이란?
- 데이터를 모아서 저장하는 자료구조(객체 모음)
분류 | 인터페이스 | 대표 클래스 | 특징 |
List | List | ArrayList, LinkedList | 순서O, 중복O |
Set | Set | HashSet, TreeSet | 순서X, 중복X |
Map | Map | HashMap, TreeMap | 키-값 쌍 저장 |
- ArrayList (순서 O, 중복 O)
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
names.add("한솔");
names.add("윈터");
names.add("한솔"); // 중복 가능
System.out.println(names); // [한솔, 윈터, 한솔]
- HashSet(순서 X, 중복 X)
import java.util.HashSet;
HashSet<String> fruits = new HashSet<>();
fruits.add("사과");
fruits.add("바나나");
fruits.add("사과"); // 중복 안 됨
System.out.println(fruits); // [바나나, 사과] ← 순서 보장 안 됨
- HashMap (key-value 저장)
import java.util.HashMap;
HashMap<String, String> capitals = new HashMap<>();
capitals.put("한국", "서울");
capitals.put("일본", "도쿄");
System.out.println(capitals.get("한국")); // 서울
상황 | 추천 컬렉션 |
순서 중요 + 중복 허용 | List (ArrayList) |
중복 제거 + 순서 상관없음 | Set (HashSet) |
키-값 형태 저장 | Map (HashMap) |
- 실습예제
// TODO_실습 문제 1: 리스트 (ArrayList) – 순서 O, 중복 O
//학생 이름을 저장하는 리스트를 만들고, 이름 3개를 추가하라.
// 그런 다음 모든 학생 이름을 출력하라.
// TODO: ArrayList 생성 후 이름 추가하고 출력
// 결과 예시:
// [지민, 정국, 한솔]
ArrayList<String> names=new ArrayList<>();
names.add("지민");
names.add("정국");
names.add("한솔");
System.out.println(names);
//TODO_실습 문제 2: 집합 (HashSet) – 중복 제거
// 다음 과일들을 집합에 추가하고 출력하라.
// "사과", "바나나", "사과", "오렌지"
HashSet<String> fruit=new HashSet<>();
fruit.add("사과");
fruit.add("바나나");
fruit.add("사과");
fruit.add("오렌지");
System.out.println(fruit);
// TODO_실습 문제 3: 맵 (HashMap) – key-value 저장
// 나라 이름을 key로, 수도를 value로 저장하라.
// 한국-서울, 일본-도쿄, 미국-워싱턴
// 그리고 일본의 수도를 출력하라.
HashMap<String, String> contry=new HashMap<>();
contry.put("한국","서울");
contry.put("일본","도쿄");
contry.put("미국","워싱턴");
System.out.println(contry.get("일본"));
제네릭(Generic)
제네릭(Generic)이란?
- 데이터 타입을 직접 지정하지 않고, 나중에 사용할 때 타입을 결정하는 문법
ArrayList<String> names = new ArrayList<>();
//`<String>` 이게 바로 제네릭
// `ArrayList`는 어떤 타입이든 저장 가능하지만
//`<String>`을 붙이면 문자열만 저장 가능하게 강제함
- 사용자 정의 제네릭 클래스도 가능
class Box<T> {
private T item;
public void set(T item) { this.item = item; }
public T get() { return item; }
}
- 사용할 때 타입 결정
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
Box<Integer> intBox = new Box<>();
intBox.set(100);
문법 | 의미 |
<T> | 타입 파라미터 (Type) |
List<String> | 문자열만 저장 |
Box<Integer> | 정수만 저장 |
- 실습문제
// TODO_실습 문제 1: ArrayList 제네릭
// 문자열만 담을 수 있는 `ArrayList`를 만들어
// `"Java"`, `"Python"`을 추가하고, 모두 출력하라.
//정답
ArrayList<String> names= new ArrayList<>();
names.add("Java");
names.add("Python");
System.out.println(names);
// 결과 예시:
// [Java, Python]
// TODO_실습 문제 2: 사용자 정의 Box<T> 클래스
// 다음 클래스에서 `T`를 제네릭 타입으로 채워서,
// 문자열을 저장하고 꺼내 출력해보라.
class Box<T> {
private T item;
public void set(T item) {
this.item = item;
}
public T get() {
return item;
}
}
// TODO: Box<String> 타입 객체 만들어서 "한솔" 저장하고 꺼내 출력하기
// 정답
Box<String> box=new Box<>();
box.set("한솔");
System.out.println(box.get());
//TODO_실습 문제 3: 제네릭 없이 쓸 때 문제점 찾기
// 다음 코드는 제네릭을 쓰지 않았다. 오류를 설명하고, 제네릭을 써서 수정하라.
ArrayList list = new ArrayList();
list.add("hello");
list.add(123); // ❓ 왜 문제일까? => 문자열만 가능
String text = (String) list.get(1); // ❓ 여기서 어떤 문제가 발생할까?=>형변환 없이 바로 사용 가능
'Spring_부캠' 카테고리의 다른 글
[Java] SSR & Refactoring (2) | 2025.07.15 |
---|---|
[JAVA] MORE.1 (2) | 2025.07.08 |
[JAVA] Level.1_Calculator (0) | 2025.07.07 |
[JAVA]Optional과 예외 처리 핵심 정리&게터와 세터 (0) | 2025.06.25 |
[JAVA]클래스, 상속, 캡슐화, 다형성 등 (0) | 2025.06.23 |