Skip to content

Commit 4c6f559

Browse files
authored
Merge pull request #321 from hwanghe159/item55
[#55][2κΈ°] μ˜΅μ…”λ„ λ°˜ν™˜μ€ μ‹ μ€‘νžˆ ν•˜λΌ
2 parents 745f01a + 3d46a11 commit 4c6f559

1 file changed

+134
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
## μ•„μ΄ν…œ55. μ˜΅μ…”λ„ λ°˜ν™˜μ€ μ‹ μ€‘νžˆ ν•˜λΌ
2+
3+
### μ–΄λŠ λ©”μ„œλ“œκ°€ 값을 λ°˜ν™˜ν•  수 없을 λ•Œ?
4+
5+
- μžλ°”8 이전엔..
6+
7+
1. μ˜ˆμ™Έλ₯Ό λ˜μ§„λ‹€
8+
9+
But..
10+
11+
- μ˜ˆμ™ΈλŠ” μ§„μ§œ μ˜ˆμ™Έμ μΈ μƒν™©μ—μ„œλ§Œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€
12+
- μ˜ˆμ™Έλ₯Ό 생성할 λ•Œ μŠ€νƒ 좔적 전체λ₯Ό μΊ‘μ³ν•˜λ―€λ‘œ λΉ„μš©μ΄ 크닀
13+
14+
2. null을 λ°˜ν™˜ν•œλ‹€
15+
16+
But..
17+
18+
- `null`을 λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” λ³„λ„μ˜ `null`처리 μ½”λ“œλ₯Ό μΆ”κ°€ν•΄μ•Ό ν•œλ‹€ -> μ „ν˜€ μƒκ΄€μ—†λŠ” μ½”λ“œμ— NPEκ°€ λ°œμƒν•  수 μžˆλ‹€
19+
20+
- μžλ°”8 이후엔 `Optional`
21+
22+
### `Optional<T>`λž€?
23+
24+
- μ›μ†Œλ₯Ό μ΅œλŒ€ 1개 κ°€μ§ˆ 수 μžˆλŠ” λΆˆλ³€ μ»¬λ ‰μ…˜
25+
- `null`이 μ•„λ‹Œ Tνƒ€μž… μ°Έμ‘°λ₯Ό ν•˜λ‚˜ λ‹΄κ±°λ‚˜("비지 μ•Šμ•˜λ‹€") 아무것도 담지 μ•Šμ„ 수 μžˆλ‹€("λΉ„μ—ˆλ‹€")
26+
- 보톡은 Tλ₯Ό λ°˜ν™˜ν•΄μ•Ό ν•˜μ§€λ§Œ νŠΉμ • μ‘°κ±΄μ—μ„œλŠ” 아무것도 λ°˜ν™˜ν•˜μ§€ μ•Šμ•„μ•Ό ν•  λ•Œ TλŒ€μ‹  `Optional<T>`λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ μ„ μ–Έν•˜λ©΄ λœλ‹€
27+
- μž₯점
28+
- μ˜΅μ…”λ„μ„ λ°˜ν™˜ν•˜λ©΄ μ˜ˆμ™Έλ₯Ό λ˜μ§€λŠ” 것보닀 μœ μ—°ν•˜κ³  μ‚¬μš©ν•˜κΈ° 쉽닀.
29+
- `null`을 λ°˜ν™˜ν•˜λŠ” 것보닀 였λ₯˜κ°€λŠ₯성이 적닀
30+
31+
### `Optional`을 μƒμ„±ν•˜λŠ” 법
32+
33+
- `Optional.empty()` : 빈 μ˜΅μ…”λ„
34+
- `Optional.of(value)` : 값이 λ“  μ˜΅μ…”λ„ (value에 `null`을 λ„£μœΌλ©΄ NPEλ₯Ό λ˜μ§„λ‹€)
35+
- `Optional.ofNullable(value)` : valueκ°€ `null`이면 빈 μ˜΅μ…”λ„
36+
- μ˜΅μ…”λ„μ„ λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œμ—μ„œλŠ” μ ˆλŒ€λ‘œ `null`을 λ°˜ν™˜ν•˜μ§€ 말자.
37+
38+
### μ–Έμ œ null을 λ°˜ν™˜ν•˜κ±°λ‚˜ μ˜ˆμ™Έλ₯Ό λ˜μ§€λŠ” 것보단 `Optional`을 λ°˜ν™˜ν•˜λŠ” 게 더 μ’‹μ„κΉŒ?
39+
40+
- λ°˜ν™˜κ°’μ΄ μ—†μ„μˆ˜λ„ μžˆμŒμ„ API μ‚¬μš©μžμ—κ²Œ λͺ…ν™•νžˆ μ•Œλ €μ£Όκ³  μ‹Άμ„λ•Œ
41+
- ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ 빈 μ˜΅μ…”λ„μΌλ•Œμ˜ 행동을 μ •μ˜ν•˜λ„λ‘ κ°•μ œν•˜κ³  μ‹Άμ„λ•Œ
42+
43+
### μ˜΅μ…”λ„μ„ λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ—μ„œλŠ”..
44+
45+
```java
46+
public class Person {
47+
private final String name;
48+
private final int age;
49+
// μƒμ„±μž, getter μƒλž΅
50+
}
51+
```
52+
53+
```java
54+
//μΈμžμ— 아무것도 주어지지 μ•ŠμœΌλ©΄ 빈 μ˜΅μ…”λ„ λ°˜ν™˜, 주어지면 ageκ°€ κ°€μž₯ 큰 Person을 담은 μ˜΅μ…”λ„ λ°˜ν™˜
55+
public Optional<Person> pickOldest(Person... people) {
56+
return Arrays.stream(people)
57+
.max(Comparator.comparingInt(Person::getAge));
58+
}
59+
```
60+
61+
1. 기본값을 μ •ν•΄λ‘˜ 수 μžˆλ‹€
62+
63+
```java
64+
Person oldest = pickOldest(person1, person2, person3)
65+
.orElse(new Person("기본이름", 0));
66+
```
67+
68+
```java
69+
//기본값을 μƒμ„±ν•˜λŠ” λΉ„μš©μ΄ 큰 경우 orElseGet을 μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€
70+
Person oldest = pickOldest(person1, person2, person3)
71+
.orElseGet(() -> new Person("기본이름", 0));
72+
```
73+
74+
2. μ›ν•˜λŠ” μ˜ˆμ™Έλ₯Ό 던질 수 μžˆλ‹€
75+
76+
```java
77+
Person oldest = pickOldest(person1, person2, person3)
78+
.orElseThrow(() -> new RuntimeException());
79+
```
80+
81+
μ‹€μ œ μ˜ˆμ™Έκ°€ μ•„λ‹ˆλΌ νŒ©ν„°λ¦¬λ₯Ό κ±΄λ„ΈμœΌλ―€λ‘œ μ˜ˆμ™Έκ°€ μ‹€μ œλ‘œ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ μ˜ˆμ™Έ 생성 λΉ„μš©μ€ 듀지 μ•ŠλŠ”λ‹€
82+
83+
3. 값이 μ±„μ›Œμžˆλ‹€κ³  κ°€μ •ν•˜κ³  κ·Έλƒ₯ 값을 κΊΌλ‚Έλ‹€
84+
85+
```java
86+
Person oldest = pickOldest(person1, person2, person3).get();
87+
```
88+
89+
빈 μ˜΅μ…”λ„μ΄λΌλ©΄ `NoSuchElementException`이 λ°œμƒν•œλ‹€
90+
91+
4. κ·Έ 외에도 `filter`, `map`, `flatMap`, `ifPresent` λ“± μ—¬λŸ¬ λ©”μ„œλ“œλ„ μžˆλ‹€
92+
93+
### `isPresent()`λŠ” λŒ€λΆ€λΆ„μ˜ 경우 λ‹€λ₯Έ λ©”μ„œλ“œλ‘œ λŒ€μ²΄ κ°€λŠ₯ν•˜λ‹€
94+
95+
κ°€μž₯ λ‚˜μ΄λ§Žμ€ μ‚¬λžŒμ˜ 이름을 좜λ ₯ν•˜κ³  μ‹Άμ„λ•Œ..
96+
97+
```java
98+
Optional<Person> oldest = pickOldest(person1, person2, person3);
99+
100+
//not good
101+
System.out.println("κ°€μž₯ λ‚˜μ΄λ§Žμ€ μ‚¬λžŒμ€? " + (oldest.isPresent() ? oldest.get().getName() : "κ²°κ³Όμ—†μŒ"));
102+
//good
103+
System.out.println("κ°€μž₯ λ‚˜μ΄λ§Žμ€ μ‚¬λžŒμ€? " + (oldest.map(p -> p.getName()).orElse("κ²°κ³Όμ—†μŒ")));
104+
```
105+
106+
`isPresent()` ν›„ `get()` ν•˜λŠ”κ²ƒλ³΄λ‹¨ `map()`을 μ‚¬μš©ν•˜λŠ”κ²Œ 더 짧고 λͺ…ν™•ν•˜κ³  μš©λ²•μ— λ§žλ‹€.
107+
108+
### μ˜΅μ…”λ„μ˜ 슀트림
109+
110+
`Stream<Optional<T>>`μ—μ„œ μ±„μ›Œμ§„ μ˜΅μ…”λ„λ§Œμ„ λ½‘μ•„μ„œ `Stream<T>`둜 λ§Œλ“€κ³  μ‹Άμ„λ•Œ..
111+
112+
```java
113+
//not good (μžλ°”8)
114+
Stream<Person> personStream = streamOfOptionals
115+
.filter(Optional::isPresent)
116+
.map(Optional::get);
117+
118+
//good (μžλ°”9 이상)
119+
Stream<Person> personStream = streamOfOptionals
120+
.flatMap(Optional::stream);
121+
```
122+
123+
### μ£Όμ˜μ‚¬ν•­
124+
125+
- μ»¬λ ‰μ…˜, 슀트림, λ°°μ—΄, μ˜΅μ…”λ„κ°™μ€ μ»¨ν…Œμ΄λ„ˆ νƒ€μž…μ€ μ˜΅μ…”λ„λ‘œ 감싸면 μ•ˆλœλ‹€.
126+
- `Optional<List<T>>` 보단 빈 `List<T>`을 λ°˜ν™˜ν•˜λŠ” 게 μ’‹λ‹€
127+
- 그러면 ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ˜΅μ…”λ„ 처리 μ½”λ“œλ₯Ό 넣지 μ•Šμ•„λ„ λœλ‹€
128+
- λ°•μ‹±λœ κΈ°λ³Ένƒ€μž…(`Integer`, `Long`, `Double`)을 담은 μ˜΅μ…”λ„μ„ λ°˜ν™˜ν•˜λ©΄ μ•ˆλœλ‹€.
129+
- λ°•μ‹±λœ κΈ°λ³Ένƒ€μž…μ„ λ‹΄λŠ” μ˜΅μ…”λ„μ€ κΈ°λ³Έ νƒ€μž… μžμ²΄λ³΄λ‹€ 무겁기 λ•Œλ¬Έμ— μžλ°” API μ„€κ³„μžλŠ” κΈ°λ³Ένƒ€μž… μ „μš© μ˜΅μ…”λ„μ„ 이미 λ§Œλ“€μ–΄λ†¨λ‹€.
130+
- `OptionalInt`, `OptionalLong`, `OptionalDouble`을 μ‚¬μš©ν•˜μž
131+
- 덜 μ€‘μš”ν•œ κΈ°λ³Ένƒ€μž…μš©(`Boolean`, `Byte`, `Character`, `Short`, `Float`)은 μ œμ™Έ
132+
- μ˜΅μ…”λ„μ„ μ»¬λ ‰μ…˜μ˜ ν‚€, κ°’, μ›μ†Œλ‚˜ λ°°μ—΄μ˜ μ›μ†Œλ‘œ μ‚¬μš©ν•˜λŠ” 게 μ μ ˆν•œ 상황은 거의 μ—†λ‹€
133+
- 예λ₯Ό λ“€μ–΄ μ˜΅μ…”λ„μ„ 맡의 κ°’μœΌλ‘œ μ‚¬μš©ν•œλ‹€λ©΄ 쓸데없이 λ³΅μž‘μ„±λ§Œ 높아진닀
134+
- μ˜΅μ…”λ„μ„ μΈμŠ€ν„΄μŠ€ ν•„λ“œμ— μ €μž₯ν•˜λŠ” 건 λŒ€λΆ€λΆ„ μ•ˆμ’‹μ§€λ§Œ ν•„μˆ˜κ°€ μ•„λ‹Œ ν•„λ“œμ— κ²½μš°μ—” μ μ ˆν•œ 상황도 μžˆλ‹€

0 commit comments

Comments
Β (0)