Generic ๊ณผ Enum

1. Generic

1.1 ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฌธ๋ฒ•

Java ์˜ ์ œ๋„ˆ๋ฆญ(Generic) ์€ ํด๋ž˜์Šค, ์ธํ„ฐํŽ˜์ด์Šค, ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ(type parameter) ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ํƒ€์ž…์— ๋Œ€ํ•ด ๋™์ž‘ํ•˜๋Š” ์ผ๋ฐ˜ํ™”๋œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž„. ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋ณดํ†ต <> ๊บฝ์‡  ๊ด„ํ˜ธ๋กœ ํ‘œํ˜„ํ•˜๋ฉฐ, ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„ ๋’ค ๋˜๋Š” ๋ฉ”์„œ๋“œ ์„ ์–ธ๋ถ€์—์„œ ๋ช…์‹œํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด JDK ์˜ List<E> ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์š”์†Œ์˜ ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ E ๋ฅผ ์„ ์–ธํ•˜๋ฉฐ, Iterator<E> ์™€ ํ•จ๊ป˜ ์ œ๋„ค๋ฆญ์œผ๋กœ ์ •์˜๋˜์–ด ์žˆ์Œ. ๋˜ํ•œ Comparable<T> ์ธํ„ฐํŽ˜์ด์Šค ์—ญ์‹œ int compareTo(T o) ์™€ ๊ฐ™์ด ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ T ๋ฅผ ์‚ฌ์šฉํ•จ. ์ด๋Ÿฌํ•œ <T> , <K, V> ์™€ ๊ฐ™์€ ํ‘œ๊ธฐ๋ฒ•์€ ๊ฐ๊ฐ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๋•Œ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•จ.

์ œ๋„ค๋ฆญ ํƒ€์ž…์€ ์‚ฌ์šฉ ์‹œ์— ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ธ์ž๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐํ™” ๋œ ํƒ€์ž… ์„ ๋งŒ๋“ฌ. ์˜ˆ๋ฅผ ๋“ค์–ด List<String> ์€ List<E> ์˜ E ๋ฅผ String ์œผ๋กœ ์ง€์ •ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐํ™” ํƒ€์ž… ์ž„. ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. ๋ฉ”์„œ๋“œ์—๋„ ์ œ๋„ค๋ฆญ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ฉ”์„œ๋“œ ๋ฆฌํ„ด ํƒ€์ž… ์•ž์— <T> ๋“ฑ์„ ๋ช…์‹œํ•˜์—ฌ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ ๋กœ ์„ ์–ธํ•จ. (์ƒ์„ฑ์ž์—๋„ ์ œ๋„ค๋ฆญ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Œ.)

//์ œ๋„ค๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค ์˜ˆ์‹œ : ์ž…๋ ฅ ํƒ€์ž… F๋ฅผ ์ถœ๋ ฅ ํƒ€์ž… T๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค
interface Converter<F, T> {
    T convert(F from);
}

// ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค ์˜ˆ์‹œ : ๋‘ ๊ฐœ์˜ ๊ฐ’์„ ์Œ์œผ๋กœ ๋ณด๊ด€ํ•˜๋Š” ํด๋ž˜์Šค
class Pair<K, V> {
    private K key;
    private V value;
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
    public K getKey() { return key; }
    public V getValue() { return value; }
}

// ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ ์˜ˆ์‹œ : ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๋ฉ”์„œ๋“œ
class GenericUtils {
    public static <T> void printArray(T[] arr) {
        for(T element : arr) {
            System.out.println(element);
        }
    }
}

์œ„ ์ฝ”๋“œ์—์„œ Converter<F, T> ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ ์˜ˆ์‹œ์ด๋ฉฐ, Pair<K, V> ๋Š” ํด๋ž˜์Šค์— ๋‘ ๊ฐœ์˜ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•œ ์˜ˆ์ž„. GenericUtils.printArray ๋ฉ”์„œ๋“œ๋Š” <T> ๋ผ๋Š” ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜์—ฌ, ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ์ž„์˜์˜ ์ฐธ์กฐํ˜• ํƒ€์ž… ๋ฐฐ์—ด์„ ๋ฐ›์•„ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ ์ž„. ์ด์ฒ˜๋Ÿผ ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•  ๋•Œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํƒ€์ž…์ด ํ•„์š”ํ•œ ์œ„์น˜(ํ•„๋“œ ํƒ€์ž…, ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ ๋ณ€ํ™˜ ํƒ€์ž… ๋“ฑ) ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. ์‹ค์ œ ์‚ฌ์šฉ ์‹œ์—๋Š” new Pair<String, Integer>("apple", 3) ์ฒ˜๋Ÿผ ํƒ€์ž… ์ธ์ž๋ฅผ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•ด์•ผ ํ•˜๋ฉฐ, ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ๊ฒ€์‚ฌํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•ด์คŒ. (Java 7 ๋ถ€ํ„ฐ๋Š” ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ ํƒ€์ž… ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•ด new Pair<>("apple", 3) ์™€ ๊ฐ™์ด ์ƒ์„ฑ์ž์ชฝ ๊บฝ์‡ ๋ฅผ ์ƒ๋žตํ•˜๋Š” ๋‹ค์ด์•„๋ชฌ๋“œ ์—ฐ์‚ฐ์ž ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.)

1.2 ์ œ์•ฝ ์กฐ๊ฑด๊ณผ bounded type(extends, ๋‹ค์ค‘ bound ๋“ฑ)

์ œ๋„ค๋ฆญ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ œ์•ฝ ์กฐ๊ฑด(bound) ์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉํ•  ํƒ€์ž…์˜ ์ƒํ•œ ๋˜๋Š” ํ•˜ํ•œ์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Œ. ์ƒํ•œ ๊ฒฝ๊ณ„(Upper Bound) ๋ฅผ ์ง€์ •ํ•  ๋•Œ๋Š” extends ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด class NumberBox<T extends Number> ๋ผ๊ณ  ์„ ์–ธํ•˜๋ฉด ์ด ํด๋ž˜์Šค์˜ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ T ๋Š” Number ์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋“ค๋งŒ ํ—ˆ์šฉ๋จ. ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ์ƒํ•œ๋„ extends ๋กœ ํ‘œ๊ธฐํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ƒํ•œ์„ ์ง€์ •ํ•˜๋Š” ๋‹ค์ค‘ bound ๋„ ๊ฐ€๋Šฅํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด <T extends Number & Comparable<T>> ๋ผ๊ณ  ํ•˜๋ฉด T ๋Š” Number ๋ฅผ ์ƒ์†๋ฐ›๊ณ  ๋™์‹œ์— Comparable<T> ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค์—ฌ์•ผ ํ•จ. ๋‹ค์ค‘ bound ๋ฅผ ์ง€์ •ํ•  ๋•Œ๋Š” ํด๋ž˜์Šค๋Š” ํ•œ ๋ฒˆ๋งŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ (Number ๊ฐ™์€ ํด๋ž˜์Šค ์ƒํ•œ์„ ๋‘˜ ์ด์ƒ ๋‚˜์—ดํ•  ์ˆ˜ ์—†์Œ), ํด๋ž˜์Šค ์ƒํ•œ์„ ์ œ์ผ ์•ž์— ์ ์–ด์•ผ ํ•จ. ์ธํ„ฐํŽ˜์ด์Šค ์ƒํ•œ์€ ์—ฌ๋Ÿฌ ๊ฐœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, & ๊ธฐํ˜ธ๋กœ ์—ฐ๊ฒฐํ•จ.

ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ƒํ•œ์„ ์ง€์ •ํ•˜๋ฉด ๊ทธ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉค๋ฒ„๋‚˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์ œํ•œ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง. ์˜ˆ๋ฅผ ๋“ค์–ด <T extends Number> ๋กœ ์„ ์–ธ๋œ T ๋Š” Number ์˜ ๋ฉ”์„œ๋“œ๋“ค(intValue() , doubleValue() ๋“ฑ) ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. ๋ฐ˜๋ฉด ํ•˜ํ•œ ๊ฒฝ๊ณ„(Lower Bound) ๋Š” ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ์—์„œ๋Š” ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ (์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์— super ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์—†์Œ.) ํ•˜ํ•œ์€ ์ฃผ๋กœ ์™€์ผ๋“œ์นด๋“œ์—์„œ ์‚ฌ์šฉ๋จ.(์•„๋ž˜ ์™€์ผ๋“œ ์นด๋“œ ์„น์…˜ ์ฐธ์กฐ). ์ •๋ฆฌํ•˜๋ฉด, ํƒ€์ž… ๋ณ€์ˆ˜์˜ ์ œํ•œ์—๋Š” extends ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Java ์ œ๋„ค๋ฆญ์—์„œ๋Š” ํด๋ž˜์Šค๋“  ์ธํ„ฐํŽ˜์ด์Šค๋“  ์ œํ•œ์—๋Š” ๋ชจ๋‘ extends ๋ฅผ ์“ด๋‹ค๋Š” ์ ์— ์œ ์˜ํ•ด์•ผํ•จ. (implements ๋ฅผ ์“ฐ์ง€ ์•Š์œผ๋ฉฐ, super ๋Š” ํƒ€์ž… ๋ณ€์ˆ˜ ์„ ์–ธ์—์„œ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š์Œ)

๋‹ค์Œ์€ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ƒํ•œ์„ ์ ์šฉํ•œ ํด๋ž˜์Šค ์˜ˆ์‹œ์ž„. RestrictedBox ๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ T ๋ฅผ Number ์˜ ํ•˜์œ„์ด๋ฉด์„œ Comparable<T> ๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž…์œผ๋กœ ์ œํ•œํ•˜๊ณ  ์žˆ์Œ. ๋”ฐ๋ผ์„œ T ๋Š” ์ˆซ์ž ํƒ€์ž…(Number ํ•˜์œ„) ์ด๋ฉฐ ์„œ๋กœ ๋น„๊ต ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ compareTo ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

// ๋‹ค์ค‘ ์ƒํ•œ(Bound) ์„ ๊ฐ€์ง€๋Š” ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค ์˜ˆ์‹œ
class RestricedBox<T extends Number & Comparable<T>> {
    private T value;
    public RestrictedBox(T value) {
        this.value = value;
    }
    public T getValue() {
        return value;
    }
    // ๊ฐ’๊ณผ ๋‹ค๋ฅธ T ๊ฐ’์˜ ํฌ๊ธฐ๋ฅผ ๋น„๊ตํ•˜๋Š” ๋ฉ”์„œ๋“œ (Comparable<T> ์‚ฌ์šฉ ๊ฐ€๋Šฅ)
    public int compareTo(T other) {
        return value.compareTo(other);
    }
}

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ <T extends ์ƒ์œ„ํƒ€์ž…> ํ˜•ํƒœ๋กœ ์„ ์–ธํ•˜๋ฉด T๋Š” ํ•ด๋‹น ์ƒ์œ„ํƒ€์ž…์œผ๋กœ ์ œํ•œ๋จ. ๋งŒ์•ฝ T ์— ์—ฌ๋Ÿฌ ์กฐ๊ฑด์„ ๊ฑธ๊ณ  ์‹ถ๋‹ค๋ฉด <T extends ClassA & InterfaceB & InterfaceC> ์™€ ๊ฐ™์ด ์„ ์–ธํ•จ. ์ฃผ์˜ : ์ƒํ•œ์— ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜๋งŒ ์ง€์ • ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•จ๊ป˜ ์ง€์ •ํ–ˆ๋‹ค๋ฉด ํด๋ž˜์Šค ์ƒํ•œ์„ ๋จผ์ € ๋ช…์‹œํ•ด์•ผ ํ•จ.

1.3 ์™€์ผ๋“œ์นด๋“œ(?, ? extends, ? super)

์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด, ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ธ์ž๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ , ์™€์ผ๋“œ์นด๋“œ(?) ๋กœ ํ‘œํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ. ์™€์ผ๋“œ์นด๋“œ๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ ๊ทธ ํƒ€์ž…์ด ์–ด๋–ค ํƒ€์ž…์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ƒ๊ด€ ์—†์Œ ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์šฉ๋„๋กœ, ? ๋‹จ๋…์œผ๋กœ ๋˜๋Š” extends , super ํ‚ค์›Œ๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•จ.

  • ? (๋ฌด์ œํ•œ ์™€์ผ๋“œ ์นด๋“œ) : ํŠน์ • ์ œํ•œ ์—†์ด "์–ด๋–ค ํƒ€์ž…์ด๋“  ๋  ์ˆ˜ ์žˆ๋‹ค." ๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง. ์˜ˆ๋ฅผ ๋“ค์–ด List<?> ๋Š” "์•„๋ฌด ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์ŠคํŠธ" ๋ฅผ ๋œปํ•จ. List<?> ๋Š” ์‚ฌ์‹ค์ƒ List<? extends Object> ์™€ ๋™์ผํ•จ. ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ œํ•œ ์—†์ด ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ๋กœ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ํƒ€์ž…์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ์ œ๋„ค๋ฆญ ํƒ€์ž… ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๊ฐ•์ œํ•  ํ•„์š”๊ฐ€ ์—†์„ ๋•Œ์ž„. ๋ฌด์ œํ•œ ์™€์ผ๋“œ์นด๋“œ์ผ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ ์‚ฝ์ž…ํ•  ์ˆ˜ ์—†๊ณ  (ํƒ€์ž…์„ ์•Œ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ง‰์Œ), ๊ฐ€์ ธ์˜ฌ ๋•Œ๋Š” Object ํƒ€์ž…์œผ๋กœ๋งŒ ์–ป์„ ์ˆ˜ ์žˆ์Œ.

  • ? extends T (์ƒํ•œ์ด ์žˆ๋Š” ์™€์ผ๋“œ์นด๋“œ) : ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์ธ์ž๋Š” ๋ชจ๋ฅด์ง€๋งŒ ์–ด๋–ค ํŠน์ • ํƒ€์ž… T ์˜ ํ•˜์œ„ ํƒ€์ž… ์œผ๋กœ ์ œํ•œํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•จ. ? extends T ์™€์ผ๋“œ ์นด๋“œ๋ฅผ ์‚ฌ์šฉํ•œ ์ œ๋„ค๋ฆญ ํƒ€์ž…์€ ํ•ด๋‹น ํƒ€์ž…์—์„œ ๊ฐ’์„ ๊บผ๋‚ด(read) ๋ณผ ๋•Œ ์•ˆ์ „ํ•˜๊ฒŒ T ๋กœ ์ทจ๊ธ‰ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Œ. ์˜ˆ๋ฅผ ๋“ค์–ด List<? extends Number> ๋Š” Number ์˜ ํ•˜์œ„ ํƒ€์ž…๋“ค๋กœ ๊ตฌ์„ฑ๋œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ๋ฆฌ์ŠคํŠธ์—์„œ ์š”์†Œ๋ฅผ ๊บผ๋‚ด๋ฉด ํ•ญ์ƒ Number ๋กœ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ์Œ. ๊ทธ๋Ÿฌ๋‚˜ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฆฌ์ŠคํŠธ์— ์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ๋ง‰์Œ. ์™œ๋ƒํ•˜๋ฉด List<? extends Number> ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹ค์ œ ๋ฆฌ์ŠคํŠธ๊ฐ€ List<Integer> ์ธ์ง€ List<Double> ์ธ์ง€ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์ž„์˜์˜ Number ๋ฅผ ๋„ฃ๋Š” ์ž‘์—…์€ ํƒ€์ž… ๋ถˆ์ผ์น˜ ์œ„ํ—˜์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž„. ๋”ฐ๋ผ์„œ ? extends T ๋ฅผ ์“ฐ๋ฉด ์ฝ๊ธฐ ์ „์šฉ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๊ณ , ์ถ”๊ฐ€ ์‚ฝ์ž…์€ ํ•  ์ˆ˜ ์—†์Œ.(null ์ถ”๊ฐ€ ์ •๋„๋งŒ ์˜ˆ์™ธ์ ์œผ๋กœ ํ—ˆ์šฉ๋˜์ง€๋งŒ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•˜๋ฉด ํ™œ์šฉ๋˜์ง€ ์•Š์Œ)

  • ? super T ( ํ•˜ํ•œ์ด ์žˆ๋Š” ์™€์ผ๋“œ ์นด๋“œ ) : ์–ด๋–ค ํŠน์ • ํƒ€์ž… T ์˜ ์ƒ์œ„ ํƒ€์ž… ์œผ๋กœ ์ œํ•œํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•จ. ? super T ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์‚ฌ์šฉํ•œ ์ œ๋„ค๋ฆญ ํƒ€์ž…์€ ํ•ด๋‹น ํƒ€์ž…์— ๊ฐ’์„ ์ถ”๊ฐ€(write) ํ•  ๋•Œ ์•ˆ์ „ํ•˜๊ฒŒ T ํƒ€์ž…์œผ๋กœ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค ๋Š” ํŠน์ง•์ด ์žˆ์Œ. ์˜ˆ๋ฅผ ๋“ค์–ด List<? super Integer> ๋Š” Integer ์˜ ์ƒ์œ„ ํƒ€์ž… ๋ฆฌ์ŠคํŠธ(List<Number> , List<Object> ๋“ฑ)๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ๋ฆฌ์ŠคํŠธ์— Integer ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ํƒ€์ž… ์•ˆ์ „ํ•จ. ์™œ๋ƒํ•˜๋ฉด ์‹ค์ œ ๋ฆฌ์ŠคํŠธ๊ฐ€ Number ๋‚˜ Object ํƒ€์ž…์˜ ๋ฆฌ์ŠคํŠธ๋ผ๋ฉด Integer ๋Š” ๊ทธ ํ•˜์œ„๋กœ์„œ ์ €์žฅ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž„. ํ•˜์ง€๋งŒ ๋ฐ˜๋Œ€๋กœ ๊บผ๋‚ด์˜ฌ ๋•Œ๋Š” ํƒ€์ž…์ด ๋ชจํ˜ธํ•˜๋ฏ€๋กœ Object ๋กœ๋งŒ ์–ป์„ ์ˆ˜ ์žˆ์Œ. ๋”ฐ๋ผ์„œ ? super T ๋ฅผ ์“ฐ๋ฉด ์“ฐ๊ธฐ ์ „์šฉ ๋ชฉ์ ์œผ๋กœ ํ™œ์šฉ๋˜๋ฉฐ, ์š”์†Œ๋ฅผ ์ฝ์–ด์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฆ‰์‹œ T ํƒ€์ž…์ž„์„ ๋ณด์žฅํ•˜์ง€ ๋ชปํ•จ.(ํ•„์š”ํ•˜๋‹ค๋ฉด ์บ์ŠคํŒ…์ด ํ•„์š”ํ•จ.)

์ด๋Ÿฌํ•œ ์™€์ผ๋“œ์นด๋“œ ์‚ฌ์šฉ ํŒจํ„ด์„ ์š”์•ฝํ•˜๋Š” ์œ ๋ช…ํ•œ ์›์น™์ด PECS(Producer Extends, Consumer Super) ์ž„. ์ฆ‰, ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์‚ฐ(์ œ๊ณต) ํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ? extends ๋กœ ๋ฐ›๊ณ , ์†Œ๋น„(์ถ”๊ฐ€ ์ €์žฅ) ํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ? super ๋กœ ๋ฐ›์œผ๋ผ๋Š” ๊ฐ€์ด๋“œ๋ผ์ธ์ž„. ๋งŒ์•ฝ ํ•œ ๋ณ€์ˆ˜์—์„œ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ์—ญํ• ์„ ๋ชจ๋‘ ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ ์ž์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•จ.

์™€์ผ๋“œ์นด๋“œ ํ™œ์šฉ ์š”์•ฝ :

  • List<? extends T> : T ์˜ ํ•˜์œ„ ํƒ€์ž…๋“ค์„ ๋‹ด๋Š” ๋ฆฌ์ŠคํŠธ. ์ฝ๊ธฐ ๋Š” T ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฐ€๋Šฅ, ์“ฐ๊ธฐ (์ถ”๊ฐ€)๋Š” ๋ถˆ๊ฐ€๋Šฅ.(Producer ์šฉ๋„)

  • List<? super T> : T ์˜ ์ƒ์œ„ ํƒ€์ž…๋“ค์„ ๋‹ด๋Š” ๋ฆฌ์ŠคํŠธ. ์ฝ๊ธฐ ์‹œ์—๋Š” Object ๋กœ๋งŒ ํš๋“, ์“ฐ๊ธฐ ๋Š” T (๋˜๋Š” ๊ทธ ํ•˜์œ„) ๊ฐ์ฒด ์ถ”๊ฐ€ ๊ฐ€๋Šฅ.(Comsumer ์šฉ๋„)

  • List<?> : ๋ถˆํŠน์ • ํƒ€์ž…์˜ ๋ฆฌ์ŠคํŠธ. Object ์ด์™ธ ๊ตฌ์ฒด์  ํƒ€์ž…์œผ๋กœ ์ฝ๊ธฐ ๋ถˆ๊ฐ€, ์“ฐ๊ธฐ ๋ถˆ๊ฐ€.(List<? extends Object> ์™€ ๋™์ผ)

์™€์ผ๋“œ ์นด๋“œ์˜ ๋™์ž‘ ์˜ˆ์ œ

์•„๋ž˜ ์ฝ”๋“œ์—์„œ ? extends Number ์™€ ? super Integer ๋ฆฌ์ŠคํŠธ์˜ ์ฐจ์ด๋ฅผ ๋ณด์—ฌ์คŒ.

List<Integer> intList = Arrays.asList(1, 2, 3);
List<? extends Number> numList = intList;
Number num = numList.get(0);        // OK : Number ๋กœ ์ฝ๊ธฐ
// numList.add(4);                  // ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ : extends ์™€์ผ๋“œ์นด๋“œ๋Š” ์ถ”๊ฐ€ ๋ถˆ๊ฐ€

List<Object> objList = new ArrayList<>();
List<? super Integer> superList = objList;
superList.add(100);                // OK : Integer ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
Object obj = superList.get(0);     // OK : Ojbect ๋กœ ์ฝ๊ธฐ( Integer ์ž„์„ ์•Œ ์ˆ˜ ์—†์Œ)

์œ„ ์ฝ”๋“œ์—์„œ numList ๋Š” Integer ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์•˜์ง€๋งŒ List<? extends Number> ๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— Number ๋กœ ๊ฐ’ ์ฝ๊ธฐ(get ) ๊ฐ€ ๊ฐ€๋Šฅํ•จ. ๊ทธ๋Ÿฌ๋‚˜ add ๋ฉ”์„œ๋“œ๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ์ธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Œ. ๋ฐ˜๋Œ€๋กœ superList ๋Š” Object ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค์ง€๋งŒ List<? super Integer> ํƒ€์ž…์œผ๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— Integer ๊ฐ’์„ ์ถ”๊ฐ€(add ) ํ•˜๋Š” ๊ฒƒ์€ ํ—ˆ์šฉ๋จ. ๋‹ค๋งŒ get ์œผ๋กœ ๊ฐ€์ ธ์˜จ ๊ฐ’์€ Object ํƒ€์ž…์œผ๋กœ๋งŒ ์–ป์–ด์ง. ์ด์ฒ˜๋Ÿผ ์™€์ผ๋“œ์นด๋“œ๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ๋ณด๋‹ค ์œ ์—ฐํ•˜๊ฒŒ ๋‹ค๋ฃจ๊ฒŒ ํ•ด์ฃผ์ง€๋งŒ, extends ์™€ super ์— ๋”ฐ๋ผ ์ฝ๊ธฐ/์“ฐ๊ธฐ์˜ ์ œ์•ฝ์ด ๋‹ค๋ฅด๋ฏ€๋กœ ์œ„ ์›์น™์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ.

1.4 ํƒ€์ž… ์†Œ๊ฑฐ(Type Erasure)์™€ ์ œ๋„ค๋ฆญ์˜ ํ•œ๊ณ„

Java ์˜ ์ œ๋„ค๋ฆญ์€ ์ปดํŒŒ์ผ ํƒ€์ž„ ์—๋งŒ ์œ ํšจํ•˜๊ณ  ๋Ÿฐํƒ€์ž„์—๋Š” ํƒ€์ž… ์ •๋ณด๊ฐ€ ์†Œ๊ฑฐ ๋จ. ์ด๋ฅผ ํƒ€์ž… ์†Œ๊ฑฐ(type erasure) ๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ, Java ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ œ๋„ค๋ฆญ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ปดํŒŒ์ผ ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•จ.

  • ๋ชจ๋“  ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋ณ€์ˆ˜๋“ค์„ ๊ทธ ์ƒํ•œ ๊ฒฝ๊ณ„ ํƒ€์ž…์ด๋‚˜ Object ๋กœ ๋Œ€์น˜ ํ•จ.(์ƒํ•œ ๊ฒฝ๊ณ„๊ฐ€ ์—†๋‹ค๋ฉด Object ๋กœ ์น˜ํ™˜). ์˜ˆ๋ฅผ ๋“ค์–ด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” List<String> ๊ณผ List<Integer> ๋ฅผ ๋‘˜ ๋‹ค ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋‹จ์ˆœํ•œ List (ํ˜น์€ List<Object> ) ๋กœ ๊ฐ„์ฃผํ•จ.

  • ์ œ๋„ค๋ฆญ์œผ๋กœ ์ธํ•ด ํ•„์š”ํ•ด์ง„ ํƒ€์ž… ์บ์ŠคํŒ… ์ฝ”๋“œ๋ฅผ ์ ์ ˆํžˆ ์‚ฝ์ž…ํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์œ ์ง€ํ•จ.

  • ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์ƒ์†ํ•˜์—ฌ ํ•˜์œ„์—์„œ ํ˜•๋ณ€ํ™˜๋˜๋Š” ๊ฒฝ์šฐ bridge method ๋“ฑ์„ ์ƒ์„ฑํ•˜์—ฌ ๋‹คํ˜•์„ฑ์ด ์ œ๋Œ€๋กœ ์œ ์ง€๋˜๋„๋ก ํ•จ.

๊ทธ ๊ฒฐ๊ณผ ๋ฐ”์ดํŠธ์ฝ”๋“œ์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๊ฐ€ ๋“ค์–ด๊ฐ€์ง€ ์•Š์œผ๋ฉฐ , ๋Ÿฐํƒ€์ž„์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ธ์ž์— ๋”ฐ๋ฅธ ๋ณ„๋„์˜ ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์Œ. ๋”ฐ๋ผ์„œ ์ œ๋„ค๋ฆญ ์ž์ฒด๋กœ ์ธํ•œ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Œ . ์ด๋Š” C++์˜ ํ…œํ”Œ๋ฆฟ๊ณผ ๋‹ฌ๋ฆฌ, Java ์˜ ์ œ๋„ค๋ฆญ์€ ์ปดํŒŒ์ผ ์‹œ์—๋งŒ ๋™์ž‘ํ•˜๊ณ  ๋Ÿฐํƒ€์ž„์— ์˜ํ–ฅ์ด ์—†๋‹ค๋Š” ์ค‘์š”ํ•œ ํŠน์ง•์ž„.

ํ•˜์ง€๋งŒ ํƒ€์ž… ์†Œ๊ฑฐ๋กœ ์ธํ•ด ๋ช‡ ๊ฐ€์ง€ ์ œ์•ฝ์‚ฌํ•ญ๊ณผ ์ฃผ์˜์  ์ด ์ƒ๊น€.

  • instanceof ์™€ ์บ์ŠคํŒ…์˜ ์ œํ•œ : ๋Ÿฐํƒ€์ž„์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ธ์ž ์ •๋ณด๊ฐ€ ์ง€์›Œ์ง€๋ฏ€๋กœ, ํŠน์ • ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ์˜ instanceof ๊ฒ€์‚ฌ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด obj instanceof List<String> ์™€ ๊ฐ™์€ ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ ์˜ค๋ฅ˜์ž„. ์ด๋Š” JVM ์ด ๋Ÿฐํƒ€์ž„์— List<String> ๊ณผ List<Integer> ๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž„. ์‹ค์ œ๋กœ new ArrayList<String>() ๋กœ ๋งŒ๋“  ๋ฆฌ์ŠคํŠธ์™€ new ArrayList<Integer>() ๋กœ ๋งŒ๋“  ๋ฆฌ์ŠคํŠธ์˜ ํด๋ž˜์Šคํƒ€์ž…์„ ์ถœ๋ ฅํ•ด๋ณด๋ฉด ๋‘˜ ๋‹ค java.util.ArrayList ๋กœ ๋‚˜ํƒ€๋‚จ. ์˜ˆ๋ฅผ ๋“ค์–ด:

List<String> listA = new ArrayList<>();
List<Integer> listB = new ArrayList<>();
System.out.println(listA.getClass() == listB.getClass()); // true(๋‘˜๋‹ค ArrayList)

์œ„ ๊ฒฐ๊ณผ์—์„œ ๋‘ ๋ฆฌ์ŠคํŠธ์˜ ํด๋ž˜์Šค๊ฐ€ ๋™์ผ(ture ) ํ•จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ. ์ฆ‰, ๋Ÿฐํƒ€์ž„์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ธ์ž์˜ ๊ตฌ๋ถ„์ด ์—†๋Š” ๊ฒƒ์ž„. ๋”ฐ๋ผ์„œ, instanceof ArrayList<String> ๊ฐ™์€ ์ฝ”๋“œ๋Š” ์˜๋ฏธ๊ฐ€ ์—†์œผ๋ฉฐ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ด๋ฅผ ๊ธˆ์ง€ํ•จ. instanceof ๋Š” ์˜ค์ง ์›์‹œ(raw) ํƒ€์ž…์ด๋‚˜ ํ•œ์ •๋˜์ง€ ์•Š์€ ์™€์ผ๋“œ์นด๋“œ(ArrayList<?> ) ๋“ฑ์— ๋Œ€ํ•ด์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

  • ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ๋ฐฐ์—ด ์ƒ์„ฑ ๋ถˆ๊ฐ€ : ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๋Š” ๋Ÿฐํƒ€์ž„์— ์†Œ๊ฑฐ๋˜๋ฏ€๋กœ, ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ๋ฐฐ์—ด ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Œ. ์˜ˆ๋ฅผ ๋“ค์–ด List<String>[] array = new List<String>[10]; ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋„ ์ปดํŒŒ์ผ ์‹œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•จ. ์ด๋Š” ๋ฐฐ์—ด์ด ๋Ÿฐํƒ€์ž„์— ์ž์‹ ์ด ๋‹ด๋Š” ์›์†Œ์˜ ํƒ€์ž…์„ ํ™•์ธํ•˜๋Š” ํŠน์ง•(๊ณต๋ณ€์„ฑ) ์ด ์žˆ๋Š”๋ฐ, ์ œ๋‹ˆ๋ฆญ ํƒ€์ž…์˜ ๋ฐฐ์—ด์˜ ๊ฒฝ์šฐ ์ดใ…๋ฅผ ๊ฒ€์‚ฌํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž„. ๋งŒ์•ฝ ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด์ด ํ—ˆ์šฉ๋œ๋‹ค๋ฉด, ๋ฐฐ์—ด์˜ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ด ์ƒ๊ฒจ๋„ ๋Ÿฐํƒ€์ž„์— ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ๋ชปํ•˜๊ณ  ์ž˜๋ชป๋œ ์บ์ŠคํŒ… ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ. ์ด๋Ÿฌํ•œ ์ด์œ ๋กœ Java ์—์„œ๋Š” ๋น„๊ฒ€์ฆ(unchecked) ์บ์ŠคํŠธ ๊ฒฝ๊ณ  ๋ฅผ ๊ฐ์ˆ˜ํ•˜๊ณ  Object ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•œ ๋’ค ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ์บ์ŠคํŒ…ํ•˜๋Š” ์šฐํšŒ ๋ฐฉ๋ฒ•์„ ์“ฐ์ง€ ์•Š๋Š” ํ•œ, ์ง์ ‘์ ์ธ ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด ์ƒ์„ฑ์€ ๊ธˆ์ง€๋จ.

  • ๊ธฐํƒ€ ์ œํ•œ : ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ์ •๋ณด๊ฐ€ ์†Œ๊ฑฐ๋˜๋ฏ€๋กœ, ํด๋ž˜์Šค์˜ static ํ•„๋“œ์—๋Š” ํƒ€์ž… ๋ณ€์ˆ˜ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅ ํ•จ. static ํ•„๋“œ๋Š” ํด๋ž˜์Šค ์ˆ˜์ค€์—์„œ ๋‹จ ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๋Š”๋ฐ, ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ธ์Šคํ„ด์Šค๋ณ„๋กœ ๋‹ฌ๋ฆฌ์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ชจ์ˆœ์ด ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์ž„. ๋˜ํ•œ ์˜ˆ์™ธ ํด๋ž˜์Šค(Throwable ํ•˜์œ„)์— ์ œ๋„ค๋ฆญ์„ ์ ์šฉ ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ throws ์ ˆ์— ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ catch ์ ˆ์— ํƒ€์ž… ๋ณ€์ˆ˜๋กœ ์˜ˆ์™ธ๋ฅผ ์žก๋Š” ๊ฒƒ ๋„ ์ œํ•œ๋จ. ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋กœ๋”ฉ ์‹œ์—๋„ ํƒ€์ž… ์†Œ๊ฑฐ ๊ฒฐ๊ณผ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ๊ฐ™์•„์ง€๋Š” ๊ฒฝ์šฐ ์˜ค๋ฒ„๋กœ๋”ฉ์ด ์„ฑ๋ฆฝ๋˜์ง€ ์•Š์Œ.( ์˜ˆ๋ฅผ ๋“ค์–ด, void method(List<String> x) ์™€ void method(List<Integer> x) ๋Š” ๋‘˜ ๋‹ค void method(List x) ๋กœ ์†Œ๊ฑฐ๋˜๋ฏ€๋กœ ๋™์‹œ์— ์ •์˜ํ•  ์ˆ˜ ์—†์Œ).

์š”์•ฝํ•˜๋ฉด, Java ์˜ ์ œ๋„ค๋ฆญ์€ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ฐ•ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ํ•ด์ฃผ๋Š” ๋ฌธ๋ฒ•์ ์ธ ์žฅ์น˜์ด๋ฉฐ, ๋Ÿฐํƒ€์ž„์—๋Š” ๋ชจ๋“  ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด ์›์‹œ ํƒ€์ž…(raw type) ์œผ๋กœ ์ทจ๊ธ‰ ๋จ. ์ด๋Ÿฌํ•œ ๊ตฌํ˜„์œผ๋กœ ์„ฑ๋Šฅ์ƒ ์ด์ ์ด ์žˆ์ง€๋งŒ, ์œ„์™€ ๊ฐ™์€ ํ•˜๊ณ„์— ์œ ์˜ํ•ด์•„ ํ•จ. ํŠนํžˆ instanceof ๋‚˜ ๋ฐฐ์—ด ์ƒ์„ฑ ์‹œ์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•ด์•ผ ํ•จ.

List<String> list = new ArrayList<>();
// if (list instanceof ArrayList<String>) { ... }  // ์ปดํŒŒ์ผ ์˜ค๋ฅ˜: ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ instanceof ๋ถˆ๊ฐ€

// List<String>[] listArray = new List<String>[5]; // ์ปดํŒŒ์ผ ์˜ค๋ฅ˜: ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด ์ƒ์„ฑ ๋ถˆ๊ฐ€

// (์ฃผ์˜) ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ๋Ÿฐํƒ€์ž„ ํƒ€์ž… ํ™•์ธ์€ ๋ถˆ๊ฐ€๋Šฅ 
System.out.println(list.getClass());            // ์ถœ๋ ฅ ์˜ˆ: class java.util.ArrayList  (ํƒ€์ž… ์ธ์ž ๋ถˆ๋ช…)

์œ„ ์ฝ”๋“œ์—์„œ ๋ณด๋“ฏ์ด, instanceof ArrayList<String> ๊ฐ™์€ ๊ฒ€์‚ฌ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด ์ƒ์„ฑ๋„ ์ปดํŒŒ์ผ์ด ๋ง‰์Œ. ๋งˆ์ง€๋ง‰ ์ถœ๋ ฅ ๊ฒฐ๊ณผ์—์„œ list ์˜ ์‹ค์ œ ํด๋ž˜์Šค ํƒ€์ž…์€ ArrayList ๋กœ๋งŒ ๋‚˜ํƒ€๋‚˜๊ณ , <String> ์ •๋ณด๋Š” ํ™•์ธํ•  ์ˆ˜ ์—†์Œ. ์ด์ฒ˜๋Ÿผ ์ œ๋„ค๋ฆญ์€ ์˜ค๋กœ์ง€ ์ปดํŒŒ์ผ ์‹œ์ ์˜ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์œ„ํ•œ ๋„๊ตฌ ์ด๋ฉฐ, ๋Ÿฐํƒ€์ž„์—๋Š” ํƒ€์ž…์ด ์ง€์›Œ์ง„๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ดํ•ดํ•ด์•ผํ•จ.(ํ•„์š”ํ•˜๋‹ค๋ฉด ๋ฆฌํ”Œ๋ ‰์…˜ ๋“ฑ์˜ ๊ธฐ๋ฒ•์œผ๋กœ ์ผ๋ถ€ ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด (Class<T> ์ธ์ˆ˜ ๋“ฑ) ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ผ๋ฐ˜์ ์ธ ์ƒํ™ฉ์—์„œ๋Š” ํƒ€์ž… ์†Œ๊ฑฐ๋กœ ์ธํ•ด ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ธ์ž๋Š” ๋Ÿฐํƒ€์ž„์— ํ™œ์šฉ๋˜์ง€ ์•Š์Œ.)

2. ์—ด๊ฑฐํ˜•(Enum)

2.1 ๊ธฐ๋ณธ ๋ฌธ๋ฒ•๊ณผ ์‚ฌ์šฉ ์˜ˆ

Java ์˜ ์—ด๊ฑฐํ˜•(enum) ์€ ๋ช‡ ๊ฐ€์ง€ ์ƒ์ˆ˜๋“ค์˜ ์ง‘ํ•ฉ ์„ ํ•˜๋‚˜์˜ ํƒ€์ž…์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ํŠน๋ณ„ํ•œ ํด๋ž˜์Šค์ž„. enum ์€ ํด๋ž˜์Šค์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ •์˜ํ•˜์ง€๋งŒ, ๋ฏธ๋ฆฌ ์ •ํ•ด์ง„ ์—ฌ๋Ÿฌ ์ƒ์ˆ˜(constants) ๋ฅผ ๋‚˜์—ดํ•˜์—ฌ ๊ทธ ๊ฐ’๋“ค๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ํ•จ. ์„ ์–ธ ๋ฌธ๋ฒ•์€ enum ์—ด๊ฑฐํ˜• ์ด๋ฆ„ { ์ƒ์ˆ˜1, ์ƒ์ˆ˜2, ... } ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด ์š”์ผ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์—ด๊ฑฐํ˜•์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•  ์ˆ˜ ์žˆ์Œ.

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

์ด๋ ‡๊ฒŒ ์—ด๊ฑฐ๋œ ์ด๋ฆ„๋“ค์ด Day enum ํƒ€์ž…์˜ ์ƒ์ˆ˜ ๋“ค์ด๋ฉฐ, ๊ฐ๊ฐ Day.SUNDAY , Day.MONDAY ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

์‚ฌ์‹ค enum ์œผ๋กœ ์„ ์–ธ๋œ ๊ฐ ์ƒ์ˆ˜๋Š” ํ•ด๋‹น enum ํƒ€์ž…์˜ public static final ๊ฐ์ฒด ๋กœ ๊ฐ„์ฃผ๋จ. Enum ํƒ€์ž…์€ ๋‚ด๋ถ€์ ์œผ๋กœ java.lang.Enum ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•  ์ˆ˜๋Š” ์—†์Œ.(์ž๋ฐ” ์–ธ์–ด์—์„œ ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ด๋ฏธ Enum ์„ ์ƒ์†ํ•œ ์—ด๊ฑฐํ˜•์€ ์ถ”๊ฐ€ ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•จ.) ๋Œ€์‹  ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ํ•„๋“œ, ๋ฉ”์„œ๋“œ, ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์–ด์„œ, ๋‹จ์ˆœํ•œ ์ƒ์ˆ˜ ๋ชจ์Œ ์ด์ƒ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•จ.

์ปดํŒŒ์ผ๋Ÿฌ๋Š” enum์„ ์ปดํŒŒ์ผํ•  ๋•Œ ๋ช‡ ๊ฐ€์ง€ ํŽธ์˜ ๊ธฐ๋Šฅ์„ ์ž๋™์œผ๋กœ ์ œ๊ณตํ•จ. ๊ทธ ์ค‘ ์ž์ฃผ ์“ฐ์ด๋Š” ๊ฒƒ์ด values() ๋ฉ”์„œ๋“œ ์ž„. ๋ชจ๋“  enum ํƒ€์ž…์€ ๋ชจ๋“  ์ƒ์ˆ˜๋ฅผ ๋‹ด์€ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” static T[] values() ๋ฉ”์„œ๋“œ ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์ƒ์ˆ˜ ์„ ์–ธ ์ˆœ์„œ์— ๋”ฐ๋ผ ๋ฐฐ์—ด์— ๋‹ด์•„ ๋Œ๋ ค์คŒ. ์ด๋ฅผ ํ†ตํ•ด ์—ด๊ฑฐํ˜•์˜ ๋ชจ๋“  ๊ฐ’๋“ค์„ ์ˆœํšŒ(iterate) ํ•  ์ˆ˜ ์žˆ์Œ. ๋˜ํ•œ valueOf(String name) ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•˜์—ฌ, ํ•ด๋‹น enum ํƒ€์ž…์—์„œ ์ฃผ์–ด์ง„ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋Š” ์ƒ์ˆ˜ ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์คŒ. ์˜ˆ๋ฅผ ๋“ค์–ด Day.valueOf("MONDAY") ๋Š” Day.MONDAY ์ƒ์ˆ˜๋ฅผ ๋Œ๋ ค์คŒ. ์ด๋•Œ ์ธ์ž๋กœ ์ „๋‹ฌํ•œ ๋ฌธ์ž์—ด๊ณผ ๋™์ผํ•œ ์ด๋ฆ„์˜ ์ƒ์ˆ˜๊ฐ€ ์—†๋‹ค๋ฉด IllegalArgumentException ์ด ๋ฐœ์ƒํ•จ.

๊ทธ ์™ธ์—๋„, ๊ฐ enum ์ƒ์ˆ˜๋Š” ordinal() ๋ฉ”์„œ๋“œ ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋Š” ํ•ด๋‹น ์ƒ์ˆ˜๊ฐ€ ์—ด๊ฑฐํ˜• ์„ ์–ธ์—์„œ ์ •์˜๋œ ์ˆœ์„œ index ๋ฅผ ์˜๋ฏธํ•˜๋Š” ์ •์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด Day.SUNDAY.ordinal() ์ด 0, Day.MONDAY.ordinal() ์ด 1 ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‹์ž„. ( ์ฒซ ์ƒ์ˆ˜์˜ ordinal ์ด 0๋ถ€ํ„ฐ ์‹œ์ž‘). ์ด ordinal ๊ฐ’์€ ์ƒ์ˆ˜์˜ ์ˆœ์„œ๋ฅผ ๋‚˜ํƒ€๋‚ด์ง€๋งŒ, ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜์˜ ์ˆœ์„œ๋Š” ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ordinal ๊ฐ’์„ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Œ . ๋Œ€์‹  ์ƒ์ˆ˜์˜ ๊ณ ์œ ํ•œ ์˜๋ฏธ๊ฐ€ ํ•„์š”ํ•˜๋ฉด ๋ณ„๋„์˜ ๊ฐ’์„ ํ•„๋“œ๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ. ๋งˆ์ง€๋ง‰์œผ๋กœ name() ๋ฉ”์„œ๋“œ๋Š” ์ƒ์ˆ˜ ์„ ์–ธ๋ช…์„ ๊ทธ๋Œ€๋กœ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•จ. ์ด ๊ฐ’์€ ์—ด๊ฑฐํ˜• ์„ ์–ธ์—์„œ์˜ ์ด๋ฆ„๊ณผ ์ •ํ™•ํ•˜๊ฒŒ ์ผ์น˜ํ•˜๋ฉฐ, ๊ธฐ๋ณธ์ ์œผ๋กœ toString() ๋ฉ”์„œ๋“œ๋„ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ ํ•„์š”์— ๋”ฐ๋ผ toString() ์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์ถœ๋ ฅ์šฉ์œผ๋กœ ๋‹ค๋ฅธ ๋ฌธ์ž์—ด์„ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์Œ.

์˜ˆ์‹œ์ฝ”๋“œ

๊ฐ„๋‹จํ•œ ๋ ˆ๋ฒจ(Level) ์—ด๊ฑฐํ˜•์„ ์ •์˜ํ•˜๊ณ , ์ œ๊ณต๋˜๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ํ™œ์šฉํ•œ ์˜ˆ์ž„.

enum Level { LOW, MEDIUM, HIGH }

for(Level lv : Level.values()) {
    System.out.println(lv + " - ordinal: " + lv.ordinal());
}

Level selected = Level.valueOf("HIGH");
System.out.println("Name: " + selected.name());

์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ:

LOW - ordinal: 0
MEDIUM - ordinal: 1
HIGH - ordinal: 2
Name: HIGH

์œ„ ์˜ˆ์—์„œ Level.values() ๋ฅผ ํ†ตํ•ด [LOW, MEDIUM, HIGH] ์ˆœ์„œ์˜ ์ƒ์ˆ˜ ๋ชฉ๋ก์„ ์–ป์–ด for-each ๋กœ ์ˆœํšŒํ–ˆ๊ณ , ๊ฐ ์ƒ์ˆ˜์˜ ์ด๋ฆ„๊ณผ ordinal() ๊ฐ’์„ ์ถœ๋ ฅํ–ˆ์Œ. ๊ทธ ๋‹ค์Œ Level.valueOf("HIGH") ๋ฅผ ์ด์šฉํ•ด ๋ฌธ์ž์—ด "HIGH" ์— ๋Œ€์‘๋˜๋Š” ์ƒ์ˆ˜๋ฅผ ์–ป์–ด๋‚ด์–ด, ๊ทธ name() ์„ ์ถœ๋ ฅํ–ˆ์Œ

  • values() : ๋ชจ๋“  ์ƒ์ˆ˜ ๋ฅผ ์ •์˜ ์ˆœ์„œ๋Œ€๋กœ ๋‹ด์€ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜

  • valueOf(String) : ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋Š” ์ƒ์ˆ˜ ๋ฅผ ๋ฐ˜ํ™˜.(๋Œ€์†Œ๋ฌธ์ž ์ •ํ™•ํžˆ ์ผ์น˜ํ•ด์•ผ ํ•˜๋ฉฐ, ์—†์œผ๋ฉด ์˜ˆ์™ธ)

  • ordinal() : ์ƒ์ˆ˜์˜ ์ˆœ์„œ ์ธ๋ฑ์Šค (0๋ถ€ํ„ฐ ์‹œ์ž‘) ๋ฅผ ๋ฐ˜ํ™˜.

  • name() : ์ƒ์ˆ˜์˜ ์ด๋ฆ„ ๋ฌธ์ž์—ด ์„ ๋ฐ˜ํ™˜. (์ฃผ๋กœ ๋””๋ฒ„๊น…์ด๋‚˜ ์ €์žฅ์šฉ์œผ๋กœ ์‚ฌ์šฉ, ํ•„์š”์‹œ toString() ์˜ค๋ฒ„๋ผ์ด๋“œ ๊ฐ€๋Šฅ)

์ด ์™ธ์—๋„ enum ์€ Enum ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ์ธ compareTo() (์ •์˜ ์ˆœ์„œ ๋น„๊ต)๋‚˜ equals() , hashcode() ๋“ฑ์ด ๊ธฐ๋ณธ ์ œ๊ณต๋˜๋ฉฐ, switch ๋ฌธ์—์„œ๋„ ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋ฅผ case ๋ ˆ์ด๋ธ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ํŽธ์˜๊ฐ€ ์žˆ์Œ.

2.2 ์ƒ์ˆ˜๋ณ„ ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ( ์ „๋žต ํŒจํ„ด ์‘์šฉ)

Java ์˜ ์—ด๊ฑฐํ˜•์€ ๊ฐ ์ƒ์ˆ˜๋งˆ๋‹ค ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋™์ž‘์„ ๊ตฌํ˜„ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ. ์‚ฌ์‹ค ์—ด๊ฑฐํ˜•์€ ํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด๋ถ€์— ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ enum ์ƒ์ˆ˜๋Š” ํ•ด๋‹น enum ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ์ด๋ฏ€๋กœ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ƒ์ˆ˜๋ณ„๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•  ์ˆ˜ ์žˆ์Œ. ์ด๋ฅผ ํ™œ์šฉํ•˜๋ฉด ํ•˜๋‚˜์˜ enum ์ƒ์ˆ˜๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ํ–‰๋™ ๊ทœ์น™์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ํŒจํ„ด์€ ํ”ํžˆ ์ „๋žต ํŒจํ„ด(Strategy Pattern) ์„ ์—ด๊ฑฐํ˜•์œผ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ๊ณผ ์œ ์‚ฌํ•จ.

์ƒ์ˆ˜๋ณ„๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ ์„ ์–ธ ํ›„ ์ƒ์ˆ˜๋ณ„ ๊ตฌํ˜„ ์ œ๊ณต ์„ ๋งŽ์ด ์‚ฌ์šฉํ•จ. ์ฆ‰, enum ํด๋ž˜์Šค ์•ˆ์— ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๊ณ , ๊ฐ ์ƒ์ˆ˜๊ฐ€ ๊ทธ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌ์ฒด์ ์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž„. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด enum ์ƒ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์ƒˆ๋กœ์šด ๋™์ž‘์„ ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๊ณ , ๋ณ„๋„์˜ switch ๋ฌธ์ด๋‚˜ ๋ถ„๊ธฐ ์—†์ด ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ. ์•„๋ž˜๋Š” ๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ๊ธฐ ์—ฐ์‚ฐ์„ enum ์œผ๋กœ ๊ตฌํ˜„ํ•œ ์˜ˆ์‹œ์ž„. Operation ์—ด๊ฑฐํ˜•์€ ์‚ฌ์น™์—ฐ์‚ฐ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ƒ์ˆ˜๋“ค์„ ๊ฐ€์ง€๋ฉฐ, ์ถ”์ƒ ๋ฉ”์„œ๋“œ apply ๋ฅผ ์„ ์–ธํ•˜๊ณ  ๊ฐ ์ƒ์ˆ˜๋งˆ๋‹ค ์ด๋ฅผ ๊ตฌํ˜„ํ•จ.

enum Operation {
    PLUS {
        @Override
        public int apply(int x, int y) { return x + y; }
    },
    MINUS {
        @Override
        public int apply(int x, int y) { return x - y; }
    }
    MULTIPLY {
        @Override
        public int apply(int x, int y) { return x * y; }
    }
    DIVIDE {
        @Override
        public int apply(int x, int y) { return x / y; }
    }
    
    public abstract int apply(int x, int y);
}

// ์‚ฌ์šฉ ์˜ˆ
System.out.println(Operation.PLUS,apply(3,4)); // result : 7
System.out.println(Operation.DIVIDE.apply(8,2)); // result : 4

์œ„ ์ฝ”๋“œ์—์„œ Operation enum ์€ apply(int, int) ๋ผ๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๊ฐ ์ƒ์ˆ˜(PLUS, MINUS, MULTIPLY, DIVIDE) ๊ฐ€ ์ž์‹ ๋งŒ์˜ ๋ฐฉ์‹์œผ๋กœ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์Œ. Operation.PLUS.apply(3,4) ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ PLUS ์ƒ์ˆ˜์— ๊ตฌํ˜„๋œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ 3 + 4 ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , Operation.DIVIDE.apply(8,2) ๋Š” DIVIDE ์ƒ์ˆ˜์˜ ๊ตฌํ˜„์„ ์‹คํ–‰ํ•จ. ์ด์ฒ˜๋Ÿผ ๊ฐ ์ƒ์ˆ˜๊ฐ€ ๋…๋ฆฝ์ ์ธ ๋กœ์ง์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ƒˆ๋กœ์šด ์—ฐ์‚ฐ์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด enum ์— ์ƒ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ•ด๋‹น ์ƒ์ˆ˜์— ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋จ. ๋ณ„๋„์˜ ์กฐ๊ฑด๋ถ„๊ธฐ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด๋„ ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์—ด๊ฑฐํ˜• ์ž์ฒด๊ฐ€ ์—ฐ์‚ฐ ์ง‘ํ•ฉ๊ณผ ๋™์ž‘์„ ์บก์Аํ™”ํ•˜๋ฏ€๋กœ ์ฝ”๋“œ๊ฐ€ ๊น”๋”ํ•ด์ง. ์ด๊ฒƒ์€ ์ผ์ข…์˜ enum ์„ ์‚ฌ์šฉํ•œ ์ „๋žต ํŒจํ„ด ๊ตฌํ˜„์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋Œ€ํ‘œ์ ์ธ ํ™œ์šฉ ์‚ฌ๋ก€์ž„. (Java API ์—์„œ๋„ java.math.RoundingMode ์˜ ๊ฐ ์ƒ์ˆ˜๊ฐ€ round ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋“ฑ ์œ ์‚ฌํ•œ ๊ธฐ๋ฒ•์ด ํ™œ์šฉ๋˜์–ด ์žˆ์Œ)

๋งŒ์•ฝ enum ์—์„œ ๊ณตํ†ต ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ ์ƒ์ˆ˜๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ผญ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๋จ. ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ , ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ๋„ฃ์€ ๋’ค ํŠน์ • ์ƒ์ˆ˜์—์„œ๋งŒ ์ด๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•  ์ˆ˜๋„ ์žˆ์Œ. ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์œ„์ฒ˜๋Ÿผ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๋Š” ํŒจํ„ด์ด ๋งŽ์ด ์“ฐ์ž„. ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ ๋•๋ถ„์— ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜ ๊ฐ๊ฐ์ด ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ  , ๊ด€๋ จ๋œ ์ƒํƒœ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Œ.

2.3 ์—ด๊ฑฐํ˜•์˜ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„

์—ด๊ฑฐํ˜•์€ ๋‚ด๋ถ€์ ์œผ๋กœ Enum ์„ ํ™•์žฅํ•œ ํด๋ž˜์Šค ์ด๋ฏ€๋กœ, ๋‹ค๋ฅธ ์ผ๋ฐ˜ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„(implements) ํ•  ์ˆ˜๋„ ์žˆ์Œ. ์—ด๊ฑฐํ˜•์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด, ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์œผ๋กœ ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์–ด ๋‹คํ˜•์„ฑ์ด ์ฆ๊ฐ€ํ•˜๊ณ , ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋“ค์—๊ฒŒ ํŠน์ • ํ–‰์œ„๋ฅผ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Œ. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” enum ์€ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด ๊ตฌํ˜„์„ ๊ฐ ์ƒ์ˆ˜๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๊ณตํ†ต๋˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ์Œ. ์ƒ์ˆ˜๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ํ•˜๋ ค๋ฉด ์•ž์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ enum ๋‚ด์— ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๊ฑฐ๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”์ƒ ๋ฉ”์„œ๋“œํ™”ํ•˜์—ฌ ๊ฐ ์ƒ์ˆ˜๊ฐ€ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉด ๋จ.

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ„๋‹จํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ enum ์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ด„. ๋‹ค์Œ ์ฝ”๋“œ๋Š” Greeting ์ด๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ , GreetingType ์—ด๊ฑฐํ˜•์ด ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ์‚ฌ๋ก€์ž„. ๊ฐ ์ƒ์ˆ˜๋Š” greet() ๋ฉ”์„œ๋“œ๋ฅผ ์ž๊ธฐ๋งŒ์˜ ๋ฐฉ์‹์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ณ  ์žˆ์Œ.

interface Greeting {
    void greet();
}

enum GreetingType implements Greeting {
    HELLO {
        @Override
        public void greet() {
            System.out.println("Hello!");
        }
    },
    GOODBYE {
        @Override
        public void greet() {
            System.out.println("Goodbye!");
        }
    }
}

// ์‚ฌ์šฉ ์˜ˆ
Greeting hello = GreetingType.HELLO;
hello.greet();        // result : Hello
GreetingType.GOODBYE.greet(); // result Goodbye!

์œ„์—์„œ GreetingType ์—ด๊ฑฐํ˜•์€ Greeting ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ์œผ๋ฏ€๋กœ, GreetingType ์˜ ๋ชจ๋“  ์ƒ์ˆ˜๋Š” Greeting ํƒ€์ž…์œผ๋กœ ์ทจ๊ธ‰๋  ์ˆ˜ ์žˆ์Œ. HELLO ์™€ GOODBYE ์ƒ์ˆ˜ ๊ฐ๊ฐ์ด greet() ๋ฉ”์„œ๋“œ์˜ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์—ฌ, ํ˜ธ์ถœ ์‹œ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•จ. ์ด์ฒ˜๋Ÿผ ์—ด๊ฑฐํ˜•์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๊ฐ ์ƒ์ˆ˜๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋กœ ํ™œ์šฉ ํ•  ์ˆ˜ ์žˆ์Œ. ์˜ˆ๋ฅผ ๋“ค์–ด ์ธ์ž๋กœ Greeting ํƒ€์ž…์„ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์— GreetingType.HELLO ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋Š” ๋‹คํ˜•์ ์œผ๋กœ ๋™์ž‘ํ•จ.

์—ด๊ฑฐํ˜•์€ ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Œ. ์ฐธ๊ณ ๋กœ, Java ์˜ ๋ชจ๋“  enum ์€ ์ปดํŒŒ์ผ ์‹œ ์ž๋™์œผ๋กœ java.lang.Enum ์„ ์ƒ์†ํ•˜๊ณ  java.lang.Comparable ๊ณผ java.io.Serializable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ๋˜์–ด ์žˆ์Œ. ๋”ฐ๋ผ์„œ enum ๊ฐ„ ๋น„๊ต๋‚˜ ์ง๋ ฌํ™” ๋“ฑ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ถ”๊ฐ€๋กœ ๊ฐœ๋ฐœ์ž๊ฐ€ ์›ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Œ. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด enum ์ƒ์ˆ˜์˜ ํ–‰๋™์„ ์ถ”์ƒํ™”ํ•˜๋ฉด, enum ์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์ž…์žฅ์—์„œ ๊ตฌํ˜„์„ ๋ชฐ๋ผ๋„ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ผ๊ด€๋œ ๋™์ž‘์„ ์ด๋Œ์–ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ด์ ๋„ ์žˆ์Œ.

2.4 EnumSet ๊ณผ EnumMap

Java Collections Framework ๋Š” ์—ด๊ฑฐํ˜•๊ณผ ํ•จ๊ป˜ ์“ฐ๊ธฐ์— ์ตœ์ ํ™”๋œ ์ปฌ๋ ‰์…˜ ๊ตฌํ˜„์ฒด๋กœ EnumSet ๊ณผ EnumMap ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•จ. ์ด๋“ค์€ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์—ด๊ฑฐํ˜•์— ํŠนํ™”ํ•˜์—ฌ, ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์„ฑ๋Šฅ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ž„. ์—ด๊ฑฐํ˜• ํƒ€์ž… ์ „์šฉ ์ด๋ผ๋Š” ์ œ์•ฝ์ด ์žˆ์ง€๋งŒ, ๊ทธ๋งŒํผ ์ผ๋ฐ˜์ ์ธ Set ์ด๋‚˜ Map ๊ตฌํ˜„๋ณด๋‹ค ๋›ฐ์–ด๋‚œ ์ตœ์ ํ™”๊ฐ€ ์ด๋ฃจ์–ด์ ธ ์žˆ์Œ.

  • EnumSet :

    EnumSet<E extends Enum<E>> ์€ ํŠน์ • ์—ด๊ฑฐํ˜• ํƒ€์ž…์˜ ๊ฐ’๋งŒ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ์ง‘ํ•ฉ(Set) ๊ตฌํ˜„์ฒด์ž„. ๋ชจ๋“  ์›์†Œ๊ฐ€ ๋™์ผํ•œ enum ํƒ€์ž…์ด์–ด์•ผ ํ•˜๋ฉฐ, ๋‚ด๋ถ€์ ์œผ๋กœ ๋น„ํŠธ ๋ฒกํ„ฐ(bit vector) ๋กœ ์›์†Œ๋“ค์„ ๊ด€๋ฆฌํ•จ. ๊ฐ ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜์— ํ•˜๋‚˜์˜ ๋น„ํŠธ๊ฐ€ ๋Œ€์‘๋˜๋ฉฐ, ์ƒ์ˆ˜๊ฐ€ EnumSet ์— ํฌํ•จ๋˜๋ฉด ๊ทธ ๋น„ํŠธ๊ฐ€ 1๋กœ ์„ค์ •๋˜๋Š” ์‹์˜ ๋งค์šฐ ์ปดํŒฉํŠธํ•œ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•จ. ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ ๋•๋ถ„์— ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„ ์„ ํšจ์œจ์ ์œผ๋กœ ์“ฐ๊ณ  ์—ฐ์‚ฐ ์†๋„๋„ ๋งค์šฐ ๋น ๋ฆ„ . ๋น„ํŠธ ์—ฐ์‚ฐ์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ํ•ฉ์ง‘ํ•ฉ, ๊ต์ง‘ํ•ฉ ๋“ฑ์˜ ์ง‘ํ•ฉ ์—ฐ์‚ฐ๋„ ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰๋˜๋ฉฐ, ์›์†Œ์˜ ์กด์žฌ ์—ฌ๋ถ€ ์ฒดํฌ, ์ถ”๊ฐ€/์‚ญ์ œ ๋“ฑ์ด ์ƒ์ˆ˜ ์‹œ๊ฐ„ O(1) ์— ๊ฐ€๋Šฅํ•จ. EnumSet ์€ ์ „ํ†ต์ ์ธ ์ •์ˆ˜ ๋น„ํŠธ ๋งˆ์Šคํฌ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ํƒ€์ž… ์•ˆ์ „ํ•œ ๋Œ€์•ˆ ์œผ๋กœ ๊ถŒ์žฅ๋˜๋ฉฐ, ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋“ค์„ ์ง‘ํ•ฉ์œผ๋กœ ๋‹ค๋ฃจ์–ด์•ผ ํ•  ๋•Œ ์ตœ์ƒ์˜ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•จ. EnumSet ์„ ์ƒ์„ฑํ•  ๋•Œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด EnumSet.of(A, B) ๋Š” ์ฃผ์–ด์ง„ ์ƒ์ˆ˜๋“ค๋กœ ๊ตฌ์„ฑ๋œ EnumSet์„ ๋งŒ๋“ค๊ณ , EnumSEt.allOf(EnumType.class) ๋Š” ํ•ด๋‹น ์—ด๊ฑฐํ˜•์˜ ๋ชจ๋“  ์ƒ์ˆ˜๋ฅผ ํฌํ•จํ•˜๋Š” EnumSet ์„ ๋งŒ๋“ฌ. EnumSet.noneOf(EnumType.class) ๋Š” ๋น„์–ด์žˆ๋Š” EnumSet ์„ ์ƒ์„ฑํ•จ. ๋‹ค์Œ์€ EnumSet ์‚ฌ์šฉ ์˜ˆ์‹œ์ž„.

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }

EnumSet<Day> weekend = EnumSet.of(Day.SAT, DAY.SUN);
System.out.println(weekend);        // result : [SAT, SUN]

EnumSet<Day> workdays = EnumSet.complementOf(weekend);
System.out.println(workdays);       // result : [MON, TUE, WED, THU, FRI]

์œ„ ์ฝ”๋“œ์—์„œ EnumSet.of(Day.SAT, Day.SUN) ์€ SAT ์™€ SUN ๋งŒ ๋‹ด์€ EnumSet ์„ ์ƒ์„ฑํ•˜๊ณ  complementOf ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์–ด์ง„ EnumSet ์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ์—ด๊ฑฐํ˜• ๊ฐ’๋“ค๋กœ ๊ตฌ์„ฑ๋œ ์ƒˆ๋กœ์šด EnumSet ์„ ๋ฐ˜ํ™˜ํ•จ. ๋”ฐ๋ผ์„œ workdays ๋Š” ์ฃผ๋ง์„ ์ œ์™ธํ•œ ์š”์ผ๋“ค๋กœ ์ฑ„์›Œ์ง. EnumSet ์€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋น„ํŠธ ์—ฐ์‚ฐ์„ ํ™œ์šฉํ•˜๋ฏ€๋กœ, ์›์†Œ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„๋„ ๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋ฉฐ, HashSet ๋Œ€๋น„ ์„ฑ๋Šฅ์ƒ ์ด์  ์ด ํผ. ๋‹จ, EnumSet ์€ enum ํƒ€์ž…๋‹น ํ•˜๋‚˜์˜ ๋น„ํŠธ์…‹์œผ๋กœ ํ‘œํ˜„๋˜๋ฏ€๋กœ ๋™์‹œ์— ์—ฌ๋Ÿฌ enum ํƒ€์ž…์„ ํ˜ผํ•ฉํ•˜์—ฌ ์ €์žฅํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, null ๊ฐ’๋„ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Œ. (null ์„ ๋„ฃ์œผ๋ ค๊ณ  ํ•˜๋ฉด NullPointerException ๋ฐœ์ƒ). ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ์ œํ•œ์€ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์œผ๋ฉฐ, ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜์˜ ์ง‘ํ•ฉ์„ ๋‹ค๋ฃฐ ๋•Œ EnumSet ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋จ.

  • EnumMap :

    EnumMap<K extends Enum<K, V> ๋Š” ์—ด๊ฑฐํ˜•์„ ํ‚ค๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ „์šฉ Map ๊ตฌํ˜„์ฒด ์ž„. EnumMap์˜ ํ‚ค๋Š” ๋ชจ๋‘ ๊ฐ™์€ enum ํƒ€์ž…์ด์–ด์•ผ ํ•˜๋ฉฐ, ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฐฐ์—ด ์„ ์ด์šฉํ•ด ๊ตฌํ˜„๋˜์–ด ์žˆ์Œ. ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜์˜ ordinal() ๊ฐ’์„ ๋ฐฐ์—ด index ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์‘๋˜๋Š” ๊ฐ’์„ ์ €์žฅํ•˜๋ฏ€๋กœ, ํ•ด์‹ฑ(Hashing) ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ๋งค์šฐ ๋น ๋ฅธ ์กฐํšŒ/๊ฐฑ์‹  ์„ฑ๋Šฅ ์„ ๋ณด์ž„. ๊ธฐ๋ณธ์—ฐ์‚ฐ(์กฐํšŒ, ์ถ”๊ฐ€, ์‚ญ์ œ ๋“ฑ) ์ด ์ƒ์ˆ˜ ์‹œ๊ฐ„ ์— ์‹คํ–‰๋˜๋ฉฐ, ์ผ๋ฐ˜์ ์ธ HashMap ๋ณด๋‹ค๋„ ํšจ์œจ์ ์ž„. ๋˜ํ•œ ๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ๊ตฌํ˜„ ๋•๋ถ„์— ๋ฉ”๋ชจ๋ฆฌ๋„ ์—ด๊ฑฐํ˜• ์š”์†Œ ๊ฐœ์ˆ˜์— ๋”ฑ ๋งž์ถฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ๋‚ญ๋น„๊ฐ€ ์ ๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ด ์ปดํŒฉํŠธ ํ•จ. EnumMap ์„ ์ƒ์„ฑํ•  ๋Œ€๋Š” ํ‚ค๋กœ ์‚ฌ์šฉํ•  enum ์˜ Class ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด new EnumMap<>(Day.class) ์ฒ˜๋Ÿผ enum ํƒ€์ž…์„ ์ง€์ •ํ•˜๋ฉด ํ•ด๋‹น enum ์˜ ๋ชจ๋“  ๊ฐ’์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๋‚ด๋ถ€ ๋ฐฐ์—ด์ด ์„ค์ •๋จ.(์ดˆ๊ธฐ์—๋Š” ๊ฐ’์ด ๋น„์–ด์žˆ๊ณ , ํ•„์š”ํ•œ ํ‚ค์— ๋Œ€ํ•ด์„œ๋งŒ ๊ฐ’์ด ์ฑ„์›Œ์ง.) EnumMap ์€ iterator(์ˆœํšŒ) ์‹œ ์—ด๊ฑฐํ˜• ์ •์˜ ์ˆœ์„œ(์ž์—ฐ์ˆœ์„œ) ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ๋„ ํŠน์ง•์ž„. ์ด๋Š” HashMap ์ด ํ•ด์‹œ๊ฐ’ ์ˆœ์„œ๋กœ ํ‚ค๋ฅผ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, EnumMap ์€ ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜์˜ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฅด๋ฏ€๋กœ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ˆœ์„œ๋ฅผ ๋ณด์ž„. ๋‹ค์Œ์€ EnumMap ์‚ฌ์šฉ ์˜ˆ์‹œ์ž„.

EnumMap<Day, String> dayType = new EnumMap<>(Day.class);
dayType.put(Day.MON, "Weekday");
dayType.put(Day.SAT, "Weekend");

System.out.println(dayType.get(Day.MON));        // result : Weekday
System.out.println(dayType);                     // result {MON=Weekday, SAT=Weekend}

์œ„ ์ฝ”๋“œ์—์„œ dayType ์€ Day ์—ด๊ฑฐํ˜•์„ ํ‚ค๋กœ ํ•˜๊ณ  ๋ฌธ์ž์—ด์„ ๊ฐ’์œผ๋กœ ๊ฐ€์ง€๋Š” EnumType ์ž„. Day.MON ํ‚ค์— "Weekday" ๋ฅผ ๋„ฃ๊ณ , Day.SAT ํ‚ค์— "Weekend" ๋ฅผ ๋„ฃ์€ ํ›„ ์กฐํšŒ์™€ ์ถœ๋ ฅ ์˜ˆ๋ฅผ ๋ณด์—ฌ์คŒ. ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด {MON=Weekday, SAT=Weekend} ์™€ ๊ฐ™์ด ํ‚ค์˜ ์„ ์–ธ ์ˆœ์„œ(์›”์š”์ผ์ด ํ† ์š”์ผ๋ณด๋‹ค ์•ž์„  ์ˆœ์„œ) ๊ฐ€ ์œ ์ง€๋˜์–ด ๋‚˜ํƒ€๋‚จ.

EnumMap ์€ ๋ชจ๋“  ํ‚ค๋ฅผ ๋ฐฐ์—ด๋กœ ์ง์ ‘ ์ ‘๊ทผ ํ•˜๋ฏ€๋กœ ๋งค์šฐ ๋น ๋ฅด๋ฉฐ, ํ‚ค์˜ ์ „์ฒด ๊ฐฏ์ˆ˜๊ฐ€ ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜์˜ ์ˆ˜๋กœ ํ•œ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— HashMap ์ฒ˜๋Ÿผ ์šฉ๋Ÿ‰์ด ๋™์ ์œผ๋กœ ๋Š˜์–ด๋‚˜๋Š” ๊ณผ์ •๋„ ์—†์Œ. ๋”ฐ๋ผ์„œ ์—ด๊ฑฐํ˜•์„ ํ‚ค๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์—์„œ๋Š” ํ•ญ์ƒ EnumMap ์„ ์šฐ์„ ์ ์œผ๋กœ ๊ณ ๋ ค ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ. ์˜ˆ๋ฅผ ๋“ค์–ด ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋ฅผ ์–ด๋–ค ๊ฐ’์— ๋งคํ•‘ํ•˜๋Š” ๊ฒฝ์šฐ (switch ๋ฌธ์œผ๋กœ์ผ์ผ์ด ๋ถ„๊ธฐํ•˜๋Š” ๋Œ€์‹ ) EnumMap ์— ์ƒ์ˆ˜-๊ฐ’ ์Œ์„ ๋„ฃ์–ด ๊ด€๋ฆฌํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊น”๋”ํ•ด์ง€๊ณ  ์„ฑ๋Šฅ๋„ ์šฐ์ˆ˜ํ•จ. EnumMap ๋„ EnumSet ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ null ํ‚ค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ null ๊ฐ’์€ ํ—ˆ์šฉํ•จ. ๊ทธ๋ฆฌ๊ณ  thread-safe ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์‹œ ์ˆ˜์ •์ด ํ•„์š”ํ•˜๋ฉด ๋ณ„๋„๋กœ ๋™๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜ Collections.synchronizedMap ์œผ๋กœ ๊ฐ์‹ธ์•ผํ•จ.

Last updated

Was this helpful?