Skip to content

Commit

Permalink
GITBOOK-191: No subject
Browse files Browse the repository at this point in the history
  • Loading branch information
GoldenPearls authored and gitbook-bot committed Nov 12, 2024
1 parent 57543ae commit 108516b
Showing 1 changed file with 196 additions and 11 deletions.
207 changes: 196 additions & 11 deletions developLog/programming-lanuage/java/effective-java/7/item-44.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

> 이둜 인해 <mark style="color:red;">ν•¨μˆ˜ 객체λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›λŠ” μƒμ„±μžμ™€ λ©”μ„œλ“œλ₯Ό 더 많이 μž‘μ„±</mark>ν•˜κ²Œ λ˜μ—ˆμœΌλ©°, μ˜¬λ°”λ₯Έ **ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…**을 μ„ νƒν•˜λŠ” 것이 μ€‘μš”ν•΄μ‘Œλ‹€. 즉, ν•¨μˆ˜ν˜• λ§€κ°œλ³€μˆ˜ νƒ€μž…μ„ μ˜¬λ°”λ₯΄κ²Œ 선택해야 ν•œλ‹€.
μžλ°”μ˜ ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œλŠ” 이미 λ‹€μ–‘ν•œ μš©λ„μ˜ **ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**κ°€ 제곡되고 있으며, 이듀을 ν™œμš©ν•˜λ©΄ λΆˆν•„μš”ν•˜κ²Œ μƒˆλ‘œμš΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μž‘μ„±ν•˜μ§€ μ•Šκ³ λ„ ν•„μš”ν•œ κΈ°λŠ₯을 κ΅¬ν˜„ν•  수 μžˆλ‹€. 특히 `java.util.function` νŒ¨ν‚€μ§€μ—λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜κΈ° μœ„ν•΄ 총 43개의 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€κ°€ μ€€λΉ„λ˜μ–΄ μžˆλ‹€.

## 1. ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ—μ„œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œ μ „ν™˜

κ³Όκ±°μ—λŠ” <mark style="color:blue;">μƒμœ„ 클래슀의 κΈ°λ³Έ λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜μ—¬ λ™μž‘μ„ 맞좀 μ„€μ •</mark>ν•˜λŠ” **ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄**을 많이 μ‚¬μš©ν–ˆλ‹€. ν•˜μ§€λ§Œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ™€ λžŒλ‹€λ₯Ό μ΄μš©ν•˜λ©΄ 이보닀 κ°„κ²°ν•˜κ³  μœ μ§€λ³΄μˆ˜ν•˜κΈ° 쒋은 APIλ₯Ό λ§Œλ“€ 수 μžˆλ‹€.
Expand Down Expand Up @@ -81,14 +83,44 @@ CustomCache<String, String> cache = new CustomCache<>((map, entry) -> map.size()

ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” 크게 λ‹€μŒκ³Ό 같은 μœ ν˜•μ΄ μžˆλ‹€.

| μΈν„°νŽ˜μ΄μŠ€ | ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜ | μ„€λͺ… |
| ------------------- | --------------------- | --------------------- |
| `UnaryOperator<T>` | `T apply(T t)` | 인수λ₯Ό ν•˜λ‚˜ λ°›μ•„ 같은 νƒ€μž…μ„ λ°˜ν™˜ |
| `BinaryOperator<T>` | `T apply(T t1, T t2)` | 인수λ₯Ό 두 개 λ°›μ•„ 같은 νƒ€μž…μ„ λ°˜ν™˜ |
| `Predicate<T>` | `boolean test(T t)` | 인수λ₯Ό ν•˜λ‚˜ λ°›μ•„ boolean을 λ°˜ν™˜ |
| `Function<T,R>` | `R apply(T t)` | μΈμˆ˜μ™€ λ°˜ν™˜ νƒ€μž…μ΄ λ‹€λ₯Έ ν•¨μˆ˜ |
| `Supplier<T>` | `T get()` | 인수λ₯Ό 받지 μ•Šκ³  값을 λ°˜ν™˜ |
| `Consumer<T>` | `void accept(T t)` | 인수λ₯Ό ν•˜λ‚˜ λ°›κ³  값을 λ°˜ν™˜ν•˜μ§€ μ•ŠμŒ |
기본적으둜 μžλ°”μ˜ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” λ‹€μŒκ³Ό 같은 μœ ν˜•μœΌλ‘œ λ‚˜λ‰©λ‹ˆλ‹€. 이 μΈν„°νŽ˜μ΄μŠ€λ“€μ€ **객체 μ°Έμ‘° νƒ€μž…**을 μœ„ν•œ κΈ°λ³Έ μΈν„°νŽ˜μ΄μŠ€λ“€λ‘œ, μ‹€λ¬΄μ—μ„œ 자주 ν™œμš©λ©λ‹ˆλ‹€.

| μΈν„°νŽ˜μ΄μŠ€ | ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜ | μ„€λͺ… | μ‚¬μš© μ˜ˆμ‹œ |
| ------------------- | --------------------- | --------------------------- | --------------------- |
| `UnaryOperator<T>` | `T apply(T t)` | 인수λ₯Ό ν•˜λ‚˜ λ°›μ•„ 같은 νƒ€μž…μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€. | `String::toLowerCase` |
| `BinaryOperator<T>` | `T apply(T t1, T t2)` | 인수λ₯Ό 두 개 λ°›μ•„ 같은 νƒ€μž…μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€. | `BigInteger::add` |
| `Predicate<T>` | `boolean test(T t)` | 인수λ₯Ό ν•˜λ‚˜ λ°›μ•„ `boolean`을 λ°˜ν™˜ν•©λ‹ˆλ‹€. | `Collection::isEmpty` |
| `Function<T, R>` | `R apply(T t)` | μΈμˆ˜μ™€ λ°˜ν™˜ νƒ€μž…μ΄ λ‹€λ₯Ό λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€. | `Arrays::asList` |
| `Supplier<T>` | `T get()` | 인수λ₯Ό 받지 μ•Šκ³  값을 λ°˜ν™˜ν•©λ‹ˆλ‹€. | `Instant::now` |
| `Consumer<T>` | `void accept(T t)` | 인수λ₯Ό ν•˜λ‚˜ λ°›κ³  λ°˜ν™˜κ°’μ΄ μ—†μŠ΅λ‹ˆλ‹€. | `System.out::println` |

**μ˜ˆμ‹œ - `Predicate`와 `BiPredicate` ν™œμš©**

`Predicate`와 `BiPredicate`λŠ” 쑰건을 ν‘œν˜„ν•˜λŠ” 데 μ‚¬μš©λ˜λ©°, 각각 ν•˜λ‚˜ λ˜λŠ” 두 개의 인수λ₯Ό λ°›μ•„ `boolean`을 λ°˜ν™˜ν•œλ‹€. 예λ₯Ό λ“€μ–΄, νŠΉμ • 크기 이상일 λ•Œ μΊμ‹œ ν•­λͺ©μ„ μ‚­μ œν•˜λ„λ‘ 쑰건을 μ„€μ •ν•  수 μžˆλ‹€.

```java
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiPredicate;

class CustomCache<K, V> extends LinkedHashMap<K, V> {
private final BiPredicate<Map<K, V>, Map.Entry<K, V>> removalCriteria;

public CustomCache(BiPredicate<Map<K, V>, Map.Entry<K, V>> removalCriteria) {
this.removalCriteria = removalCriteria;
}

@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return removalCriteria.test(this, eldest);
}
}

// μ‚¬μš© 예: μΊμ‹œ 크기가 100을 μ΄ˆκ³Όν•˜λ©΄ 였래된 ν•­λͺ© 제거
CustomCache<String, String> cache = new CustomCache<>((map, entry) -> map.size() > 100);
```

μœ„ μ½”λ“œλŠ” `BiPredicate`λ₯Ό μ‚¬μš©ν•΄ νŠΉμ • 크기λ₯Ό λ„˜μ„ λ•Œ μΊμ‹œ ν•­λͺ©μ„ μ œκ±°ν•˜λ„λ‘ μ„€μ •ν•œ μ˜ˆμ‹œμ΄λ‹€.

**예제**

Expand Down Expand Up @@ -124,9 +156,19 @@ CustomCache<String, String> cache = new CustomCache<>((map, entry) -> map.size()
System.out.println(toLowerCase.apply("HELLO")); // hello
```

### 2) ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ ν™œμš©μ˜ 이점

κΈ°μ‘΄μ—λŠ” μ»€μŠ€ν…€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μž‘μ„±ν•˜μ—¬ κΈ°λŠ₯을 κ΅¬ν˜„ν•˜λŠ” κ²½μš°κ°€ λ§Žμ•˜μ§€λ§Œ, ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ λ‹€μŒκ³Ό 같은 이점을 λˆ„λ¦΄ 수 μžˆλ‹€:

* **μ½”λ“œμ˜ κ°„κ²°μ„±**: μ€‘λ³΅λ˜λŠ” μΈν„°νŽ˜μ΄μŠ€ 생성을 ν”Όν•  수 μžˆλ‹€.
* **API의 일관성**: μžλ°” κ°œλ°œμžλ“€μ΄ 이미 μ΅μˆ™ν•œ ν‘œμ€€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ―€λ‘œ, μƒˆλ‘œμš΄ κ°œλ…μ„ 읡힐 ν•„μš”κ°€ 쀄어든닀.
* **λ””ν΄νŠΈ λ©”μ„œλ“œμ˜ ν™œμš©**: ν‘œμ€€ μΈν„°νŽ˜μ΄μŠ€λŠ” ν•„μš”ν•œ 경우 λ©”μ„œλ“œλ₯Ό μ‘°ν•©ν•˜κ±°λ‚˜ λ³€ν˜•ν•  수 μžˆλŠ” μœ μš©ν•œ λ””ν΄νŠΈ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜μ—¬ λ‹€λ₯Έ μ½”λ“œμ™€ μ‰½κ²Œ μƒν˜Έ 운용이 κ°€λŠ₯ν•˜λ‹€.

예λ₯Ό λ“€μ–΄, `Predicate` μΈν„°νŽ˜μ΄μŠ€λŠ” 쑰건을 μ‘°ν•©ν•  수 μžˆλŠ” `and`, `or`, `negate` λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜μ—¬ λ³΅μž‘ν•œ 쑰건을 κ°„νŽΈν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλ‹€.

## 3. κΈ°λ³Έ νƒ€μž…μš© ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

κΈ°λ³Έ νƒ€μž…μ„ μœ„ν•΄ `java.util.function` νŒ¨ν‚€μ§€μ—μ„œλŠ” κΈ°λ³Έ νƒ€μž…μš© ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ„ μ œκ³΅ν•œλ‹€. 예λ₯Ό λ“€μ–΄, `IntPredicate`, `LongFunction`, `DoubleConsumer` 등이닀. κΈ°λ³Έ νƒ€μž…μ„ μ§€μ›ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ **λ°•μ‹± μ˜€λ²„ν—€λ“œ**λ₯Ό ν”Όν•  수 μžˆμ–΄ μ„±λŠ₯이 κ°œμ„ λœλ‹€.
κΈ°λ³Έ νƒ€μž…μ„ μœ„ν•΄ `java.util.function` νŒ¨ν‚€μ§€μ—μ„œλŠ” κΈ°λ³Έ νƒ€μž…μš© ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ„ μ œκ³΅ν•œλ‹€. 박싱을 ν”Όν•˜κ³  μ„±λŠ₯을 높이기 μœ„ν•΄ κΈ°λ³Έ νƒ€μž…μ„ μœ„ν•œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ λ³€ν˜•λ„ μ œκ³΅ν•œλ‹€. 예λ₯Ό λ“€μ–΄, `IntPredicate`, `LongFunction`, `DoubleConsumer` 등이닀. κΈ°λ³Έ νƒ€μž…μ„ μ§€μ›ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ **λ°•μ‹± μ˜€λ²„ν—€λ“œ**λ₯Ό ν”Όν•  수 μžˆμ–΄ μ„±λŠ₯이 κ°œμ„ λœλ‹€.

**예제**

Expand All @@ -136,6 +178,33 @@ System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(5)); // false
```

μžλ°” κΈ°λ³Έ νƒ€μž…μ„ μœ„ν•œ λ³€ν˜•μ€ λ‹€μŒκ³Ό 같은 κ·œμΉ™μ— 따라 λ„€μ΄λ°λœλ‹€.

1. **νƒ€μž… 접두어**: `Int`, `Long`, `Double`을 μ‚¬μš©ν•˜μ—¬ κΈ°λ³Έ νƒ€μž…μ„ λͺ…μ‹œ
2. **κΈ°λŠ₯**: `Predicate`, `Function`, `Consumer` λ“± μ£Όμš” κΈ°λŠ₯을 반영
3. **λ³€ν˜• μ˜ˆμ‹œ**:
* `IntPredicate`: `boolean test(int value)` ν˜•νƒœλ‘œ `int` νƒ€μž…μ„ λ°›λŠ”λ‹€.
* `LongToIntFunction`: `int applyAsInt(long value)` ν˜•νƒœλ‘œ `long` νƒ€μž…μ˜ 인수λ₯Ό λ°›κ³  `int`λ₯Ό λ°˜ν™˜ν•œλ‹€.

**μ˜ˆμ‹œ - κΈ°λ³Έ νƒ€μž…μš© ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**

κΈ°λ³Έ νƒ€μž…μ„ μ‚¬μš©ν•˜μ—¬ νŠΉμ • 쑰건을 κ²€μ‚¬ν•˜λŠ” 예제

```java
import java.util.function.IntPredicate;

public class BasicTypePredicateExample {
public static void main(String[] args) {
IntPredicate isEven = value -> value % 2 == 0;

System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(5)); // false
}
}
```

μœ„ μ˜ˆμ œμ—μ„œλŠ” `IntPredicate`λ₯Ό μ‚¬μš©ν•˜μ—¬ μˆ«μžκ°€ μ§μˆ˜μΈμ§€ μ—¬λΆ€λ₯Ό κ²€μ‚¬ν•œλ‹€.

## 4. 직접 μž‘μ„±ν•΄μ•Ό ν•˜λŠ” 경우

ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€κ°€ 거의 λŒ€λΆ€λΆ„μ˜ 경우λ₯Ό μ»€λ²„ν•˜μ§€λ§Œ, **λ‹€μŒκ³Ό 같은 경우**μ—λŠ” 직접 μž‘μ„±ν•˜λŠ” 것이 더 λ‚˜μ„ 수 μžˆλ‹€.
Expand All @@ -144,14 +213,17 @@ System.out.println(isEven.test(5)); // false
* **자주 μ‚¬μš©λ˜λ©° μ΄λ¦„λ§ŒμœΌλ‘œ μš©λ„κ°€ λͺ…ν™•ν•œ 경우**: 자주 μ‚¬μš©λ˜λ©° λͺ…ν™•ν•œ 이름을 가지면 μ½”λ“œ 가독성이 높아진닀.
* **좔가적인 λ””ν΄νŠΈ λ©”μ„œλ“œκ°€ ν•„μš”ν•œ 경우**: μΈν„°νŽ˜μ΄μŠ€ λ‚΄μ—μ„œ λ©”μ„œλ“œλ₯Ό μ‘°ν•©ν•˜κ±°λ‚˜ λ³€ν˜•ν•˜λŠ” λ””ν΄νŠΈ λ©”μ„œλ“œκ°€ ν•„μš”ν•œ κ²½μš°κ°€ μžˆλ‹€.

**예제 - μ»€μŠ€ν…€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**
**μ˜ˆμ‹œ - 3개의 λ§€κ°œλ³€μˆ˜λ₯Ό λ°›λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**

`java.util.function` νŒ¨ν‚€μ§€μ—λŠ” λ§€κ°œλ³€μˆ˜ 3개λ₯Ό λ°›λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€κ°€ μ—†μœΌλ―€λ‘œ, 직접 μž‘μ„±ν•  수 μžˆλ‹€.

```java
@FunctionalInterface
interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v);
}

// μ‚¬μš© μ˜ˆμ‹œ
TriFunction<Integer, Integer, Integer, Integer> sumThree = (a, b, c) -> a + b + c;
System.out.println(sumThree.apply(1, 2, 3)); // 6
```
Expand All @@ -160,13 +232,126 @@ System.out.println(sumThree.apply(1, 2, 3)); // 6

μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό 같은 μœ„μΉ˜μ˜ 인수둜 λ°›λŠ” λ©”μ„œλ“œλ₯Ό 닀쀑 μ •μ˜ν•˜λŠ” 것은 ν”Όν•΄μ•Ό ν•œλ‹€. 예λ₯Ό λ“€μ–΄, `ExecutorService`의 `submit` λ©”μ„œλ“œλŠ” `Callable`κ³Ό `Runnable`을 닀쀑 μ •μ˜ν•˜λŠ”λ°, 이λ₯Ό μ‚¬μš©ν•  λ•Œ ν˜•λ³€ν™˜μ΄ ν•„μš”ν•œ κ²½μš°κ°€ 생긴닀. μ΄λŠ” λΆˆν•„μš”ν•œ ν˜Όλž€μ„ μ΄ˆλž˜ν•  수 μžˆλ‹€.

λ”°λΌμ„œ, **같은 μœ„μΉ˜μ˜ 인수둜 μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό 받지 μ•Šλ„λ‘ 주의**ν•˜λŠ” 것이 μ’‹λ‹€.
> λ”°λΌμ„œ, **같은 μœ„μΉ˜μ˜ 인수둜 μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό 받지 μ•Šλ„λ‘ 주의**ν•˜λŠ” 것이 μ’‹λ‹€.&#x20;
μ΄λŠ” API μ„€κ³„μ—μ„œ λͺ¨ν˜Έν•¨μ„ 쀄이고, μ‚¬μš©μžκ°€ μ½”λ“œμ˜ μ˜λ„λ₯Ό λͺ…ν™•ν•˜κ²Œ 이해할 수 μžˆλ„λ‘ 도와쀀닀.

{% hint style="info" %}
μ•ˆ 쒋은 μ˜ˆμ‹œ
{% endhint %}

μ•„λž˜λŠ” μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€(`Callable`κ³Ό `Runnable`)λ₯Ό 같은 μœ„μΉ˜μ—μ„œ 받도둝 닀쀑 μ •μ˜λœ λ©”μ„œλ“œ

```java
import java.util.concurrent.Callable;

public class ExecutorServiceExample {
// Runnable을 인수둜 λ°›λŠ” λ©”μ„œλ“œ
public void submit(Runnable task) {
System.out.println("Runnable version called");
task.run();
}

// Callable을 인수둜 λ°›λŠ” λ©”μ„œλ“œ
public <T> T submit(Callable<T> task) throws Exception {
System.out.println("Callable version called");
return task.call();
}

public static void main(String[] args) throws Exception {
ExecutorServiceExample service = new ExecutorServiceExample();

// Runnable을 μ‚¬μš©ν•œ 경우
service.submit(() -> System.out.println("Running task..."));

// Callable을 μ‚¬μš©ν•œ 경우
String result = service.submit(() -> {
System.out.println("Calling task...");
return "Task result";
});
System.out.println("Result: " + result);

// ν˜Όλž€μ„ μΌμœΌν‚¬ 수 μžˆλŠ” λͺ¨ν˜Έν•œ 상황
service.submit((Callable<Void>) () -> {
System.out.println("Ambiguous task...");
return null;
});
}
}
```

* `submit(Runnable task)`: `Runnable` μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ°›λŠ” `submit` λ©”μ„œλ“œμ΄λ‹€.
* `submit(Callable<T> task)`: `Callable` μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ°›λŠ” μ œλ„€λ¦­ `submit` λ©”μ„œλ“œμ΄λ‹€.
* 두 λ©”μ„œλ“œλŠ” λͺ¨λ‘ 같은 μ΄λ¦„μ˜ `submit` λ©”μ„œλ“œμ§€λ§Œ, 인수의 νƒ€μž…λ§Œ λ‹€λ₯΄κ²Œ μ •μ˜λ˜μ–΄ μžˆλ‹€.

> 문제점
이 닀쀑 μ •μ˜λœ λ©”μ„œλ“œλŠ” `Runnable`κ³Ό `Callable` 쀑 μ–΄λ–€ 것을 ν˜ΈμΆœν• μ§€ λͺ¨ν˜Έν•œ κ²½μš°κ°€ λ°œμƒν•  수 μžˆλ‹€. 특히 **λžŒλ‹€ ν‘œν˜„μ‹**으둜 전달할 λ•Œ 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. `Runnable`κ³Ό `Callable`은 λ‘˜ λ‹€ μΈμˆ˜κ°€ μ—†μœΌλ―€λ‘œ λžŒλ‹€μ‹μœΌλ‘œλŠ” λͺ…ν™•νžˆ κ΅¬λΆ„λ˜μ§€ μ•ŠλŠ”λ‹€. 예λ₯Ό λ“€μ–΄, λ‹€μŒκ³Ό 같이 ν˜ΈμΆœν•  λ•Œ λ¬Έμ œκ°€ λœλ‹€.

```java
service.submit(() -> {
System.out.println("Ambiguous task...");
return null;
});
```

μœ„ μ½”λ“œλŠ” `Runnable`인지 `Callable`인지 μ»΄νŒŒμΌλŸ¬κ°€ κ΅¬λΆ„ν•˜μ§€ λͺ»ν•˜μ—¬ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¨λ‹€. 이λ₯Ό ν•΄κ²°ν•˜λ €λ©΄ **λͺ…μ‹œμ μΈ ν˜•λ³€ν™˜**이 ν•„μš”ν•˜λ‹€.

```java
service.submit((Callable<Void>) () -> {
System.out.println("Callable task...");
return null;
});
```

λͺ…μ‹œμ  ν˜•λ³€ν™˜μ„ 톡해 `Callable`μ΄λΌλŠ” μ˜λ„λ₯Ό λͺ…ν™•νžˆ ν–ˆμ§€λ§Œ, μ΄λŠ” μ½”λ“œλ₯Ό 더 λ³΅μž‘ν•˜κ²Œ λ§Œλ“€κ³  μ‹€μˆ˜ν•  κ°€λŠ₯성을 높인닀.

#### ν•΄κ²° 방법: ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ 닀쀑 μ •μ˜λ₯Ό ν”Όν•˜κΈ°

이 문제λ₯Ό ν”Όν•˜λ €λ©΄ μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό 같은 μœ„μΉ˜μ˜ 인수둜 λ°›λŠ” **닀쀑 μ •μ˜λ₯Ό ν”Όν•˜λŠ” 것**이 μ’‹λ‹€. 예λ₯Ό λ“€μ–΄, `submit` λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜λ‘œ ν†΅μΌν•˜κ³ , `Runnable`μ΄λ‚˜ `Callable`이 ν•„μš”ν•  경우 래퍼 λ©”μ„œλ“œλ‘œ κ΅¬λΆ„ν•˜λŠ” 방식이 κ°€λŠ₯ν•˜λ‹€.

```java
public class ExecutorServiceExample {
public <T> T submitTask(Callable<T> task) throws Exception {
System.out.println("Callable version called");
return task.call();
}

public void submitTask(Runnable task) {
System.out.println("Runnable version called");
task.run();
}

public static void main(String[] args) throws Exception {
ExecutorServiceExample service = new ExecutorServiceExample();

// Runnable둜 전달
service.submitTask(() -> System.out.println("Running task..."));

// Callable둜 전달
String result = service.submitTask(() -> {
System.out.println("Calling task...");
return "Task result";
});
System.out.println("Result: " + result);
}
}
```

μ΄λ ‡κ²Œ λ©”μ„œλ“œ 이름을 λͺ…ν™•νžˆ λ‚˜λˆ„μ–΄ **각 λ©”μ„œλ“œκ°€ μ–΄λ–€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ°›λŠ”μ§€ λͺ…ν™•νžˆ** ν•˜λ©΄ ν˜Όλž€μ„ 쀄일 수 μžˆλ‹€.



## 핡심 μš”μ•½

1. **ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**λ₯Ό 톡해 λžŒλ‹€ ν‘œν˜„μ‹μ„ ν™œμš©ν•˜λ©΄ μ½”λ“œκ°€ 간결해지고 μœ μ—°μ„±μ΄ 높아진닀.
2. **ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**λ₯Ό 적극적으둜 ν™œμš©ν•˜κ³ , ν•„μš”ν•  λ•Œλ§Œ μ»€μŠ€ν…€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜λŠ” 것이 μ’‹λ‹€.

> `Predicate`, `Function`, `Supplier`, `Consumer` λ“±μ˜ μ£Όμš” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” λŒ€λΆ€λΆ„μ˜ 경우λ₯Ό 컀버할 수 μžˆμ–΄, **ν‘œμ€€ μΈν„°νŽ˜μ΄μŠ€** μ‚¬μš©μ„ μš°μ„ μ μœΌλ‘œ κ³ λ €ν•΄μ•Ό ν•œλ‹€.
3. μ»€μŠ€ν…€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•  λ•ŒλŠ” **λ°˜λ“œμ‹œ 따라야 ν•  κ·œμ•½**μ΄λ‚˜ **μœ μš©ν•œ λ””ν΄νŠΈ λ©”μ„œλ“œ**κ°€ ν•„μš”ν•œμ§€ 고민해보아야 ν•œλ‹€.
4. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό 닀쀑 μ •μ˜ν•˜λŠ” 것을 ν”Όν•˜μ—¬ **λͺ¨ν˜Έν•¨**을 λ°©μ§€ν•œλ‹€.
5. μžλ°”μ—μ„œ **ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€**λ₯Ό 적극 ν™œμš©ν•˜λ©΄ λΆˆν•„μš”ν•œ μΈν„°νŽ˜μ΄μŠ€ μž‘μ„±μ„ 쀄일 수 있으며, APIκ°€ 더 일관성 있고 간결해진닀.
6. **κΈ°λ³Έ νƒ€μž…μš© μΈν„°νŽ˜μ΄μŠ€**λ₯Ό μ‚¬μš©ν•˜μ—¬ μ„±λŠ₯을 μ΅œμ ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ°•μ‹±λœ νƒ€μž… λŒ€μ‹  `IntPredicate`, `LongFunction` λ“± κΈ°λ³Έ νƒ€μž…μ„ μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

μžλ°”μ—μ„œλ„ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ μž₯점을 ν™œμš©ν•  수 μžˆμœΌλ―€λ‘œ, API 섀계 μ‹œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ˜ ν™œμš©μ„ 염두에 λ‘λŠ” 것이 μ’‹λ‹€.

0 comments on commit 108516b

Please sign in to comment.