26 ~ 33

์•„์ดํ…œ 26. ๋กœ ํƒ€์ž…์€ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์— ์˜ˆ์™ธ๊ฐ€ ๋‚  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.

- ๋กœ ํƒ€์ž…์€ ์ œ๋„ค๋ฆญ์ด ๋„์ž…๋˜๊ธฐ ์ด์ „ ์ฝ”๋“œ์™€์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ์ œ๊ณต๋  ๋ฟ์ด๋‹ค.

ยท Set<Object>๋Š” ์–ด๋–  ํƒ€์ž…์˜ ๊ฐ์ฒด๋„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ด๊ณ , Set<?>๋Š” ๋ชจ์ข…์˜ ํƒ€์ž… ๊ฐ์ฒด๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด๋‹ค. ๊ฐ๊ฐ์„ ์ž„์˜์˜ ๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…, ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์œผ๋กœ ๋ถ€๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

- ์ด๋“ค์˜ ๋กœ ํƒ€์ž…์ธ Set์€ ์ œ๋„ค๋ฆญ ํƒ€์ž… ์‹œ์Šคํ…œ์— ์†ํ•˜์ง€ ์•Š๋Š”๋‹ค. Set<Object>์™€ Set<?>์€ ์•ˆ์ „ํ•˜์ง€๋งŒ, ๋กœ ํƒ€์ž…์€ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค.

์ œ๋„ค๋ฆญ ๊ด€๋ จ ์šฉ์–ด ์ •๋ฆฌ

ยท ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ์— ๋Œ€ํ•ด ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์“ฐ์ด๋ฉด ์ด๋ฅผ ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค ํ˜น์€ ์ œ๋„ค๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค๋ผ ํ•œ๋‹ค.

ex) List ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์›์†Œ ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ E๋ฅผ ๋ฐ›๋Š”๋‹ค.

ยท ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค์™€ ์ œ๋„ค๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ‹€์–ด ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด๋ผ ํ•œ๋‹ค.

- ๊ฐ๊ฐ์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž…์€ ์ผ๋ จ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์„ ์ •์˜ํ•œ๋‹ค. ๋จผ์ € ํด๋ž˜์Šค(ํ˜น์€ ์ธํ„ฐํŽ˜์ด์Šค) ์ด๋ฆ„์ด ๋‚˜์˜ค๊ณ  ์ด์–ด์„œ ๊บพ์‡ ๊ด„ํ˜ธ ์•ˆ์— ์‹ค์ œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ๋‚˜์—ดํ•œ๋‹ค.

ex) List<String>์€ ์›์†Œ์˜ ํƒ€์ž…์ด String์ธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋œปํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ด๋‹ค. ์—ฌ๊ธฐ์„œ ์ •๊ทœ(formal) ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ E์— ํ•ด๋‹นํ•˜๋Š” ์‹ค์ œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” String์ด๋‹ค.

ยท ๋กœ ํƒ€์ž…(raw type)์ด๋ž€ ์ œ๋„ค๋ฆญ ํƒ€์ž…์—์„œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „ํ˜€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ๋ฅผ ๋งํ•œ๋‹ค.

- ๋กœ ํƒ€์ž…์˜ ์šฉ๋„: ์ œ๋„ค๋ฆญ์ด ๋„๋ž˜ํ•˜๊ธฐ ์ „ ์ฝ”๋“œ์™€ ํ˜ธํ™˜๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ œ๊ณต๋œ๋‹ค.

ex) List<E>์˜ ๋กœ ํƒ€์ž…์€ List์ด๋‹ค.

๋กœ ํƒ€์ž…์˜ ๋ฌธ์ œ์ 

์ œ๋„ค๋ฆญ์„ ์ง€์›ํ•˜๊ธฐ ์ „ ์ปฌ๋ ‰์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ–ˆ๋‹ค.

// Stamp ์ธ์Šคํ„ด์Šค๋งŒ ์ทจ๊ธ‰ํ•œ๋‹ค.
private final Collection stamps= ...;

ยท ๋ฌธ์ œ์ : ์ด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‹ค์ˆ˜๋กœ ๋„์žฅ ๋Œ€์‹  ๋™์ „์„ ๋„ฃ์–ด๋„ ์•„๋ฌด ์˜ค๋ฅ˜ ์—†์ด ์ปดํŒŒ์ผ๋˜๊ณ  ์‹คํ–‰๋œ๋‹ค.

// ์‹ค์ˆ˜๋กœ ๋™์ „์„ ๋„ฃ๋Š”๋‹ค.
stamps.add(new Coin(...));

๊ทธ๋ฆฌ๊ณ  ๋™์ „์„ ๋‹ค์‹œ ๊บผ๋‚ด๊ธฐ ์ „์—๋Š” ์˜ค๋ฅ˜๋ฅผ ์•Œ์•„์ฑ„์ง€ ๋ชปํ•œ๋‹ค.

- ์˜ค๋ฅ˜๋Š” ๊ฐ€๋Šฅํ•œ ๋ฐœ์ƒ ์ฆ‰์‹œ, ์ด์ƒ์ ์œผ๋กœ๋Š” ์ปดํŒŒ์ผํ•  ๋•Œ ๋ฐœ๊ฒฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

// ๋ฐ˜๋ณต์ž์˜ ๋กœ ํƒ€์ž… - ๋”ฐ๋ผ ํ•˜์ง€ ๋ง ๊ฒƒ!
for(Iterator i = stamps.iterator(); i.hasNext();){
    Stamp stamp = (Stamp) i.next(); // ClassCastException์„ ๋˜์ง„๋‹ค.
    stamp.cancel()
}

๋กœ ํƒ€์ž…์˜ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ - ์ œ๋„ค๋ฆญ์˜ ์‚ฌ์šฉ

์ œ๋„ค๋ฆญ์„ ํ™œ์šฉํ•˜๋ฉด ์ด ์ •๋ณด๊ฐ€ ์ฃผ์„์ด ์•„๋‹Œ ์„ ์–ธ ์ž์ฒด์— ๋…น์•„๋“ ๋‹ค.

// ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ์ปฌ๋ ‰์…˜ ํƒ€์ž… - ํƒ€์ž… ์•ˆ์ •์„ฑ ํ™•๋ณด!
private final Collection<Stamp> stamps= ...;

์ด๋ ‡๊ฒŒ ์„ ์–ธํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” stamp์—๋Š” Stamp์˜ ์ธ์Šคํ„ด์Šค๋งŒ ๋„ฃ์–ด์•ผ ํ•จ์„ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ธ์ง€ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ์—‰๋šฑํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋„ฃ์œผ๋ ค ํ•˜๋ฉด ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ ๋ฌด์—‡์ด ์ž˜๋ชป๋๋Š”์ง€ ์ •ํ™•ํžˆ ์•Œ๋ ค์ค€๋‹ค.

- ์‹ค์ œ๋กœ ํ˜„์—…์—์„œ BigDecimal์šฉ ์ปฌ๋ ‰์…˜์— BigInteger๋ฅผ ๋„ฃ๋Š” ๋“ฑ์˜ ์‹ค์ˆ˜๋Š” ์ข…์ข… ์ผ์–ด๋‚œ๋‹ค.

stamps.add(new Coin(...)); // incompatible types: Coin cannot be converted to Stamp

ยท ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ปฌ๋ ‰์…˜์—์„œ ์›์†Œ๋ฅผ ๊บผ๋‚ด๋Š” ๋ชจ๋“  ๊ณณ์— ๋ณด์ด์ง€ ์•Š๋Š” ํ˜•๋ณ€ํ™˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ ˆ๋Œ€ ์‹คํŒจํ•˜์ง€ ์•Š์Œ์„ ๋ณด์žฅํ•œ๋‹ค.

ยท ๋กœ ํƒ€์ž…์„ ์“ฐ๋ฉด ์ œ๋„ค๋ฆญ์ด ์•ˆ๊ฒจ์ฃผ๋Š” ์•ˆ์ „์„ฑ๊ณผ ํ‘œํ˜„๋ ฅ์„ ๋ชจ๋‘ ์žƒ๊ฒŒ ๋˜๋ฏ€๋กœ, ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

์ž„์˜์˜ ๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…

ยท List์™€ List<Object>์˜ ์ฐจ์ด์ : List๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์—์„œ ์™„์ „ํžˆ ๋ฐœ์„ ๋บ€ ๊ฒƒ์ด๊ณ , List<Object>๋Š” ๋ชจ๋“  ํƒ€์ž…์„ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ์˜์‚ฌ๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ์— ๋ช…ํ™•ํžˆ ์ „๋‹ฌํ•œ ๊ฒƒ์ด๋‹ค.

ยท ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ List๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์— List<String>์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ์ง€๋งŒ, List<Object>๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์—๋Š” ๋„˜๊ธธ ์ˆ˜ ์—†๋‹ค. ์ด๋Š” ์ œ๋„ค๋ฆญ์˜ ํ•˜์œ„ ํƒ€์ž… ๊ทœ์น™ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰, List<String>์€ ๋กœ ํƒ€์ž…์ธ List์˜ ํ•˜์œ„ ํƒ€์ž…์ด์ง€๋งŒ, List<Object>์˜ ํ•˜์œ„ ํƒ€์ž…์€ ์•„๋‹ˆ๋‹ค(์•„์ดํ…œ 28).

ยท List<Object>์ฒ˜๋Ÿผ ์ž„์˜ ๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์€ ๊ดœ์ฐฎ๋‹ค.

- List<Object> ๊ฐ™์€ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋‹ฌ๋ฆฌ List ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ์žƒ๊ฒŒ ๋œ๋‹ค.

์˜ˆ์‹œ 1 - ๋กœ ํƒ€์ž…๊ณผ ์ž„์˜์˜ ๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…

๋‘˜์˜ ์ฐจ์ด๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด์ž. ์•„๋ž˜๋Š” ๋กœ ํƒ€์ž… List๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋‹ค.

public static void main(String[] args) {
    List<String> strings = new ArrayList<>();
        unsafeAdd(strings, Integer.valueOf(42));
        String s = strings.get(0); // ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™์œผ๋กœ ํ˜•๋ณ€ํ™˜ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
        }
        
        private static void unsafeAdd(List list, Object o) {
            list.add(o);
        }

์ด ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ์€ ๋˜์ง€๋งŒ, unchecked ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ์ด๋Œ€๋กœ ์‹คํ–‰ํ•˜๋ฉด strings.get(0)์˜ ๊ฒฐ๊ณผ๋ฅผ ํ˜•๋ณ€ํ™˜ํ•˜๋ ค ํ•  ๋•Œ ClassCastException์„ ๋˜์ง„๋‹ค.

ํ•ด๋‹น ๋กœ ํƒ€์ž… List๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ธ List<Object>๋กœ ๋ฐ”๊พธ๋ฉด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๋ฉฐ ์ปดํŒŒ์ผ์กฐ์ฐจ ๋˜์ง€ ์•Š๋Š”๋‹ค.

์˜ˆ์‹œ 2 - ๋กœ ํƒ€์ž…๊ณผ ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…

์•„๋ž˜๋Š” 2๊ฐœ์˜ ์ง‘ํ•ฉ(Set)์„ ๋ฐ›์•„ ๊ณตํ†ต ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋‹ค. ๋ชจ๋ฅด๋Š” ํƒ€์ž…์˜ ์›์†Œ๋„ ๋ฐ›๋Š” ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ๋‹ค.

static int numElementsInCommon(Set s1, Set s2){
    int result = 0;
    for(Object o1 : s1){
        if(s2.contains(o1)){
            result++;
        }
    }
    return result;
}

์ด ๋ฉ”์„œ๋“œ๋Š” ๋™์ž‘์€ ํ•˜์ง€๋งŒ ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค. ๋”ฐ๋ผ์„œ ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…(unbounded wildcard type)์„ ๋Œ€์‹  ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค.

ยท ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์“ฐ๊ณ  ์‹ถ์ง€๋งŒ ์‹ค์ œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‹ ๊ฒฝ ์“ฐ๊ณ  ์‹ถ์ง€ ์•Š์„ ๋•Œ๋Š” ๋ฌผ์Œํ‘œ(?)๋ฅผ ์‚ฌ์šฉํ•˜์ž.

- ์ด๊ฒƒ์€ ์–ด๋–ค ํƒ€์ž…์ด๋ผ๋„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋ฒ”์šฉ์ ์ธ Set ํƒ€์ž…์ด๋‹ค.

๋‹ค์Œ์€ ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ๋‹ค.

static int numElementsInCommon(Set<?> s1, Set<?> s2) {...}

ยท ๋กœ ํƒ€์ž…(Set)๊ณผ ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์˜ ์ฐจ์ด์ : ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์€ ์•ˆ์ „ํ•˜๋ฉฐ, ์œ ์—ฐํ•˜๋‹ค.

- ๋กœ ํƒ€์ž… ์ปฌ๋ ‰์…˜์—๋Š” ์•„๋ฌด ์›์†Œ๋‚˜ ๋„ฃ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ํƒ€์ž… ๋ถˆ๋ณ€์‹์„ ํ›ผ์†ํ•˜๊ธฐ ์‰ฝ๋‹ค.

- ๋ฐ˜๋ฉด, Collection<?>์—๋Š” null ์™ธ์—๋Š” ์–ด๋–ค ์›์†Œ๋„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค. ๋‹ค๋ฅธ ์›์†Œ๋ฅผ ๋„ฃ์œผ๋ ค ํ•˜๋ฉด ์ปดํŒŒ์ผํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ฆ‰, ์ปฌ๋ ‰์…˜์˜ ํƒ€์ž… ๋ถˆ๋ณ€์‹์„ ํ›ผ์†ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์•˜๋‹ค. ์–ด๋–ค ์›์†Œ๋„ Collection<?>์— ๋„ฃ์ง€ ๋ชปํ•˜๊ฒŒ ํ–ˆ์œผ๋ฉฐ ์ปฌ๋ ‰์…˜์—์„œ ๊บผ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์˜ ํƒ€์ž…๋„ ์ „ํ˜€ ์•Œ ์ˆ˜ ์—†๋‹ค. ์ด๋Ÿฌํ•œ ์ œ์•ฝ์„ ๋ฐ›์•„ ๋“ค์ผ ์ˆ˜ ์—†๋‹ค๋ฉด, ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ(์•„์ดํ…œ 30)๋‚˜ ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…(์•„์ดํ…œ31)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๋กœ ํƒ€์ž…์ด ํ—ˆ์šฉ๋˜๋Š” ์‚ฌ๋ก€

1. class ๋ฆฌํ„ฐ๋Ÿด์—๋Š” ๋กœ ํƒ€์ž…์„ ์จ์•ผ ํ•œ๋‹ค.

- ์ž๋ฐ” ๋ช…์„ธ๋Š” class ๋ฆฌํ„ฐ๋Ÿด์— ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ–ˆ๋‹ค(๋ฐฐ์—ด๊ณผ ๊ธฐ๋ณธ ํƒ€์ž…์€ ํ—ˆ์šฉ).

ex) List.class, String[].class, int.class๋Š” ํ—ˆ์šฉํ•˜๊ณ  List<String>.class, List<?>, class๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

2. instanceof ์—ฐ์‚ฐ์ž๋Š” ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž… ์ด์™ธ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์—๋Š” ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

- ๋Ÿฐํƒ€์ž„์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด ์ง€์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ๋กœ ํƒ€์ž…์ด๋“  ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด๋“  instanceof๋Š” ์™„์ „ํžˆ ๋˜‘๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค.

๋น„ํ•œ์ •์  ์™€์ด๋“ค์นด๋“œ ํƒ€์ž…์˜ ๊บพ์‡ ๊ด„ํ˜ธํ™” ๋ฌผ์Œํ‘œ๋Š” ์•„๋ฌด๋Ÿฐ ์—ญํ•  ์—†์ด ์ฝ”๋“œ๋งŒ ์ง€์ €๋ถ„ํ•˜๊ฒŒ ๋งŒ๋“œ๋ฏ€๋กœ, ์ฐจ๋ผ๋ฆฌ ๋กœ ํƒ€์ž…์„ ์“ฐ๋Š” ํŽธ์ด ๊น”๋”ํ•˜๋‹ค. ๋‹ค์Œ์€ ์ œ๋„ค๋ฆญ ํƒ€์ž…์— instanceof๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์ด๋‹ค.

// o์˜ ํƒ€์ž…์ด Set ์ž„์„ ํ™•์ธํ•œ ๋‹ค์Œ Set<?> ๋กœ ํ˜•๋ณ€ํ™˜ํ•ด์•ผ ํ•œ๋‹ค
if( o instanceof Set ){     // raw ํƒ€์ž…
    Set<?> s = (Set<?>) o;    // ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž… (์ปดํŒŒ์ผ๋Ÿฌ ๊ฒฝ๊ณ ๊ฐ€ ๋œจ์ง€ ์•Š๋Š”๋‹ค)
        }

์•„์ดํ…œ 27. ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์ œ๊ฑฐํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋Š” ์ค‘์š”ํ•˜๋‹ˆ ๋ฌด์‹œํ•˜์ง€ ๋ง์ž.

- ๋ชจ๋“  ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋Š” ๋Ÿฐํƒ€์ž„์— ClassCassException์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์ž ์žฌ์  ๊ฐ€๋Šฅ์„ฑ์„ ๋œปํ•œ๋‹ค. ์ตœ์„ ์„ ๋‹คํ•ด ์ œ๊ฑฐํ•˜์ž.

ยท ๊ฒฝ๊ณ ๋ฅผ ์—†์•จ ๋ฐฉ๋ฒ•์„ ์ฐพ์ง€ ๋ชปํ•˜๊ฒ ๋‹ค๋ฉด, ๊ทธ ์ฝ”๋“œ๊ฐ€ ํƒ€์ž… ์•ˆ์ ํ•จ์„ ์ฆ๋ช…ํ•˜๊ณ  ๊ฐ€๋Šฅํ•œ ํ•œ ๋ฒ”์œ„๋ฅผ ์ขํ˜€ @SuppressWarnings("unchecked") ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ฒจ๋ผ. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฒฝ๊ณ ๋ฅผ ์ถœ๊ธฐ๊ธฐ๋กœ ํ•œ ๊ทผ๊ฑฐ๋ฅผ ์ฃผ์„์œผ๋กœ ๋‚จ๊ฒจ๋ผ.

์ œ๋„ค๋ฆญ๊ณผ ์ปดํŒŒ์ผ๋Ÿฌ ๊ฒฝ๊ณ 

ยท ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ์ˆ˜๋งŽ์€ ์ปดํŒŒ์ผ๋Ÿฌ ๊ฒฝ๊ณ ๋ฅผ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

ex) ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜ ๊ฒฝ๊ณ , ๋น„๊ฒ€์‚ฌ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๊ฒฝ๊ณ , ๋น„๊ฒ€์‚ฌ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ๊ฐ€๋ณ€์ธ์ˆ˜ ํƒ€์ž… ๊ฒฝ๊ณ , ๋น„๊ฒ€์‚ฌ ๋ณ€ํ™˜ ๊ฒฝ๊ณ  ๋“ฑ

ยท ๋Œ€๋ถ€๋ถ„์˜ ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋Š” ์‰ฝ๊ฒŒ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž˜๋ชป ์ž‘์„ฑํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

Set<Lark> exaltation = new HashSet();

์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฌด์—‡์ด ์ž˜๋ชป๋๋Š”์ง€ ์นœ์ ˆํžˆ ์„ค๋ช…ํ•ด์ค€๋‹ค.

์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ๋ ค์ค€ ๋Œ€๋กœ ์ˆ˜์ •ํ•˜๋ฉด ๊ฒฝ๊ณ ๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ๋ ค์ค€ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š๊ณ , ์ž๋ฐ” 7๋ถ€ํ„ฐ ์ง€์›ํ•˜๋Š” ๋‹ค์ด์•„๋ชฌ๋“œ ์—ฐ์‚ฐ์ž(<>)๋งŒ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

- ๊ทธ๋Ÿฌ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์‹ค์ œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ถ”๋ก ํ•ด์ค€๋‹ค.

Set<Lark> exaltation = new HashSet<>();
    

ยท ํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ ๋ชจ๋“  ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์ œ๊ฑฐํ•˜์ž. ๋ชจ๋‘ ์ œ๊ฑฐํ•œ๋‹ค๋ฉด ๊ทธ ์ฝ”๋“œ๋Š” ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋œ๋‹ค.

- ์ฆ‰, ๋Ÿฐํƒ€์ž„์— ClassCastException์ด ๋ฐœ์ƒํ•  ์ผ์ด ์—†๊ณ , ์šฐ๋ฆฌ๊ฐ€ ์˜๋„ํ•œ ๋Œ€๋กœ ์ž˜ ๋™์ž‘ํ•˜๋ฆฌ๋ผ ํ™•์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํ™•์‹คํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด @SuppressWaringins("unchecked") ์• ๋„ˆํ…Œ์ด์…˜์„ ๋‹ฌ์•„ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธฐ์ž.

- ๋‹จ, ํƒ€์ž… ์•ˆ์ „ํ•จ์„ ๊ฒ€์ฆํ•˜์ง€ ์•Š์€ ์ฑ„ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธฐ๋ฉด ์Šค์Šค๋กœ์—๊ฒŒ ์ž˜๋ชป๋œ ๋ณด์•ˆ ์ธ์‹์„ ์‹ฌ์–ด์ฃผ๋Š” ๊ผด์ด๋‹ค.

- ํ•ด๋‹น ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ๋•Œ๋ฉด ๊ทธ ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•ด๋„ ์•ˆ์ „ํ•œ ์ด์œ ๋ฅผ ํ•ญ์ƒ ์ฃผ์„์œผ๋กœ ๋‚จ๊ฒจ์•ผ ํ•œ๋‹ค.

ยท ์•ˆ์ „ํ•˜๋‹ค๊ณ  ๊ฒ€์ฆ๋œ ๋น„์ ์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธฐ์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ๋‘๋ฉด, ์ง„์งœ ๋ฌธ์ œ๋ฅผ ์•Œ๋ฆฌ๋Š” ์ƒˆ๋กœ์šด ๊ฒฝ๊ณ ๊ฐ€ ๋‚˜์™€๋„ ์ œ๊ฑฐํ•˜์ง€ ์•Š์€ ์ˆ˜๋งŽ์€ ๊ฑฐ์ง“ ๊ฒฝ๊ณ  ์†์— ํŒŒ๋ฌปํ˜€ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท @SuppressWaring ์• ๋„ˆํ…Œ์ด์…˜์€ ์ง€์—ญ๋ณ€์ˆ˜๋ถ€ํ„ฐ ํด๋ž˜์Šค ์ „์ฒด๊นŒ์ง€ ์–ด๋–ค ์„ ์–ธ์—๋„ ๋‹ฌ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ฐ€๋Šฅํ•œ ์ข์€ ๋ฒ”์œ„์— ์ ์šฉํ•˜์ž.

- ๋ณดํ†ต์€ ๋ณ€์ˆ˜ ์„ ์–ธ, ์•„์ฃผ ์งง์€ ๋ฉ”์„œ๋“œ, ํ˜น์€ ์ƒ์„ฑ์ž๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.

- ํด๋ž˜์Šค ์ „์ฒด์— ์ ์šฉํ•˜๋ฉด ์ž์นซ ์‹ฌ๊ฐํ•œ ๊ฒฝ๊ณ ๋ฅผ ๋†“์น  ์ˆ˜ ์žˆ๋‹ค.

@SuppressWaring ์• ๋„ˆํ…Œ์ด์…˜ ์‚ฌ์šฉ ๋ฒ”์œ„๋ฅผ ์ขํžˆ๋Š” ์˜ˆ์‹œ

๋‹ค์Œ์€ ArrayList์—์„œ ๊ฐ€์ ธ์˜จ toArray ๋ฉ”์„œ๋“œ๋‹ค.

public <T> T[] toArray(T[] a) {
    if( a.length < size )
        return (T[]) Arrays.copyOf(elements, size, a.getClass());
    System.arraycopy(elements, 0, a, 0, size);
    if( a.length > size )
        a[size] = null;
    return a;
}

ArrayList๋ฅผ ์ปดํŒŒ์ผํ•˜๋ฉด ์ด ๋ฉ”์„œ๋“œ์—์„œ elements ์š”์†Œ์— unchecked cast ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์• ๋„ˆํ…Œ์ด์…˜์€ ์„ ์–ธ์—๋งŒ ๋‹ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— return ๋ฌธ์—๋Š” ๋‹ฌ ์ˆ˜ ์—†๋‹ค. ๋ฉ”์„œ๋“œ ์ „์ฒด์— ๋‹ฌ๊ณ  ์‹ถ๊ฒ ์ง€๋งŒ, ๋ฒ”์œ„๊ฐ€ ํ•„์š” ์ด์ƒ์œผ๋กœ ๋„“์–ด์ง„๋‹ค.

๋Œ€์‹ ์— ๋ฐ˜ํ™˜๊ฐ’์„ ๋‹ด์„ ์ง€์—ญ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜ ์„ ์–ธํ•˜๊ณ , ๊ทธ ๋ณ€์ˆ˜์— ์• ๋„ˆํ…Œ์ด์…˜์„ ๋‹ฌ์•„์ฃผ์ž.

public <T> T[] toArray(T[] a) {
    if( a.length < size ){
        // ์ƒ์„ฑํ•œ ๋ฐฐ์—ด๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ๋ฐฐ์—ด์˜ ํƒ€์ž…์ด ๋ชจ๋‘ T[] ๋กœ ๊ฐ™์œผ๋ฏ€๋กœ
        // ์˜ฌ๋ฐ”๋ฅธ ํ˜•๋ณ€ํ™˜์ด๋‹ค
        @SuppressWarnings("unchecked") T[] result =
        (T[]) Arrays.copyOf(elements, size, a.getClass());
        return result;
    }
    System.arraycopy(elements, 0, a, 0, size);
    if( a.length > size )
        a[size] = null;
    return a;
}

ยท ์ด ์ฝ”๋“œ๋Š” ๊น”๋”ํ•˜๊ฒŒ ์ปดํŒŒ์ผ๋˜๊ณ , ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธฐ๋Š” ๋ฒ”์œ„๋„ ์ตœ์†Œ๋กœ ์ขํ˜”๋‹ค.

์•„์ดํ…œ 28. ๋ฐฐ์—ด๋ณด๋‹ค๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ๋ฐฐ์—ด์€ ๊ณต๋ณ€์ด๋‹ค.

- Sub๊ฐ€ Super์˜ ํ•˜์œ„ ํƒ€์ž…์ด๋ผ๋ฉด Sub[]์€ ๋ฐฐ์—ด Super[]์˜ ํ•˜์œ„ ํƒ€์ž…์ด ๋œ๋‹ค.

ยท ์ œ๋„ค๋ฆญ์€ ๋ถˆ๊ณต๋ณ€์ด๊ณ , ํƒ€์ž… ์ •๋ณด๊ฐ€ ์†Œ๊ฑฐ๋œ๋‹ค.

- ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž… Type1๊ณผ Type2๊ฐ€ ์žˆ์„ ๋•Œ, List<Type1>์€ List<Type2>์˜ ํ•˜์œ„ ํƒ€์ž…๋„ ์•„๋‹ˆ๊ณ  ์ƒ์œ„ ํƒ€์ž…๋„ ์•„๋‹ˆ๋‹ค.

ยท ๊ทธ ๊ฒฐ๊ณผ ๋ฐฐ์—ด์€ ๋Ÿฐํƒ€์ž„์—๋Š” ํƒ€์ž… ์•ˆ์ „ํ•˜์ง€๋งŒ, ์ปดํŒŒ์ผํƒ€์ž„์—๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. ์ œ๋„ค๋ฆญ์€ ๋ฐ˜๋Œ€๋‹ค.

ยท ๊ทธ๋ž˜์„œ ๋‘˜์„ ์„ž์–ด ์“ฐ๊ธฐ๋ž€ ์‰ฝ์ง€ ์•Š๋‹ค. ๋‘˜์„ ์„ž์–ด ์“ฐ๋‹ค๊ฐ€ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋‚˜ ๊ฒฝ๊ณ ๋ฅผ ๋งŒ๋‚˜๋ฉด, ๊ฐ€์žฅ ๋จผ์ € ๋ฐฐ์—ด์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋Œ€์ฒดํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ ์šฉํ•ด๋ณด์ž.

๋ฐฐ์—ด๊ณผ ๋ฆฌ์ŠคํŠธ์˜ ์ฐจ์ด

ยท ๋ฐฐ์—ด๊ณผ ์ œ๋„ค๋ฆญ ํƒ€์ž…์—๋Š” ์ค‘์š”ํ•œ ์ฐจ์ด๊ฐ€ ๋‘ ๊ฐ€์ง€ ์žˆ๋‹ค.

1. ๋ฐฐ์—ด์€ ๊ณต๋ณ€(covariant)์ด๊ณ , ์ œ๋„ค๋ฆญ์€ ๋ถˆ๊ณต๋ณ€(invariant)์ด๋‹ค.

- Sub๊ฐ€ Super์˜ ํ•˜์œ„ ํƒ€์ž…์ด๋ผ๋ฉด ๋ฐฐ์—ด Sub[]์€ ๋ฐฐ์—ด Super[]์˜ ํ•˜์œ„ ํƒ€์ž…์ด ๋œ๋‹ค. ๊ณต๋ณ€์€ ํ•จ๊ป˜ ๋ณ€ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.

์ฆ‰, Object[]์— Integer[]์„ ๋Œ€์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค. (์ž๋ฐ”์˜ ์„ค๊ณ„ ์˜ค๋ฅ˜)

- ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž… Type1๊ณผ Type2๊ฐ€ ์žˆ์„ ๋•Œ, List<Type1>์€ List<Type2>์˜ ํ•˜์œ„ ํƒ€์ž…๋„ ์•„๋‹ˆ๊ณ  ์ƒ์œ„ ํƒ€์ž…๋„ ์•„๋‹ˆ๋‹ค.

List<String>์€ List<Object>๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ œ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•˜์ง€ ๋ชปํ•˜๋‹ˆ ํ•˜์œ„ ํƒ€์ž…์ด ๋  ์ˆ˜ ์—†๋‹ค(๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™์— ์–ด๊ธ‹๋‚œ๋‹ค. ์•„์ดํ…œ 10).

๋‘˜์˜ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด์ž. ๋‹ค์Œ์€ ํ—ˆ์šฉ๋˜๋Š” ์ฝ”๋“œ๋‹ค.

// ๋Ÿฐํƒ€์ž„์— ์‹คํŒจํ•˜๋‹ค.
Object[] objectArray = new Long[1];
objectArray[0] = "ํƒ€์ž…์ด ๋‹ฌ๋ผ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค";    // ArrayStoreException

๋‹ค์Œ์€ ๋ฌธ๋ฒ•์— ๋งž์ง€ ์•Š๋Š”๋‹ค.

// ์ปดํŒŒ์ผ๋˜์ง€ ์•Š๋Š”๋‹ค.
List<Object> ol = new ArrayList<Long>();    // ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ํƒ€์ž…
    ol.add("ํƒ€์ž…์ด ๋‹ฌ๋ผ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค");

์–ด๋Š ์ชฝ์ด๋“  Long์šฉ ์ €์žฅ์†Œ์— String์„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค. ๋‹ค๋งŒ ๋ฐฐ์—ด์—์„œ๋Š” ๊ทธ ์‹ค์ˆ˜๋ฅผ ๋Ÿฐํƒ€์ž„์— ์•Œ๊ฒŒ ๋˜์ง€๋งŒ, ๋ฆฌ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผํ•  ๋•Œ ๋ฐ”๋กœ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

2. ๋ฐฐ์—ด์€ ์‹ค์ฒดํ™”(reify)๋œ๋‹ค.

- ๋ฐฐ์—ด์€ ๋Ÿฐํƒ€์ž„์—๋„ ์ž์‹ ์ด ๋‹ด๊ธฐ๋กœํ•œ ์›์†Œ์˜ ํƒ€์ž…์„ ์ธ์ง€ํ•˜๊ณ  ํ™•์ธํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์œ„์—์„œ ์ฒ˜๋Ÿผ Long ๋ฐฐ์—ด์— String์„ ๋„ฃ์œผ๋ ค ํ•˜๋ฉด ArrayStoreException์ด ๋ฐœ์ƒํ•œ๋‹ค.

- ๋ฐ˜๋ฉด, ์ œ๋„ค๋ฆญ์€ ํƒ€์ž… ์ •๋ณด๊ฐ€ ๋Ÿฐํƒ€์ž„์—๋Š” ์†Œ๊ฑฐ(erasure)๋œ๋‹ค. ์ฆ‰, ์›์†Œ ํƒ€์ž…์„ ์ปดํŒŒ์ผํƒ€์ž„์—๋งŒ ๊ฒ€์‚ฌํ•˜๋ฉฐ ๋Ÿฐํƒ€์ž„์—๋Š” ์•Œ์ˆ˜์กฐ์ฐจ ์—†๋‹ค.

- ์†Œ๊ฑฐ๋Š” ์ œ๋„ค๋ฆญ์ด ์ง€์›๋˜๊ธฐ ์ „์˜ ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์™€ ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋งค์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

ยท ์ด๋Ÿฌํ•œ ์ฐจ์ด๋กœ ๋ฐฐ์—ด๊ณผ ์ œ๋„ค๋ฆญ์€ ์ž˜ ์–ด์šฐ๋Ÿฌ์ง€์ง€ ๋ชปํ•œ๋‹ค.

- ์˜ˆ๋ฅผ๋“ค์–ด ๋ฐฐ์—ด์€ ์ œ๋„ค๋ฆญ ํƒ€์ž…, ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…, ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ex) new List<E>[], new List<String>[], new E[] ์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ์ปดํŒŒ์ผํ•  ๋•Œ ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด ์ƒ์„ฑ ์˜ค๋ฅ˜๋ฅผ ์ผ์œผํ‚จ๋‹ค.

์ œ๋„ค๋ฆญ ๋ฐฐ์—ด์„ ๋งŒ๋“ค์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์€ ์ด์œ 

ยท ํƒ€์ž…์•ˆ์ „ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ์ด๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™ ์ƒ์„ฑํ•œ ํ˜•๋ณ€ํ™˜ ์ฝ”๋“œ์—์„œ ๋Ÿฐํƒ€์ž„์— ClassCastException์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์ด๋Š” ๋Ÿฐํƒ€์ž„์— ClassCastException์ด ๋ฐœ์ƒํ•˜๋Š” ์ผ์„ ๋ง‰์•„์ฃผ๊ฒ ๋‹ค๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์‹œ์Šคํ…œ์˜ ์ทจ์ง€์— ์–ด๊ธ‹๋‚œ๋‹ค.

TODO: ๋‚ด์šฉ ์ถ”๊ฐ€

List<String>[] stringLists = new List<String>[1];   // (1)
    List<Integer> intList = List.of(42);   				// (2)
        Object[] objects = stringLists;   					// (3)
        objects[0] = intList;   							// (4)
        String s = stringLists[0].get(0);   				// (5)
public class Chooser {
    private final Object[] choiceArray;
    
    public Chooser(Collection choices) {
        choiceArray = choices.toArray();
    }
    
    public Object choose() {
        Random rnd = ThreadLocalRandom.current();
        return choiceArray[rnd.nextInt(choiceArray.length)];
    }
}
public class Chooser<T> {
    private final T[] choiceArray;
    
    public Chooser(Collection<T> choices) {
        choiceArray = choices.toArray();
    }
    
    // choose ๋ฉ”์„œ๋“œ๋Š” ๊ทธ๋Œ€๋กœ
    }
public class Chooser<T> {
    private final List<T> choiceList;
        
        public Chooser(Collection<T> choices) {
            choiceList = new ArrayList<>(choices);
        }
        
        public T choose() {
            Random rnd = ThreadLocalRandom.current();
            return choiceList.get(rnd.nextInt(choiceList.size()));
        }
        }

์•„์ดํ…œ 29. ์ด์™•์ด๋ฉด ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ํด๋ผ์ด์–ธํŠธ์—์„œ ์ง์ ‘ ํ˜•๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š” ํƒ€์ž…๋ณด๋‹ค ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด ๋” ์•ˆ์ „ํ•˜๊ณ  ์“ฐ๊ธฐ ํŽธํ•˜๋‹ค.

ยท ๋”ฐ๋ผ์„œ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์„ค๊ณ„ํ•  ๋•Œ๋Š” ํ˜•๋ณ€ํ™˜ ์—†์ด๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ผ. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

ยท ๊ธฐ์กด ํƒ€์ž… ์ค‘ ์ œ๋„ค๋ฆญ์ด์—ˆ์–ด์•ผ ํ•˜๋Š” ๊ฒŒ ์žˆ๋‹ค๋ฉด ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝํ•˜์ž.

- ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ์—๋Š” ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ, ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋ฅผ ํ›จ์”ฌ ํŽธํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธธ์ด๋‹ค(์•„์ดํ…œ 26).

์˜ˆ์‹œ - Object ๊ธฐ๋ฐ˜ ์Šคํƒ

ยท ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ์ผ์€ ์กฐ๊ธˆ ์–ด๋ ต๋‹ค. ๊ทธ๋ž˜๋„ ๋ฐฐ์›Œ๋‘๋ฉด ๊ทธ๋งŒํ•œ ๊ฐ’์–ด์น˜๋ฅผ ์ถฉ๋ถ„ํžˆ ํ•œ๋‹ค.

// Object ๊ธฐ๋ฐ˜ ์Šคํƒ - ์ œ๋„ค๋ฆญ์ด ์ ˆ์‹คํ•œ ๊ฐ•๋ ฅ ํ›„๋ณด
public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }
    
    public Object pop() {
        if( size == 0 ) throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null;    // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ
        return result;
    }
    
    public boolean isEmpty() {
        return size == 0;
    }
    
    private void ensureCapacity() {
        if( elements.length == size )
            elements = Arrays.copyOf(elements, 2*size + 1);
    }
}

ยท ์ด ํด๋ž˜์Šค๋Š” ์›๋ž˜ ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด์–ด์•ผ ๋งˆ๋•…ํ•˜๋‹ค. ์ด ํด๋ž˜์Šค๋ฅผ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋ฐ”๊ฟ”๋„ ํ˜„์žฌ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ์—๋Š” ์•„๋ฌด๋Ÿฐ ํ•ด๊ฐ€ ์—†๋‹ค.

- ์˜คํžˆ๋ ค ์ง€๊ธˆ ์ƒํƒœ์—์„œ์˜ ํด๋ผ์ด์–ธํŠธ๋Š” ์Šคํƒ์—์„œ ๊บผ๋‚ธ ๊ฐ์ฒด๋ฅผ ํ˜•๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๋•Œ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ๋‚  ์œ„ํ—˜์ด ์žˆ๋‹ค.

์˜ˆ์‹œ - ์ œ๋„ค๋ฆญ ์Šคํƒ์œผ๋กœ ๊ฐ€๋Š” ์ฒซ ๋‹จ๊ณ„

์ผ๋ฐ˜ ํด๋ž˜์Šค๋ฅผ ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด๋ณด์ž.

1. ํด๋ž˜์Šค ์„ ์–ธ์— ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์Šคํƒ์ด ๋‹ด์„ ์›์†Œ ํƒ€์ž… ํ•˜๋‚˜๋งŒ ์ถ”๊ฐ€ํ•œ๋‹ค. ํƒ€์ž… ์ด๋ฆ„์œผ๋กœ ๋ณดํ†ต E๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค(์•„์ดํ…œ 68).

2. ๋‘ ์ฝ”๋“œ์— ์“ฐ์ธ Object๋ฅผ ์ ์ ˆํ•œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ”๊พธ๊ณ  ์ปดํŒŒ์ผํ•ด๋ณด์ž.

public class Stack<E> {
    private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    public Stack() {
        elements = new E[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }
    
    public E pop() {
        if( size == 0 ) throw new EmptyStackException();
        E result = elements[--size];
        elements[size] = null;    // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ
        return result;
    }
    
    ... // isEmpty์™€ ensureCapacity ๋ฉ”์„œ๋“œ๋Š” ๊ทธ๋Œ€๋กœ๋‹ค.
}

์ด ๋‹จ๊ณ„์—์„œ ๋Œ€์ฒด๋กœ ํ•˜๋‚˜ ์ด์ƒ์˜ ์˜ค๋ฅ˜๋‚˜ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์œ„ ์ฝ”๋“œ๋„ ์•„๋ž˜ ๋ถ€๋ถ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. E์™€ ๊ฐ™์€ ์‹ค์ฒดํ™” ๋ถ„๊ฐ€ ํƒ€์ž…์œผ๋กœ๋Š” ๋ฐฐ์—ด์„ ๋งŒ๋“ค ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

elements = new E[DEFAULT_INITIAL_CAPACITY];

์ด๋ ‡๊ฒŒ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋งŒ๋“ค๋ ค ํ•  ๋•Œ ํ•ด๊ฒฐ์ฑ…์€ ๋‘ ๊ฐ€์ง€๋‹ค.

์˜ค๋ฅ˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ์ฒซ ๋ฒˆ์งธ, ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด ์ƒ์„ฑ์„ ๊ธˆ์ง€ํ•˜๋Š” ์ œ์•ฝ์„ ๋Œ€๋†“๊ณ  ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. Object ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•œ ๋‹ค์Œ ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด๋กœ ํ˜•๋ณ€ํ™˜ํ•˜์ž.

- ์ด์ œ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์˜ค๋ฅ˜ ๋Œ€์‹  ๊ฒฝ๊ณ ๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค. ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ํƒ€์ž… ์•ˆ์ •ํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];

์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด ํ”„๋กœ๊ทธ๋žจ์ด ํƒ€์ž… ์•ˆ์ „ํ•œ์ง€ ์ฆ๋ช…ํ•  ๋ฐฉ๋ฒ•์ด ์—†์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜์ด ํ”„๋กœ๊ทธ๋žจ์˜ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ํ•ด์น˜์ง€ ์•Š์Œ์„ ์šฐ๋ฆฌ ์Šค์Šค๋กœ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.

๋ฌธ์ œ์˜ ๋ฐฐ์—ด elements๋Š” private ํ•„๋“œ์— ์ €์žฅ๋˜๊ณ , ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ˜ํ™˜๋˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ๋˜๋Š” ์ผ์ด ์ „ํ˜€ ์—†๋‹ค. push ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋ฐฐ์—ด์— ์ €์žฅ๋˜๋Š” ์›์†Œ์˜ ํƒ€์ž…์€ ํ•ญ์ƒ E๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜์€ ํ™•์‹คํžˆ ์•ˆ์ „ํ•˜๋‹ค.

๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜์ด ์•ˆ์ „ํ•จ์„ ์ง์ ‘ ์ฆ๋ช…ํ–ˆ๋‹ค๋ฉด, ๋ฒ”์œ„๋ฅผ ์ตœ์†Œ๋กœ ์ขํ˜€ @SuppressWarings ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ํ•ด๋‹น ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธด๋‹ค(์•„์ดํ…œ 27). ์ด ์˜ˆ์—์„œ๋Š” ์ƒ์„ฑ์ž๊ฐ€ ๋น„๊ฒ€์‚ฌ ๋ฐฐ์—ด ์ƒ์„ฑ ๋ง๊ณ ๋Š” ํ•˜๋Š” ์ผ์ด ์—†์œผ๋‹ˆ ์ƒ์„ฑ์ž ์ „์ฒด์—์„œ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ฒจ๋„ ์ข‹๋‹ค.

// ๋ฐฐ์—ด elements ๋Š” push(E) ๋กœ ๋„˜์–ด์˜จ E ์ธ์Šคํ„ด์Šค๋งŒ ๋‹ด๋Š”๋‹ค
// ๋”ฐ๋ผ์„œ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜์ง€๋งŒ,
// ์ด ๋ฐฐ์—ด์˜ ๋Ÿฐํƒ€์ž„ ํƒ€์ž…์€ E[] ๊ฐ€ ์•„๋‹Œ Object[] ์ด๋‹ค
@SuppressWarnings("unchecked")
public Stack() {
    elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}

์˜ค๋ฅ˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ๋‘ ๋ฒˆ์งธ, elements ํ•„๋“œ์˜ ํƒ€์ž…์„ E[]์—์„œ Object[]๋กœ ๋ฐ”๊พผ๋‹ค.

- ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ์™€๋Š” ๋‹ค๋ฅธ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜ํ•œ ์›์†Œ๋ฅผ E๋กœ ํ˜•๋ณ€ํ™˜ํ•˜๋ฉด ์˜ค๋ฅ˜ ๋Œ€์‹  ์˜ค๋ฅ˜ ๋Œ€์‹  ๊ฒฝ๊ณ ๊ฐ€ ๋œฌ๋‹ค. E๋Š” ์‹ค์ฒดํ™” ๋ถˆ๊ฐ€ ํƒ€์ž…์ด๋ฏ€๋กœ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋Ÿผํƒ€์ž„์— ์ด๋ค„์ง€๋Š” ํ˜•๋ณ€ํ™˜์ด ์•ˆ์ „ํ•œ์ง€ ์ฆ๋ช…ํ•  ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฒˆ์—๋„ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ฆ๋ช…ํ•˜๊ณ  ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

pop ๋ฉ”์„œ๋“œ ์ „์ฒด์—์„œ ๊ฒฝ๋กœ๋ฅผ ์ˆจ๊ธฐ์ง€ ๋ง๊ณ , ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ• ๋‹น๋ฌธ์—์„œ๋งŒ ์ˆจ๊ฒจ๋ณด์ž.

// ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์ ์ ˆํžˆ ์ˆจ๊ธด๋‹ค
public E pop() {
    if( size == 0 ) throw new EmptyStackException();
    
    // push ์—์„œ E ํƒ€์ž…๋งŒ ํ—ˆ์šฉํ•˜๋ฏ€๋กœ ์ด ํ˜•๋ณ€ํ™˜์€ ์•ˆ์ „ํ•˜๋‹ค
    @SuppressWarnings("unchecked")
    E result = (E) elements[--size];
    
    elements[size] = null;    // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ
    return result;
}

๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ ๋‚˜๋ฆ„์˜ ์ง€์ง€๋ฅผ ์–ป๊ณ  ์žˆ์ง€๋งŒ, ํ˜„์—… ์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ๋” ์„ ํ˜ธํ•œ๋‹ค.

1. ๊ฐ€๋…์„ฑ์ด ๋” ์ข‹๋‹ค.

2. ๋ฐฐ์—ด์˜ ํƒ€์ž…์„ E[]๋กœ ์„ ์–ธํ•˜์—ฌ ์˜ค์ง Eํƒ€์ž… ์ธ์Šคํ„ด์Šค๋งŒ ๋ฐ›์Œ์„ ํ™•์‹คํžˆ ์–ดํ•„ํ•œ๋‹ค.

3. ์ฝ”๋“œ๊ฐ€ ๋” ์งง๋‹ค.

4. ์ฒซ ๋ฒˆ์งธ ๋ฐฉ์‹์—์„œ๋Š” ํ˜•๋ณ€ํ™˜์„ ๋ฐฐ์—ด ์ƒ์„ฑ ์‹œ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ํ•ด์ฃผ๋ฉด ๋˜์ง€๋งŒ, ๋‘ ๋ฒˆ์งธ ๋ฐฉ์‹์—์„œ๋Š” ๋ฐฐ์—ด์—์„œ ์›์†Œ๋ฅผ ์ฝ์„ ๋•Œ๋งˆ๋‹ค ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์˜ ๋‹จ์ ๋„ ์žˆ๋‹ค. ํž™์˜ค์—ผ(์•„์ดํ…œ 32)์„ ์ผ์œผํ‚จ๋‹ค.

๋‹ค์Œ์€ ๋ช…๋ ฌ์ค„ ์ธ์ˆ˜๋“ค์„ ์—ญ์ˆœ์œผ๋กœ ๋ฐ”๊ฟ” ๋Œ€๋ฌธ์ž๋กœ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ๋ฐฉ๊ธˆ ๋งŒ๋“  ์ œ๋„ค๋ฆญ Stack ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ์Šต์„ ๋ณด์—ฌ์ค€๋‹ค.

// ์ œ๋„ค๋ฆญ stack ์‚ฌ์šฉ์‹œ ๋ช…์‹œ์  ํ˜•๋ณ€ํ™˜์ด ์—†๋‹ค (์ปดํŒŒ์ผ๋Ÿฌ์— ์˜ํ•ด ์ˆ˜ํ–‰)
publi static void main(String[] args) {
    Stack<String> stack = new Stack<>();
        for( String arg : args )
            stack.push( arg );
        while( !stack.isEmpty() )
            System.out.println(stack.pop().toUpperCase());
        }

ยท ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ธฐ๋ณธ ํƒ€์ž…์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์‹œ์Šคํ…œ์˜ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ์ด๋‚˜, ๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…(์•„์ดํ…œ 61)์„ ์‚ฌ์šฉํ•ด ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

Ex) Stack<int>, Stack<double>์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•˜๋ฉด ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค.

์•„์ดํ…œ 30. ์ด์™•์ด๋ฉด ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“ค๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์ œ๋„ค๋ฆญ ํƒ€์ž…๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ํด๋ผ์ด์–ธํŠธ์—์„œ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ํ˜•๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ณด๋‹ค ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๊ฐ€ ๋” ์•ˆ์ „ํ•˜๋ฉฐ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ์‰ฝ๋‹ค.

ยท ํƒ€์ž…๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋ฉ”์„œ๋“œ๋„ ํ˜•๋ณ€ํ™˜ ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŽธ์ด ์ข‹์œผ๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค.

- ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ๋Š” ๊ทธ๋Œ€๋กœ ๋‘” ์ฑ„ ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž์˜ ์‚ถ์„ ํ›จ์”ฌ ํŽธํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค„ ๊ฒƒ์ด๋‹ค(์•„์ดํ…œ 26).

์˜ˆ์‹œ - ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ๋ฉ”์„œ๋“œ

๋‹ค์Œ์€ ๋‘ ์ง‘ํ•ฉ์˜ ํ•ฉ์ง‘ํ•ฉ์„ ๋ฐ˜ํ™˜ํ•˜๋Š”, ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋‹ค.

// ๊ฒฝ๊ณ ๋ฅผ ์—†์• ๋ ค๋ฉด ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค
public static Set union(Set s1, Set s2) {
    Set result = new HashSet(s1);     // unchecked ๊ฒฝ๊ณ  ๋ฐœ์ƒ
    result.addAll(s2);                // unchecked ๊ฒฝ๊ณ  ๋ฐœ์ƒ
    return result;
}

์ปดํŒŒ์ผ์€ ๋˜์ง€๋งŒ ๊ฒฝ๊ณ ๊ฐ€ ๋‘ ๊ฐœ ๋ฐœ์ƒํ•œ๋‹ค. ๊ฒฝ๊ณ ๋ฅผ ์—†์• ๋ ค๋ฉด ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

์˜ˆ์‹œ1 - ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ

์œ„์˜ ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•œ๋‹ค.

- ๋ฉ”์„œ๋“œ ์„ ์–ธ์—์„œ์˜ ์„ธ ๊ฒฐํ•ฉ(์ž…๋ ฅ 2๊ฐœ, ๋ฐ˜ํ™˜ 1๊ฐœ)์˜ ์›์†Œ ํƒ€์ž…์„ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ช…์‹œํ•œ๋‹ค.

- ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ๋„ ์ด ํƒ€์ž… ๋งค๊ฐœ๋ฒผ์ˆ˜๋งŒ ์‚ฌ์šฉํ•˜๊ฒŒ ์ˆ˜์ •ํ•œ๋‹ค.

- ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก์€ ๋ฉ”์„œ๋“œ์˜ ์ œํ•œ์ž์™€ ๋ฐ˜ํ™˜ ํƒ€์ž… ์‚ฌ์ด์— ์˜จ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ์—์„œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก์€ <E>์ด๊ณ , ๋ฐ˜ํ™˜ ํƒ€์ž…์€ Set<E>์ด๋‹ค. ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๋ช…๋ช… ๊ทœ์น™์€ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ, ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด ๋˜‘๊ฐ™๋‹ค.

public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
    Set<E> result = new HashSet(s1);
        result.addAll(s2);
        return result;
        }

ยท ์œ„์˜ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋Š” ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ ๋˜๋ฉฐ, ํƒ€์ž… ์•ˆ์ „ํ•˜๊ณ , ์“ฐ๊ธฐ๋„ ์‰ฝ๋‹ค.

๋‹ค์Œ์€ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. ์ง์ ‘ ํ˜•๋ณ€ํ™˜ํ•˜์ง€ ์•Š์•„๋„ ์˜ค๋ฅ˜๋‚˜ ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ๋œ๋‹ค.

public static void main(String[] args) {
    Set<String> guys = Set.of("ํ†ฐ", "๋”•", "ํ•ด๋ฆฌ");
        Set<String> stooges = Set.of("๋ž˜๋ฆฌ", "๋ชจ์—", "์ปฌ๋ฆฌ");
            Set<String> aflCio = union( guys, stooges );    // ์ถ”์ •์— ์˜ํ•œ ์‚ฌ์šฉ๋ฐฉ๋ฒ•(2)
                System.out.println(aflCio);
                }

ยท union ๋ฉ”์„œ๋“œ์˜ ๋ฌธ์ œ์ : ์ง‘ํ•ฉ 3๊ฐœ(์ž…๋ ฅ 2๊ฐœ, ๋ฐ˜ํ™˜ 1๊ฐœ)์˜ ํƒ€์ž…์ด ๋ชจ๋‘ ๊ฐ™์•„ ํ•œ๋‹ค.

์ด๋ฅผ ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…(์•„์ดํ…œ 31)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋” ์œ ์—ฐํ•˜๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ ํŒจํ„ด

ยท ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์—ฌ๋Ÿฌ ํƒ€์ž…์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค. ์ œ๋„ค๋ฆญ์€ ๋Ÿฐํƒ€์ž„์— ํƒ€์ž… ์ •๋ณด๊ฐ€ ์†Œ๊ฑฐ(์•„์ดํ…œ 28)๋˜๋ฏ€๋กœ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์š”์ฒญํ•œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋งž๊ฒŒ ๋งค๋ฒˆ ๊ทธ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ๋ฐ”๊ฟ”์ฃผ๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ์ด ํŒจํ„ด์„ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ๋ผ๊ณ  ํ•œ๋‹ค.

ex) Collections.reverseOrder ๊ฐ™์€ ํ•จ์ˆ˜ ๊ฐ์ฒด(์•„์ดํ…œ42), Collections.emptySet ๊ฐ™์€ ์ปฌ๋ ‰์…˜์šฉ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

ยท ํ•ญ๋“ฑ ํ•จ์ˆ˜(identity function)์„ ๋‹ด์€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด, ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํ•˜๋‚˜๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค.

- ์ œ๋„ค๋ฆญ์ด ์‹ค์ฒดํ™”๋œ๋‹ค๋ฉด ํ•ญ๋“ฑํ•ฉ์ˆ˜๋ฅผ ํƒ€์ž…๋ณ„๋กœ ํ•˜๋‚˜์”ฉ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

- ๋ฌผ๋ก  ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ Function.identity๋ฅผ ์‚ฌ์šฉํ•ด ํ•ญ๋“ฑํ•จ์ˆ˜๋ฅผ ๋‹ด์€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ์—์„œ IDENTITY_FN์„ UnaryOperator<T>๋กœ ํ˜•๋ณ€ํ™˜ํ•˜๋ฉด ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ํ•˜์ง€๋งŒ ํ•ญ๋“ฑํ•จ์ˆ˜๋ž€ ์ž…๋ ฅ ๊ฐ’์„ ์ˆ˜์ • ์—†์ด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋ฏ€๋กœ, T๊ฐ€ ์–ด๋–ค ํƒ€์ž…์ด๋“  UnaryOperator<T>๋ฅผ ์‚ฌ์šฉํ•ด๋„ ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค.

๋”ฐ๋ผ์„œ @SuppressWarnings ์• ๋„ˆํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์ž.

// ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด
private static UnaryOperator<Object> ITENTIFY_FN = (t) -> t;
    
    @SuppressWarnings("unchecked")
    public static <T> UnaryOperator<T> identifyFunction() {
        return (UnaryOperator<T>) IDENTIFY_FN;
            }

๋‹ค์Œ์€ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋‹ค. ํ˜•๋ณ€ํ™˜์„ ํ•˜์ง€ ์•Š์•„๋„ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋‚˜ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

public static void main(String[] args) {
    String[] strings = { "ํ•˜๋‚˜", "๋‘˜", "์…‹" };
    UnaryOperator<String> sameString = identifyFunction();
        for( String s : strings )
            System.out.println( sameString.apply(s) );
        
        Number[] numbers = { 1, 2.0, 3L };
        UnaryOperator<Number> sameNumber = identifyFunction();
            for( Number n : numbers )
                System.out.println( sameNumber.apply(n) );
            }

์žฌ๊ท€ ํƒ€์ž… ํ•œ์ •

ยท ๋“œ๋ฌผ๊ฒŒ ์ž๊ธฐ ์ž์‹ ์ด ๋“ค์–ด๊ฐ„ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํ—ˆ์šฉ ๋ฒ”์œ„๋ฅผ ํ•œ์ •ํ•˜๋Š” ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •(recursive type bound)์ด ์‚ฌ์šฉ๋œ๋‹ค.

- ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์€ ์ฃผ๋กœ ํƒ€์ž…์˜ ์ž์—ฐ์  ์ˆœ์„œ๋ฅผ ์ •ํ•˜๋Š” Comparable ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์“ฐ์ธ๋‹ค.

public interface Comparable<T> {
    int compareTo(T o);
}

์œ„ ์ฝ”๋“œ์—์„œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ T๋Š” Comparable<T>๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž…์ด ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ์›์†Œ์˜ ํƒ€์ž…์„ ์ •์˜ํ•œ๋‹ค.

- ์‹ค์ œ๋กœ ๊ฑฐ์˜ ๋ชจ๋“  ํƒ€์ž…์€ ์ž์‹ ๊ณผ ๊ฐ™์€ ํƒ€์ž…์˜ ์›์†Œ์™€๋งŒ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค.

ex) String์€ Comparable<String>์„ ๊ตฌํ˜„ํ•˜๊ณ , Integer๋Š” Comparable<Integer>๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

Comparable์„ ๊ตฌํ˜„ํ•œ ์›์†Œ์˜ ์ปฌ๋ ‰์…˜์„ ์ž…๋ ฅ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ์ฃผ๋กœ ๊ทธ ์›์†Œ๋“ค์„ ์ •๋ ฌ ํ˜น์€ ๊ฒ€์ƒ‰ํ•˜๊ฑฐ๋‚˜, ์ตœ์†Ÿ๊ฐ’์ด๋‚˜ ์ตœ๋Œ“๊ฐ’์„ ๊ตฌํ•˜๋Š” ์‹์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ์ปฌ๋ ‰์…˜์— ๋‹ด๊ธด ์›์†Œ๊ฐ€ ์ƒํ˜ธ ๋น„๊ต๋  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

๋‹ค์Œ์€ ์ด ์ œ์•ฝ์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•œ ๋ชจ์Šต์ด๋‹ค. ํƒ€์ž… ํ•œ์ •์ธ <E extends Comparable<E>>๋Š” "๋ชจ๋“  ํƒ€์ž… E๋Š” ์ž์‹ ๊ณผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค"๋ผ๊ณ  ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค.

// ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์„ ์ด์šฉํ•ด ์ƒํ˜ธ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Œ์„ ํ‘œํ˜„
public static <E extends Comparable<E>> E max(Collection<E> c);

๋‹ค์Œ์€ ๋ฐฉ๊ธˆ ์„ ์–ธํ•œ max ๋ฉ”์„œ๋“œ์˜ ๊ตฌํ˜„์ด๋‹ค. ์ปฌ๋ ‰์…˜์— ๋‹ด๊ธด ์›์†Œ์˜ ์ž์—ฐ์  ์ˆœ์„œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ตœ๋Œ“๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋ฉฐ, ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋‚˜ ๊ฒฝ๊ณ ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

public static <E extends Comparable<E>> E max(Collection<E> c) {
    if( c.isEmpty() )
        throw new IllegalArgumentException("์ปฌ๋ ‰์…˜์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค");
    
    E result = null;
    for( E e : c )
        if( result == null || e.compareTo(result) > 0 )
            result = Objects.requireNonNull(e);
    
    return result;
}

ยท ์ด๋ฒˆ ์•„์ดํ…œ์—์„œ ์„ค๋ช…ํ•œ ๊ด€์šฉ๊ตฌ, ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ด์šฉํ•œ ๋ณ€ํ˜•(์•„์ดํ…œ 31), ์‹œ๋ฎฌ๋ ˆ์ดํŠธํ•œ ์…€ํ”„ ํƒ€์ž… ๊ด€์šฉ๊ตฌ(์•„์ดํ…œ 2)๋ฅผ ์ดํ•ดํ•˜๊ณ  ๋‚˜๋ฉด ์‹ค์ „์—์„œ ๋งˆ์ฃผ์น˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์„ ๋ฌด๋ฆฌ ์—†์ด ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

์•„์ดํ…œ 31. ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์‚ฌ์šฉํ•ด API ์œ ์—ฐ์„ฑ์„ ๋†’์ด๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์กฐ๊ธ‰ ๋ณต์žกํ•˜๋”๋ผ๋„ ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์ ์šฉํ•˜๋ฉด API๊ฐ€ ํ›จ์”ฌ ์œ ์—ฐํ•ด์ง„๋‹ค.

ยท ๋„๋ฆฌ ์“ฐ์ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜์ž.

ยท PECS ๊ณต์‹์„ ๊ธฐ์–ตํ•˜์ž.

- ์ƒ์‚ฐ์ž(producer)๋Š” extends๋ฅผ ์†Œ๋น„์ž(consumer)๋Š” super๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

- Comparable๊ณผ Comparator๋Š” ๋ชจ๋‘ ์†Œ๋น„์ž๋ผ๋Š” ์‚ฌ์‹ค์„ ์žŠ์ง€ ๋ง์ž.

๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์˜ ํ•œ๊ณ„

์•„์ดํ…œ 28์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์€ ๋ถˆ๊ณต๋ณ€์ด๋ผ๊ณ  ๋งํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ถˆ๊ณต๋ณ€ ๋ฐฉ์‹๋ณด๋‹ค ์œ ์—ฐํ•œ ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

๋‹ค์Œ์€ ์•„์ดํ…œ 29์˜ Stack ํด๋ž˜์Šค์˜ public API๋‹ค.

java public class Stack {
    public Stack();
    public void push(E e);
    public E pop();
    public boolean isEmpty();
}

์—ฌ๊ธฐ์— ์ผ๋ ฅ์˜ ์›์†Œ๋ฅผ ์Šคํƒ์— ๋„ฃ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž.

public void pushAll(Iterable<E> src) {
    for( E e : src )
        push(e);
}

์œ„ ๋ฉ”์„œ๋“œ๋Š” ์ปดํŒŒ์ผ๋˜์ง€๋งŒ ์™„๋ฒฝํ•˜์ง„ ์•Š๋‹ค. Iterable src์˜ ์›์†Œ ํƒ€์ž…์ด ์Šคํƒ์˜ ์›์†Œ ํƒ€์ž…๊ณผ ์ผ์น˜ํ•˜๋ฉด ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ, Stack<Number>๋กœ ์„ ์–ธํ•œ ํ›„ pushAll(intVal)์„ ํ˜ธ์ถœํ•ด๋ณด์ž(intVal์€ Integer ํƒ€์ž…์ด๋‹ค.).

Integer๋Š” Number์˜ ํ•˜์œ„ ํƒ€์ž…์ด๋‹ˆ ์ž˜ ๋™์ž‘ํ•  ๊ฒƒ ๊ฐ™์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ด ๋ถˆ๊ณต๋ณ€์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Stack<Number> numberStack = new Stack<>();
    Iterable<Integer> integers = ...;
        numberStack.pushAll(integers);

ยท ์ž๋ฐ”์—์„œ๋Š” ์ด๋Ÿฐ ์ƒํ™ฉ์— ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์„ ์ง€์›ํ•œ๋‹ค.

- ์•„๋ž˜ ์ฝ”๋“œ์˜ Iterable<? extends E>๋Š” 'E์˜ ํ•˜์œ„ ํƒ€์ž…์˜ Iterable'์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.

public void pushAll(Iterable<? extends E> src) {
    for( E e : src )
        push(e);
}

์ด์ œ pushAll๊ณผ ์ง์„ ์ด๋ฃจ๋Š” popAll ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ž. popAll ๋ฉ”์„œ๋“œ๋Š” Stack ์•ˆ์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ์ฃผ์–ด์ง„ ์ปฌ๋ ‰์…˜์œผ๋กœ ์˜ฎ๊ฒจ ๋‹ด๋Š”๋‹ค.

// ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ popAll ๋ฉ”์„œ๋“œ - ๊ฒฐํ•จ์ด ์žˆ๋‹ค.
public void popAll(Collection<E> dst) {
    while( !isEmpty() )
        dst.add( pop() );
}

์œ„ ์ฝ”๋“œ๋„ ์ปฌ๋ ‰์…˜์˜ ์›์†Œ ํƒ€์ž…์ด ์Šคํƒ์˜ ์›์†Œ ํƒ€์ž…๊ณผ ์ผ์น˜ํ•œ๋‹ค๋ฉด ๋ง๋”ํžˆ ์ปดํŒŒ์ผ๋˜๊ณ , ๋ฌธ์ œ์—†์ด ๋™์ž‘ํ•˜์ง€๋งŒ, ์™„๋ฒฝํ•˜์ง„ ์•Š๋‹ค.

Stack<Number>์˜ ์›์†Œ๋ฅผ Object์šฉ ์ปฌ๋ ‰์…˜์œผ๋กœ ์˜ฎ๊ธฐ๋ ค ํ•œ๋‹ค๋ฉด, "Collection<Object>๋Š” Collection<Number>์˜ ํ•˜์œ„ ํƒ€์ž…์ด ์•„๋‹ˆ๋‹ค"๋ผ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

Stack<Number> numberStack = new Stack<>();
    Collection<Object> objects = ...;
        numberStack.popAll( objects );

์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ด๋ฅผ ๊ฐœ์„ ํ•œ ์ฝ”๋“œ๋‹ค. ์—ฌ๊ธฐ์„œ ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ Collection<? super E>๋Š” 'E์˜ ์ƒ์œ„ ํƒ€์ž…์˜ Collection'์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋‹ค.

public void popAll(Collection<? super E> dst) {
    while( !isEmpty() )
        dst.add( pop() );
}

ยท ์ด์ฒ˜๋Ÿผ ์œ ์—ฐ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜๋ ค๋ฉด ์›์†Œ์˜ ์ƒ์‚ฐ์ž๋‚˜ ์†Œ๋น„์ž์šฉ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

- ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณต ์›์น™์ธ ํŽ™์Šค(PECS) ๊ณต์‹์„ ๊ธฐ์–ตํ•˜์ž. Poducer-Extends, Consumer-Super

- ์ฆ‰, ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž… T๊ฐ€ ์ƒ์‚ฐ์ž๋ผ๋ฉด <? extends T>, ์†Œ๋น„์ž๋ผ๋ฉด <? super T>๋ฅผ ์‚ฌ์šฉํ•˜์ž.

- ๋ฐ›์•„๋“ค์—ฌ์•ผ ํ•  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๊ณ , ๊ฑฐ์ ˆํ•ด์•ผ ํ•  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ฑฐ์ ˆํ•˜๋Š” ์ž‘์—…์ด ์•Œ์•„์„œ ์ด๋ค„์ง„๋‹ค.

- ํด๋ž˜์Šค ์‚ฌ์šฉ์ž๊ฐ€ ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‹ ๊ฒฝ ์จ์•ผ ํ•œ๋‹ค๋ฉด ๊ทธ API์— ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๋‹ค.

์ด์ „ ์•„์ดํ…œ์˜ ์ฝ”๋“œ ๊ฐœ์„ 

์•„์ดํ…œ 28์—์„œ Chooser ์ƒ์‚ฐ์ž๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ–ˆ๋‹ค.

public Chooser( Collection<T> choices );

์ด ์ƒ์„ฑ์ž๋กœ ๋„˜๊ฒจ์ง„ choices ์ปฌ๋ ‰์…˜์€ T ํƒ€์ž…์˜ ๊ฐ’์„ ์ƒ์‚ฐํ•˜๊ธฐ๋งŒ ํ•œ๋‹ค. PECS ๊ณต์‹์— ๋”ฐ๋ผ T๋ฅผ ํ™•์žฅํ•˜๋Š” ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค.

public Chooser( Collection<? extends T> choices );
    

์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ•˜๋ฉด, Chooser<Number>์˜ ์ƒ์„ฑ์ž์— List<Integer>๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

- ์ˆ˜์ • ์ „ ์ƒ์„ฑ์ž๋กœ๋Š” ์ปดํŒŒ์ผ์กฐ์ฐจ ๋˜์ง€ ์•Š๋Š”๋‹ค.

๋‹ค์Œ์œผ๋กœ ์•„์ดํ…œ 30์˜ union ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

public static <E> Set<E> union( Set<E> s1, Set<E> s2 );

s1๊ณผ s2 ๋ชจ๋‘ E์˜ ์ƒ์ƒ์ž์ด๋‹ˆ PECS ๊ณต์‹์— ๋”ฐ๋ผ ๋‹ค์Œ์ฒ˜๋Ÿผ ์„ ์–ธํ•œ๋‹ค.

- ๋ฐ˜ํ™˜ ํƒ€์ž…์€ ์—ฌ์ „ํžˆ Set<E>์ž„์— ์ฃผ๋ชฉํ•˜์ž. ๋ฐ˜ํ™˜ ํƒ€์ž…์—๋Š” ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ์œ ์—ฐ์„ฑ์„ ๋†’์—ฌ์ฃผ๊ธฐ๋Š”์ปค๋…• ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ๋„ ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„์จ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

public static <E> Set<E> union( Set<? extends E> s1, Set<? extends E> s2 );
    

์ˆ˜์ •ํ•œ ์„ ์–ธ์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋‹ค์Œ ์ฝ”๋“œ๋„ ๋ง๋”ํžˆ ์ปดํŒŒ์ผ๋œ๋‹ค.

Set<Integer> integers = Set.of(1, 3, 5);
    Set<Double> doubles = Set.of(2.0, 4.0, 6.0);
        Set<Number> numbers = union(integers, doubles);

์•ž์˜ ์ฝ”๋“œ๋Š” ์ž๋ฐ” 8๋ถ€ํ„ฐ ์ œ๋Œ€๋กœ ์ปดํŒŒ์ผ๋œ๋‹ค. ์ž๋ฐ” 7๊นŒ์ง€๋Š” ํƒ€์ž… ์ถ”๋ก  ๋Šฅ๋ ฅ์ด ๋ถ€์กฑํ•˜์—ฌ ๋ฌธ๋งฅ์— ๋งž๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…(ํ˜น์€ ๋ชฉํ‘œ ํƒ€์ž…)์„ ๋ช…์‹œํ•ด์•ผํ•œ๋‹ค.

Set<Number> numbers = union(integers, doubles); // imcompatible types ์˜ค๋ฅ˜ ๋ฐœ์ƒ

์ด ์˜ค๋ฅ˜๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜์ง€ ๋ชปํ•  ๋•Œ ๋ช…์‹œ์  ํƒ€์ž… ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํƒ€์ž…์„ ์•Œ๋ ค์ฃผ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๋ชฉํ‘œ ํƒ€์ดํ•‘(target typing)์€ ์ž๋ฐ” 8๋ถ€ํ„ฐ ์ง€์›ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

// ์ž๋ฐ” 7 ์ดํ•˜์—์„œ๋„ ๊นจ๋—์ด ์ปดํŒŒ์ผ ๋œ๋‹ค.
Set<Number> numbers = Union.<Number>union(integers, doubles);

๋‹ค์Œ์œผ๋กœ ์•„์ดํ…œ 30์˜ max ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

public static <E extends Comparable<E>> E max(
    List<E> list);

์•„๋ž˜ ์ฝ”๋“œ๋Š” ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ๋‹ค์Œ์€ ๋ชจ์Šต์ด๋‹ค.

public static <E extends Comparable<? super E>> E max(
    List<? extends E> list );

์ด๋ฒˆ์—๋Š” PECS ๊ณต์‹์„ ๋‘ ๋ฒˆ ์ ์šฉํ–ˆ๋‹ค.

์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ๋Š” E ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์ƒํ•˜๋ฏ€๋กœ, ์›๋ž˜์˜ List<E>๋ฅผ List<? extends E>๋กœ ์ˆ˜์ •ํ–ˆ๋‹ค.

ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ Comparable<E>๋Š” E ์ธ์Šคํ„ด์Šค๋ฅผ ์†Œ๋น„ํ•˜๋ฏ€๋กœ, Comparable<? super E>๋กœ ๋Œ€์ฒดํ–ˆ๋‹ค.

- Comparable๊ณผ Comparator๋Š” ์–ธ์ œ๋‚˜ ์†Œ๋น„์ž์ด๋ฏ€๋กœ Comparable<? super E> ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜์ž.

ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์™€์ผ๋“œ์นด๋“œ ๋‘˜ ๋‹ค ๊ฐ€๋Šฅํ•œ ๋ฉ”์„œ๋“œ ์ •์˜

ยท ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์™€์ผ๋“œ์นด๋“œ์—๋Š” ๊ณตํ†ต๋˜๋Š” ๋ถ€๋ถ„์ด ์žˆ์–ด์„œ, ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ๋‘ฅ ์ค‘ ์–ด๋Š ๊ฒƒ์„ ์‚ฌ์šฉํ•ด๋„ ๊ดœ์ฐฎ์„ ๋•Œ๊ฐ€ ๋งŽ๋‹ค.

๋‹ค์Œ์€ ๊ทธ ์˜ˆ์‹œ๋‹ค. ์ฃผ์–ด์ง„ ๋ฆฌ์ŠคํŠธ์—์„œ ๋ช…์‹œํ•œ ๋‘ ์ธ๋ฑ์Šค์˜ ์•„์ดํ…œ๋“ค์„ ๊ตํ™˜(swap)ํ•˜๋Š” ์ •์  ๋ฉ”์„œ๋“œ๋‹ค.

// swap ๋ฉ”์„œ๋“œ์˜ ๋‘ ๊ฐ€์ง€ ์„ ์–ธ
public static <E> void swap(List<E> list, int i, int j);
    public static void swap(List<?> list, int i, int j);

์–ด๋–ค ์„ ์–ธ์ด ๋” ๋‚ซ๊ณ , ๋” ๋‚˜์€ ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ?

public API๋ผ๋ฉด ๊ฐ„๋‹จํ•œ ๋‘ ๋ฒˆ์งธ๊ฐ€ ๋” ๋‚ซ๋‹ค.

์–ด๋–ค ๋ฆฌ์ŠคํŠธ๋“  ์ด ๋ฉ”์„œ๋“œ์— ๋„˜๊ธฐ๋ฉด ๋ช…์‹œํ•œ ์ธ๋ฑ์Šค์˜ ์›์†Œ๋“ค์„ ๊ตํ™˜ํ•ด ์ค„ ๊ฒƒ์ด๊ณ , ์‹ ๊ฒฝ ์จ์•ผ ํ•  ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ์—†๋‹ค.

ยท ๊ธฐ๋ณธ ๊ทœ์น™: ๋ฉ”์„œ๋“œ ์„ ์–ธ์— ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ๋‚˜์˜ค๋ฉด ์™€์ผ๋“œ ์นด๋“œ๋กœ ๋Œ€์ฒดํ•˜๋ผ.

- ๋น„ํ•œ์ •์  ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ผ๋ฉด ๋น„ํ•œ์ •์  ์™€์ผ๋“œ ์นด๋“œ๋กœ ๋ฐ”๊พธ๊ณ , ํ•œ์ •์  ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ผ๋ฉด ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ๋กœ ๋ฐ”๊พผ๋‹ค.

๋‘ ๋ฒˆ์งธ swap ์„ ์–ธ์—๋Š” ๋ฌธ์ œ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•„์ฃผ ์ง๊ด€์ ์œผ๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๊ฐ€ ์ปดํŒŒ์ผ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

public static void swap(List<?> list, int i, int j) {
    list.set(i, list.set(j, list.get(i)));
}

์ด ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผ ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ฆ‰, ๋ฐฉ๊ธˆ ๊บผ๋‚ธ ์›์†Œ๋ฅผ ๋ฆฌ์ŠคํŠธ์— ๋‹ค์‹œ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค.

์›์ธ์€ ๋ฆฌ์ŠคํŠธ์˜ ํƒ€์ž…์ด List<?>์ธ๋ฐ, List<?>์—๋Š” null ์™ธ์—๋Š” ์–ด๋–ค ๊ฐ’๋„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค๋Š” ๋ฐ ์žˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์‹ค์ œ ํƒ€์ž…์„ ์•Œ๋ ค์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ private ๋„์šฐ๋ฏธ ๋ฉ”์„œ๋“œ๋กœ ๋”ฐ๋กœ ์ž‘์„ฑํ•˜์—ฌ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์‹ค์ œ ํƒ€์ž…์„ ์•Œ์•„๋‚ด๋ ค๋ฉด ์ด ๋„์šฐ๋ฏธ ๋ฉ”์„œ๋“œ๋Š” ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ์—ฌ์•ผ ํ•œ๋‹ค.

public static void swap(List<?> list, int i, int j) {
    swapHelper(list, i, j);
}

// ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‹ค์ œ ํƒ€์ž…์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” private ๋„์šฐ๋ฏธ ๋ฉ”์„œ๋“œ
private static <E> void swapHelper(List<E> list, int i, int j) {
    list.set(i, list.set(j, list.get(i)));
}

ยท ๊ฒฐ๊ณผ์ ์œผ๋กœ swap ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ๋Š” ๋” ๋ณต์žกํ•œ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ–ˆ์ง€๋งŒ, ๋•๋ถ„์— ์™ธ๋ถ€์—์„œ๋Š” ์™€์ผ๋“œ์นด๋“œ ๊ธฐ๋ฐ˜์˜ ๋ฉ‹์ง„ ์„ ์–ธ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

- ์ฆ‰, swap ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ๋ณต์žกํ•œ swapHelper์˜ ์กด์žฌ๋ฅผ ๋ชจ๋“  ์ฑ„ ๊ทธ ํ˜œํƒ์„ ๋ˆ„๋ฆฐ๋‹ค.

์•„์ดํ…œ 32. ์ œ๋„ค๋ฆญ๊ณผ ๊ฐ€๋ณ€์ธ์ˆ˜๋ฅผ ํ•จ๊ป˜ ์“ธ ๋•Œ๋Š” ์‹ ์ค‘ํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ๊ฐ€๋ณ€์ธ์ˆ˜์™€ ์ œ๋„ค๋ฆญ์€ ๊ถํ•ฉ์ด ์ข‹์ง€ ์•Š๋‹ค.

- ๊ฐ€๋ณ€์ธ์ˆ˜ ๊ธฐ๋Šฅ์€ ๋ฐฐ์—ด์„ ๋…ธ์ถœํ•˜์—ฌ ์ถ”์ƒํ™”๊ฐ€ ์™„๋ฒฝํ•˜์ง€ ๋ชปํ•˜๊ณ , ๋ฐฐ์—ด๊ณผ ์ œ๋„ค๋ฆญ์˜ ํƒ€์ž… ๊ทœ์น™์ด ์„œ๋กœ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ยท ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด, ๋จผ์ € ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ํƒ€์ž… ์•ˆ์ „ํ•œ์ง€ ํ™•์ธํ•œ ๋‹ค์Œ @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์„ ๋‹ฌ์•„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ๋ถˆํŽธํ•จ์ด ์—†๊ฒŒ๋” ํ•˜์ž.

์ œ๋„ค๋ฆญ๊ณผ ๊ฐ€๋ณ€์ธ์ˆ˜ ๋ฉ”์„œ๋“œ

ยท ๊ฐ€๋ณ€์ธ์ˆ˜(varargs) ๋ฉ”์„œ๋“œ(์•„์ดํ…œ 53)์™€ ์ œ๋„ค๋ฆญ์€ ์ž๋ฐ” 5 ๋•Œ ํ•จ๊ป˜ ์ถ”๊ฐ€๋˜์—ˆ์ง€๋งŒ, ์ž˜ ์•„์šธ์–ด์ง€์ง€ ๋ชปํ–ˆ๋‹ค.

ยท ๊ฐ€๋ณ€์ธ์ˆ˜๋Š” ๋ฉ”์„œ๋“œ์— ๋„˜๊ธฐ๋Š” ์ธ์ˆ˜์˜ ๊ฐœ์ˆ˜๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š”๋ฐ, ๊ตฌํ˜„ ๋ฐฉ์‹์— ํ—ˆ์ ์ด์žˆ๋‹ค.

- ๊ฐ€๋ณ€์ธ์ˆ˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ฐ€๋ณ€์ธ์ˆ˜๋ฅผ ๋‹ด๊ธฐ ์œ„ํ•ด ๋ฐฐ์—ด์ด ์ž๋™์œผ๋กœ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ง€๋Š”๋ฐ, ์ด ๋ฐฐ์—ด์ด ๋‚ด๋ถ€๋กœ ๊ฐ์ถฐ์ง€์ง€ ์•Š๊ณ  ํด๋ผ์ด์–ธํŠธ์— ๋…ธ์ถœ๋œ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ varargs ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ œ๋„ค๋ฆญ์ด๋‚˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ด ํฌํ•จ๋˜๋ฉด ์•Œ๊ธฐ ์–ด๋ ค์šด ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์˜ˆ์‹œ - ์ œ๋„ค๋ฆญ๊ณผ ๊ฐ€๋ณ€์ธ์ˆ˜๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉ

ยท ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์˜ ํƒ€์ž…์ด ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ํž™ ์˜ค์—ผ์ด ๋ฐœ์ƒํ•œ๋‹ค.

- ์ด๋ ‡๊ฒŒ ๋‹ค๋ฅธ ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ƒํ™ฉ์—๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™ ์ƒ์„ฑํ•œ ํ˜•๋ณ€ํ™˜์ด ์‹คํŒจํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ œ๋„ค๋ฆญ ํƒ€์ž… ์‹œ์Šคํ…œ์ด ์•ฝ์†ํ•œ ํƒ€์ž… ์•ˆ์ „์„ฑ์˜ ๊ทผ๊ฐ„์ด ํ”๋“ค๋ฆฐ๋‹ค.

// ์ œ๋„ค๋ฆญ๊ณผ varargs๋ฅผ ํ˜ผ์šฉํ•˜๋ฉด ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๊นจ์ง„๋‹ค.
static void dangerous(List<String>... stringLists) {
    List<Integer> intList = List.of(42);
        Object[] objects = stringLists;
        objects[0] = intList;               // ํž™ ์˜ค์—ผ ๋ฐœ์ƒ
        String s = stringLists[0].get(0);   // ClassCastException
        }

์œ„ ๋ฉ”์„œ๋“œ๋Š” ํ˜•๋ณ€ํ™˜ํ•˜๋Š” ๊ณณ์ด ๋ณด์ด์ง€ ์•Š๋Š”๋ฐ๋„ ์ธ์ˆ˜๋ฅผ ๊ฑด๋ฐ ํ˜ธ์ถœํ•˜๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค. ๋งˆ์ง€๋ง‰ ์ค„์— ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ƒ์„ฑํ•œ (๋ณด์ด์ง€ ์•Š๋Š”) ํ˜•๋ณ€ํ™˜์ด ์ˆจ์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ยท ์ด์ฒ˜๋Ÿผ ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๊นจ์ง€๋‹ˆ ์ œ๋„ค๋ฆญ varargs ๋ฐฐ์—ด ๋งค๊ฐœ๋ณ€์ˆ˜์— ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค.

์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ ์ด์œ ๋Š”?

ยท ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฑด ํ—ˆ์šฉ๋˜์ง€ ์•Š์ง€๋งŒ, ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๋Š” ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค. (๊ฒฝ๊ณ ๋งŒ ๋ฐœ์ƒํ•˜๊ณ , ์ปดํŒŒ์ผ์„ ๋œ๋‹ค)

ยท ์ œ๋„ค๋ฆญ์ด๋‚˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์˜ varargs ๋ฐฐ์—ด์„ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹ค๋ฌด์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ๊ทธ๋ž˜์„œ ์–ธ์–ด ์„ค๊ณ„์ž๋Š” ์ด ๋ชจ์ˆœ์„ ์ˆ˜์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

ยท ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ์—ฌ๋Ÿฟ ์ œ๊ณตํ•œ๋‹ค. ๋‹คํ–‰์ด ์ด๋“ค์€ ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค.

ex) Arrays.asList<T... a), Collections.addAll(Collection<? super T> c, T... elements)

ยท ์ž๋ฐ” 7 ์ „์—๋Š” ์ œ๋„ค๋ฆญ ๊ฐ€๋ณ€์ธ์ˆ˜ ๋ฉ”์„œ๋“œ์˜ ์ž‘์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ์ž ์ชฝ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ๊ณ ์— ๋Œ€ํ•ด ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ์ผ์ด ์—†์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉํ•˜๊ธฐ์— ์ข€ ๊บผ๋ฆผ์น™ํ–ˆ๋‹ค.

- ์‚ฌ์šฉ์ž๋Š” ์ด ๊ฒฝ๊ณ ๋“ค์„ ๊ทธ๋ƒฅ ๋‘๊ฑฐ๋‚˜, ํ˜ธ์ถœํ•˜๋Š” ๊ณณ ๋งˆ๋‹ค @SuppressWarnings("unchecked") ์• ๋„ˆํ…Œ์ด์…˜์„ ๋‹ฌ์•„ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ฒจ์•ผ ํ–ˆ๋‹ค.

- ์ด๋Š” ์ง€๋ฃจํ•œ ์ž‘์—…์ด๊ณ , ๊ฐ€๋…์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ณ , ์ง„์งœ ๋ฌธ์ œ๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฒฝ๊ณ ๋งˆ์ € ์ˆจ๊ธฐ๋Š” ์•ˆ ์ข‹์€ ๊ฒฐ๊ณผ๋กœ ์ด์–ด์กŒ๋‹ค.

ยท ์ž๋ฐ” 7๋ถ€ํ„ฐ @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์ด ์ถ”๊ฐ€๋˜์–ด ์ œ๋„ค๋ฆญ ๊ฐ€๋ณ€์ธ์ˆ˜ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

- @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์€ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ์ž๊ฐ€ ๊ทธ ๋ฉ”์„œ๋“œ์˜ ํƒ€์ž… ์•ˆ์ „ํ•จ์„ ๋ณด์žฅํ•˜๋Š” ์žฅ์น˜๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด ์•ฝ์†์„ ๋ฏฟ๊ณ  ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ์•ˆ์ „ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒฝ๊ณ ๋ฅผ ๋” ์ด์ƒ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

ยท @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์€ ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†๋Š” ๋ฉ”์„œ๋“œ์—๋งŒ ๋‹ฌ์•„์•ผ ํ•œ๋‹ค.

- ์žฌ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ๋„ ์•ˆ์ „ํ• ์ง€๋Š” ๋ณด์žฅํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ์ž๋ฐ” 8์—์„œ ์ด ์• ๋„ˆํ…Œ์ด์…˜์€ ์˜ค์ง ์ •์  ๋ฉ”์„œ๋“œ์™€ final ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์—๋งŒ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค.

- ์ž๋ฐ” 9๋ถ€ํ„ฐ๋Š” private ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์—๋„ ํ—ˆ์šฉ๋œ๋‹ค.

๋ฉ”์„œ๋“œ๊ฐ€ ์•ˆ์ „ํ•œ์ง€ ์–ด๋–ป๊ฒŒ ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

ยท ๊ฐ€๋ณ€ ์ธ์ˆ˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋‹ด๋Š” ์ œ๋„ค๋ฆญ ๋ฐฐ์—ด์ด ๋งŒ๋“ค์–ด์ง„๋‹ค. ๋ฉ”์„œ๋“œ๊ฐ€ ์ด ๋ฐฐ์—ด์— ์•„๋ฌด๊ฒƒ๋„ ์ €์žฅํ•˜์ง€ ์•Š๊ณ (๊ทธ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๊ณ ), ๊ทธ ๋ฐฐ์—ด์˜ ์ฐธ์กฐ๊ฐ€ ๋ฐ–์œผ๋กœ ๋…ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค.

- ์ฆ‰, varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์ด ํ˜ธ์ถœ์ž๋กœ๋ถ€ํ„ฐ ๊ทธ ๋ฉ”์„œ๋“œ๋กœ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ์ธ์ˆ˜๋“ค์„ ์ „๋‹ฌํ•˜๋Š” ์ผ๋งŒ ํ•œ๋‹ค๋ฉด, ๊ทธ ๋ฉ”์„œ๋“œ๋Š” ์•ˆ์ „ํ•˜๋‹ค.

ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๊นจ๋Š” ์‚ฌ๋ก€

ยท varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์— ์•„๋ฌด๊ฒƒ๋„ ์ €์žฅํ•˜์ง€ ์•Š๊ณ ๋„ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๊นฐ์ˆ˜๋„ ์žˆ์œผ๋‹ˆ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

๋‹ค์Œ์€ ๊ฐ€๋ณ€์ธ์ˆ˜๋กœ ๋„˜์–ด์˜จ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ๋ฐฐ์—ด์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋‹ค.

// ์ž์‹ ์˜ ์ œ๋„ค๋ฆญ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์˜ ์ฐธ์กฐ๋ฅผ ๋…ธ์ถœํ•œ๋‹ค. - ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค.
static <T> T[] toArray(T... args) {
    return args;
}

์ด ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฐ์—ด์˜ ํƒ€์ž…์€ ์ด ๋ฉ”์„œ๋“œ์˜ ์ธ์ˆ˜๋ฅผ ๋„˜๊ธฐ๋Š” ์ปดํŒŒ์ผํƒ€์ž„์— ๊ฒฐ์ •๋˜๋Š”๋ฐ, ๊ทธ ์‹œ์ ์—๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ถฉ๋ถ„ํ•œ ์ •๋ณด๊ฐ€ ์ฃผ์–ด์ง€์ง€ ์•Š์•„ ํƒ€์ž…์„ ์ž˜๋ชป ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž์‹ ์˜ varargs ๋งค๋ฐฐ๋ณ€์ˆ˜ ๋ฐฐ์—ด์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํž™ ์˜ค์—ผ์„ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์ชฝ์˜ ์ฝœ์Šคํƒ๊นŒ์ง€ ์ „์ดํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋‚ณ์„ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ ๋ฉ”์„œ๋“œ๋Š” T ํƒ€์ž„ ์ธ์ˆ˜ 3๊ฐœ๋ฅผ ๋ฐ›์•„ ๊ทธ์ค‘ 2๊ฐœ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ๊ณจ๋ผ ๋‹ด์€ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

static <T> T[] pickTwo(T a, T b, T c) {
    switch( ThreadLocalRandom.current().nextInt(3)) {
        case 0: return toArray(a, b);
        case 1: return toArray(a, c);
        case 2: return toArray(b, c);
    }
    throw new AssertionError();     // ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋‹ค
}

์ด ๋ฉ”์„œ๋“œ๋ฅผ ๋ณธ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” toArray์— ๋„˜๊ธธ T ์ธ์Šคํ„ด์Šค 2๊ฐœ๋ฅผ ๋‹ด์„ varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“œ๋Š” ๋ฐฐ์—ด์˜ ํƒ€์ž…์€ Object[]์ด๋‹ค. pickTwo์— ์–ด๋–ค ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋„˜๊ธฐ๋”๋ผ๋„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  toArray ๋ฉ”์„œ๋“œ๊ฐ€ ๋Œ๋ ค์ค€ ์ด ๋ฐฐ์—ด(Object[] ํƒ€์ž…)์ด ๊ทธ๋Œ€๋กœ pickTwo๋ฅผ ํ˜ธ์ถœํ•œ ํด๋ผ์ด์–ธํŠธ๊นŒ์ง€ ์ „๋‹ฌ๋œ๋‹ค.

์ด์ œ pickTwo๋ฅผ ์‚ฌ์šฉํ•˜๋Š” main ๋ฉ”์„œ๋“œ๋ฅผ ๋ณด์ž.

public static void main(String[] args) {
    String[] attributes = pickTwo("์ข‹์€", "๋น ๋ฅธ", "์ €๋ ดํ•œ");
}

๋ณ„๋‹ค๋ฅธ ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ๋˜์ง€๋งŒ, ์‹คํ–‰ํ•˜๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค.

pickTwo์˜ ๋ฐ˜ํ™˜๊ฐ’์„ attributes์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด String[]๋กœ ํ˜•๋ณ€ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. Object[]๋Š” String[]์˜ ํ•˜์œ„ ํƒ€์ž…์ด ์•„๋‹ˆ๋ฏ€๋กœ ์ด ํ˜•๋ณ€ํ™˜์€ ์‹คํŒจํ•œ๋‹ค.

ํž™ ์˜ค์—ผ์„ ๋ฐœ์ƒ์‹œํ‚จ ์›์ธ์€ toArray๋กœ๋ถ€ํ„ฐ ๋‘ ๋‹จ๊ณ„๋‚˜ ๋–จ์–ด์ ธ ์žˆ๊ณ , varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์€ ์‹ค์ œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ €์žฅ๋œ ํ›„ ๋ณ€๊ฒฝ๋œ ์ ๋„ ์—†๋‹ค.

ยท ์ด ์˜ˆ๋Š” ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์— ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๊ฐ€ ์ ‘๊ทผํ•˜๋„๋ก ํ—ˆ์šฉํ•˜๋ฉด ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค๋Š” ์ ์„ ์ƒ๊ธฐ์‹œํ‚จ๋‹ค.

์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ

ยท ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์— ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๊ฐ€ ์ ‘๊ทผํ•ด๋„ ์•ˆ์ „ํ•œ ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

1. @SafeVarargs๋กœ ์ œ๋Œ€๋กœ ์• ๋„ˆํ…Œ์ดํŠธ๋œ ๋˜ ๋‹ค๋ฅธ varargs ๋ฉ”์„œ๋“œ์— ๋„˜๊ธฐ๋Š” ๊ฒƒ์€ ์•ˆ์ „ํ•˜๋‹ค.

2. ๋ฐฐ์—ด ๋‚ด์šฉ์˜ ์ผ๋ถ€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ๋งŒ ํ•˜๋Š”(varargs๋ฅผ ๋ฐ›์ง€ ์•Š๋Š”) ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ์— ๋„˜๊ธฐ๋Š” ๊ฒƒ์€ ์•ˆ์ „ํ•˜๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ์ „ํ˜•์ ์ธ ์˜ˆ๋‹ค.

flatten ๋ฉ”์„œ๋“œ๋Š” ์ž„์˜ ๊ฐœ์ˆ˜์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„, ๋ฐ›์€ ์ˆœ์„œ๋Œ€๋กœ ๊ทธ ์•ˆ์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ๋ฆฌ์ŠคํŠธ๋กœ ์˜ฎ๊ฒจ ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ด ๋ฉ”์„œ๋“œ์—์„œ๋Š” @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์ด ๋‹ฌ๋ ค ์žˆ์–ด ์„ ์–ธํ•˜๋Š” ์ชฝ๊ณผ ์‚ฌ์šฉํ•˜๋Š” ์ชฝ ๋ชจ๋‘ ๊ฒฝ๊ณ ๋ฅผ ๋‚ด์ง€ ์•Š๋Š”๋‹ค.

// ์ œ๋„ค๋ฆญ varags ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ
@SafeVarargs
static <T> List<T> flatten(List<? extends T>... lists) {
    List<T> result = new ArrayList<>();
        for( List<? extends T> list : lists )
            result.addAll(list);
        return result;
        }

ยท @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ๋ฅผ ์ •ํ•˜๋Š” ๊ทœ์น™: ์ œ๋„ค๋ฆญ์ด๋‚˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์˜ varargs ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์˜ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— @SafeVarargs๋ฅผ ๋‹ฌ๋ผ.

- ๊ทธ๋ž˜์•ผ ์‚ฌ์šฉ์ž๋ฅผ ํ—ท๊ฐˆ๋ฆฌ๊ฒŒ ํ•˜๋Š” ์ปดํŒŒ์ผ๋Ÿฌ ๊ฒฝ๋กœ๋ฅผ ์—†์•จ ์ˆ˜ ์žˆ๋‹ค.

- ์ด ๋ง์€ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ varargs ๋ฉ”์„œ๋“œ๋Š” ์ ˆ๋Œ€ ์ž‘์„ฑํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๋Š” ๋œป์ด๋‹ค.

ยท ์šฐ๋ฆฌ๊ฐ€ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ ์ค‘ ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ํž™ ์˜ค์—ผ ๊ฒฝ๊ณ ๊ฐ€ ๋œจ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ์ง„์งœ ์•ˆ์ „ํ•œ์ง€ ์ ๊ฒ€ํ•˜์ž.

- ๋‹ค์Œ ๋‘ ์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•˜๋Š” ์ œ๋„ค๋ฆญ varargs ๋ฉ”์„œ๋“œ๋Š” ์•ˆ์ „ํ•˜๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์–ด๊ฒผ๋‹ค๋ฉด ์ˆ˜์ •ํ•˜์ž.

1. varargs ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐฐ์—ด์— ์•„๋ฌด๊ฒƒ๋„ ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

2. ๊ทธ ๋ฐฐ์—ด(ํ˜น์€ ๋ณต์ œ๋ณธ)์„ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ฝ”๋“œ์— ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.

ยท @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์•„์ดํ…œ 28์˜ ์กฐ์–ธ์„ ๋”ฐ๋ผ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ List ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ๋‹ค.

// ์ œ๋„ค๋ฆญ varargs ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ List๋กœ ๋Œ€์ฒดํ•œ ์˜ˆ - ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค.
static <T> List<T> flatten(List<List<? extends T>> lists) {
    List<T> result = new ArrayList<>();
        for( List<? extends T> list : lists )
            result.addAll(list);
        return result;
        }

์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์ธ List.of๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด ๋ฉ”์„œ๋“œ์— ์ž„์˜ ๊ฐœ์ˆ˜์˜ ์ธ์ˆ˜๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

- List.of์—๋„ @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์ด ๋‹ฌ๋ ค ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•˜๋‹ค.

audience = flatten(List.of(friends, romans, countrymen));

ยท ์ด ๋ฐฉ์‹์˜ ์žฅ์ ์€ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ด ๋ฉ”์„œ๋“œ์˜ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฐ ์žˆ๋‹ค.

- @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์„ ์ง์ ‘ ๋‹ฌ์ง€ ์•Š์•„๋„ ๋˜๊ณ , ์‹ค์ˆ˜๋กœ ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•  ๊ฑฑ์ •๋„ ์—†๋‹ค.

ยท ์ด ๋ฐฉ์‹์€ ๋‹จ์ ์€ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๊ฐ€ ์‚ด์ง ์ง€์ €๋ถ„ํ•ด์ง€๊ณ , ์†๋„๊ฐ€ ์กฐ๊ธˆ ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ •๋„๋‹ค.

ยท ์ด ๋ฐฉ์‹์€ ์œ„์˜ toArray ๋ฉ”์„œ๋“œ์ฒ˜๋Ÿผ varargs ๋ฉ”์„œ๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ๊ฒŒ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ƒํ™ฉ์—๋„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

- ์ด toArray์˜ List ๋ฒ„์ „์ด ๋ฐ”๋กœ ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” List.of๋‹ค.

static <T> List<T> pickTwo(T a, T b, T c) {
    switch( ThreadLocalRandom.current().nextInt(3)) {
        case 0: return List.of(a, b);
        case 1: return List.of(a, c);
        case 2: return List.of(b, c);
    }
    throw new AssertionError();
}
public static void main(String[] args) {
    List<String> attributes = pickTwo("์ข‹์€", "๋น ๋ฅธ", "์ €๋ ดํ•œ");
        }

์•„์ดํ…œ 33. ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ณ ๋ คํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์ปฌ๋ ‰์…˜ API๋กœ ๋Œ€ํ‘œ๋˜๋Š” ์ผ๋ฐ˜์ ์ธ ์ œ๋„ค๋ฆญ ํ˜•ํƒœ์—์„œ๋Š” ํ•œ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ˆ˜๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปจํ…Œ์ด๋„ˆ ์ž์ฒด๊ฐ€ ์•„๋‹Œ ํ‚ค๋ฅผ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ”๊พธ๋ฉด ์ด๋Ÿฐ ์ œ์•ฝ์ด ์—†๋Š” ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

- ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ด๋„ˆ๋Š” Class๋ฅผ ํ‚ค๋กœ ์“ฐ๋ฉฐ, ์ด๋Ÿฐ ์‹์œผ๋กœ ์“ฐ์ด๋Š” Class ๊ฐ์ฒด๋ฅผ ํƒ€์ž… ํ† ํฐ์ด๋ผ ํ•œ๋‹ค.

- ์ง์ ‘ ๊ตฌํ˜„ํ•œ ํ‚ค ํƒ€์ž…๋„ ์“ธ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์ปจ๋Œ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ–‰(์ปจํ…Œ์ด๋„ˆ)์„ ํ‘œํ˜„ํ•œ DatabaseRow ํƒ€์ž…์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์ธ Column<T>๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹จ์ผ ์›์†Œ ์ปจํ…Œ์ด๋„ˆ

ยท ์ œ๋„ค๋ฆญ์€ Set<E>, Map<K, V> ๋“ฑ ๋‹จ์ผ์›์†Œ ์ปจํ…Œ์ด๋„ˆ์— ํ”ํžˆ ์“ฐ์ธ๋‹ค.

ยท ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์˜ ์ˆ˜๋Š” ์ œํ•œ๋œ๋‹ค.

- ์›์ธ: ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋˜๋Š” ๋Œ€์ƒ์€ ์›์†Œ๊ฐ€ ์•„๋‹Œ ์ปจํ…Œ์ด๋„ˆ ์ž์‹ ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ์ปจํ…Œ์ด๋„ˆ์˜ ์ผ๋ฐ˜์ ์ธ ์šฉ๋„์— ๋งž๊ฒŒ ์„ค๊ณ„๋œ ๊ฒƒ์ด๋‹ˆ ๋ฌธ์ œ๋  ๊ฑด ์—†๋‹ค. Set์—๋Š” ์›์†Œ ํƒ€์ž…์„ ๋œปํ•˜๋Š” ๋‹จ ํ•˜๋‚˜์˜ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ์žˆ์œผ๋ฉด ๋˜๊ณ , Map์—๋Š” ํ‚ค์™€ ๊ฐ’์ด ํƒ€์ž…์„ ๋œปํ•˜๋Š” 2๊ฐœ๋งŒ ํ•„์š”ํ•œ ์‹์ด๋‹ค.

ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ด๋„ˆ

ยท ์œ„์—์„œ ๋งํ•œ ์‚ฌ๋ก€๋ณด๋‹ค ๋” ์œ ์—ฐํ•œ ์ˆ˜๋‹จ์ด ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์ข…์ข… ์žˆ๋‹ค.

ex) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ–‰์€ ์ž„์˜ ๊ฐœ์ˆ˜์˜ ์—ด์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ชจ๋‘ ์—ด์„ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ฉ‹์งˆ ๊ฒƒ์ด๋‹ค.

ยท ์ปจํ…Œ์ด๋„ˆ ๋Œ€์‹  ํ‚ค๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•œ ๋‹ค์Œ, ์ปจํ…Œ์ด๋„ˆ์— ๊ฐ’์„ ๋„ฃ๊ฑฐ๋‚˜ ๋บ„ ๋•Œ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•œ ํ‚ค๋ฅผ ํ•จ๊ป˜ ์ œ๊ณตํ•˜๋Š” ์‹์œผ๋กœ ์œ„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ œ๋„ค๋ฆญ ํƒ€์ž… ์‹œ์Šคํ…œ์ด ๊ฐ’์˜ ํƒ€์ž…์ด ํ‚ค์™€ ๊ฐ™์Œ์„ ๋ณด์žฅํ•ด ์ค€๋‹ค.

- ์ด๋Ÿฌํ•œ ์„ค๊ณ„ ๋ฐฉ์‹์„ ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ดํ„ฐ ํŒจํ„ด(type safe heterogeneous container pattern)์ด๋ผ๊ณ  ํ•œ๋‹ค.

์˜ˆ์‹œ - ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Favorites ํด๋ž˜์Šค

ํƒ€์ž…๋ณ„๋กœ ์ฆ๊ฒจ ์ฐพ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•˜๊ณ , ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” Favorites ํด๋ž˜์Šค๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.

ยท ๊ฐ ํƒ€์ž…์˜ Class ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•œ ํ‚ค ์—ญํ• ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์ด ๋ฐฉ์‹์ด ๋™์ž‘ํ•˜๋Š” ์ด์œ ๋Š” class์˜ ํด๋ž˜์Šค๊ฐ€ ์ œ๋„ค๋ฆญ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- class ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์€ Class๊ฐ€ ์•„๋‹Œ Class<T>๋‹ค.

ex) String.class ํƒ€์ž…์€ Class<String>์ด๊ณ  Integer.class์˜ ํƒ€์ž…์€ Class<Integer>์ด๋‹ค.

- ์ปดํŒŒ์ผํƒ€์ž„ ํƒ€์ž… ์ •๋ณด์™€ ๋Ÿฐํƒ€์ž„ ํƒ€์ž… ์ •๋ณด๋ฅผ ์•Œ์•„๋‚ด๊ธฐ ์œ„ํ•ด ๋ฉ”์„œ๋“œ๋“ค์ด ์ฃผ๊ณ  ๋ฐ›๋Š” class ๋ฆฌํ„ฐ๋Ÿด์„ ํƒ€์ž… ํ† ํฐ(type token)์ด๋ผ ํ•œ๋‹ค.

public class Favorites {
    public <T> void putFavorites(Class<T> type, T instance);
        public <T> T getFavorites(Class<T> type);
            }

์œ„ ์ฝ”๋“œ๋Š” Favorites ํด๋ž˜์Šค์˜ API๋กœ, ํ‚ค๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋˜์—ˆ๋‹ค๋Š” ์ ๋งŒ ๋นผ๋ฉด ์ผ๋ฐ˜ ๋งต์ฒ˜๋Ÿผ ๋ณด์ผ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์–ป์–ด์˜ฌ ๋•Œ Class ๊ฐ์ฒด๋ฅผ ์•Œ๋ ค์ฃผ๋ฉด ๋œ๋‹ค.

๋‹ค์Œ์€ Favorites ํด๋ž˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ๋‹ค. ์ฆ๊ฒจ ์ฐพ๋Š” String, Integer, Class ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅ, ๊ฒ€์ƒ‰, ์ถœ๋ ฅํ•˜๊ณ  ์žˆ๋‹ค.

์ด ํ”„๋กœ๊ทธ๋žจ์€ ๊ธฐ๋Œ€ํ•œ ๋Œ€๋กœ Java cafebabe Favorites๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

public static void main(String[] args) {
    Favorites f = new Favorites();
    
    f.putFavorites(String.class, "Java");
    f.putFavorites(Integer.class, 0xcafebabe);
    f.putFavorites(Class.class, Favorites.class);
    
    String favoriteString = f.getFavorites(String.class);
    int favoriateInteger = f.getFavorites(Integer.class);
    Class<?> favoriateClass = f.getFavorites(Class.class);
    
    System.out.printf("%s %x %s%n", favoriteString,
        favoriateInteger, favoriateClass.getName());
}

ยท Favorites ์ธ์Šคํ„ด์Šค์˜ ์žฅ์ : 1. ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค.

- String์„ ์š”์ฒญํ–ˆ๋Š”๋ฐ, Integer๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ผ์€ ์—†๋‹ค.

2. ๋ชจ๋“  ํ‚ค์˜ ํƒ€์ž…์ด ์ œ๊ฐ๊ฐ์ด๋ผ, ์ผ๋ฐ˜์ ์ธ ๋งต๊ณผ ๋‹ฌ๋ฆฌ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํƒ€์ž…์˜ ์›์†Œ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.

- Favorites๋Š” ํƒ€์ž… ์•ˆ์ „ ์ด์ข…(heterogeneous) ์ปจํ…Œ์ด๋„ˆ๋ผ ํ•  ๋งŒํ•˜๋‹ค.

// ํƒ€์ž… ์•ˆ์ „ ์ด์ข… ์ปจํ…Œ์ด๋„ˆ ํŒจํ„ด - ๊ตฌํ˜„
public class Favorites {
    
    private Map<Class<?>, Object> favorites = new HashMap<>();
        
        public <T> void putFavorites(Class<T> type, T instance) {
            favorites.put(Objects.requireNonNull(type), instance);
        }
        
        public <T> T getFavorites(Class<T> type) {
            return type.cast(favorites.get(type));
        }
        }

ยท favorites์˜ ํƒ€์ž…์€ Map<Class<?>, Object>์ด๋‹ค.

๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด๋ผ ์ด ๋งต ์•ˆ์— ์•„๋ฌด๊ฒƒ๋„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‚ฌ์‹ค์€ ๊ทธ ๋ฐ˜๋Œ€๋‹ค. ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด ์ค‘์ฒฉ(nested)๋˜์—ˆ๋‹ค๋Š” ์ ์„ ๊นจ๋‹ฌ์•„์•ผ ํ•œ๋‹ค. ๋งต์ด ์•„๋‹ˆ๋ผ ํ‚ค๊ฐ€ ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ธ ๊ฒƒ์ด๋‹ค. ์ด๋Š” ๋ชจ๋“  ํ‚ค๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

- ๋‹ค์–‘ํ•œ ํƒ€์ž…์„ ์ง€์›ํ•˜๋Š” ํž˜์ด ์—ฌ๊ธฐ์„œ ๋‚˜์˜จ๋‹ค.

ex) Class<String>, Class<Integer>

ยท favorites ๋งต์˜ ๊ฐ’ ํƒ€์ž…์€ ๋‹จ์ˆœํžˆ Object๋‹ค.

์ด ๋งต์€ ํ‚ค์™€ ๊ฐ’ ์‚ฌ์ด์˜ ํƒ€์ž… ๊ด€๊ณ„๋ฅผ ๋ณด์ฆํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ง์ด๋‹ค. ์ฆ‰, ๋ชจ๋“  ๊ฐ’์ด ํ‚ค๋กœ ๋ช…์‹œํ•œ ํƒ€์ž…์ž„์„ ๋ณด์ฆํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ž๋ฐ”์˜ ํƒ€์ž… ์‹œ์Šคํ…œ์—์„œ๋Š” ์ด ๊ด€๊ณ„๋ฅผ ๋ช…์‹œํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์ด ๊ด€๊ณ„๊ฐ€ ์„ฑ๋ฆฝํ•จ์„ ์•Œ๊ณ  ์žˆ๊ณ , ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฅผ ๊ฒ€์ƒ‰ํ•  ๋•Œ ๊ทธ ์ด์ ์„ ๋ˆ„๋ฆฌ๊ฒŒ ๋œ๋‹ค.

ยท putFavorites๋Š” ์ฃผ์–ด์ง„ Class ๊ฐ์ฒด์™€ ์ฆ๊ฒจ์ฐพ๊ธฐ ์ธ์Šคํ„ด์Šค๋ฅผ favorites์— ์ถ”๊ฐ€ํ•ด ๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค.

ยท getFavorites ์ฝ”๋“œ๋Š” ์ฃผ์–ด์ง„ Class ๊ฐ์ฒด์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์„ favorites ๋งต์—์„œ ๊บผ๋‚ธ๋‹ค.

์ด ๊ฐ์ฒด๊ฐ€ ๋ฐ”๋กœ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•  ๊ฐ์ฒด๊ฐ€ ๋งž์ง€๋งŒ, ์ž˜๋ชป๋œ ์ปดํŒŒ์ผํƒ€์ž„ ํƒ€์ž…์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์ด ๊ฐ์ฒด์˜ ํƒ€์ž…์€ favorites ๋งต์˜ ๊ฐ’ ํƒ€์ž…์ธ Object์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋ฅผ T๋กœ ๋ฐ”๊ฟ” ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.

- ์ฆ‰, getFavorite ๊ตฌํ˜„์€ Class cast ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ Class ๊ฐ์ฒด๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํƒ€์ž…์œผ๋กœ ๋™์  ํ˜•๋ณ€ํ™˜ํ•œ๋‹ค.

- cast ๋ฉ”์„œ๋“œ๋Š” ํ˜•๋ณ€ํ™˜ ์—ฐ์‚ฐ์ž์˜ ๋™์  ๋ฒ„์ „์ด๋‹ค. ์ฃผ์–ด์ง„ ์ธ์ˆ˜๊ฐ€ Class ๊ฐ์ฒด๊ฐ€ ์•Œ๋ ค์ฃผ๋Š” ํƒ€์ž… ์ธ์Šคํ„ด์Šค์ธ์ง€ ๊ฒ€์‚ฌํ•˜์—ฌ ๋งž๋‹ค๋ฉด ๊ทธ ์ธ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์•„๋‹ˆ๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค.

ยท cast ๋ฉ”์„œ๋“œ๊ฐ€ ์ธ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋งŒ ํ•˜๋Š”๋ฐ, ๊ตณ์ด ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ํ•ด๋‹น ๋ฉ”์„œ๋“œ์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ Class ํด๋ž˜์Šค๊ฐ€ ์ œ๋„ค๋ฆญ์ด๋ผ๋Š” ์ด์ ์„ ์™„๋ฒฝํžˆ ํ™œ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

cast์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์€ Class ๊ฐ์ฒด์˜ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๊ฐ™๋‹ค.

public class Class<T> {
    T cast(Object obj);
}

์ด๊ฒƒ์€ getFavorite ๋ฉ”์„œ๋“œ์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์œผ๋กœ, T๋กœ ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜ํ•˜๋Š” ์†์‹ค ์—†์ด๋„ Favorites๋ฅผ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋น„๊ฒฐ์ด๋‹ค.

ยท Favorites ํด๋ž˜์Šค์˜ ์ œ์•ฝ:

1. ์•…์˜์ ์ธ ํด๋ผ์ด์–ธํŠธ๊ฐ€ Class ๊ฐ์ฒด๋ฅผ ๋กœ ํƒ€์ž…(์•„์ดํ…œ 26)์œผ๋กœ ๋„˜๊ธฐ๋ฉด Favorites ์ธ์Šคํ„ด์Šค์˜ ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ์‰ฝ๊ฒŒ ๊นจ์ง„๋‹ค.

- ํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ์ปดํŒŒ์ผํ•  ๋•Œ ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๊ฐ€ ๋œฐ ๊ฒƒ์ด๋‹ค.

Favorites๊ฐ€ ํƒ€์ž… ๋ถˆ๋ณ€์‹์„ ์–ด๊ธฐ๋Š” ์ผ์ด ์—†๋„๋ก ๋ณด์žฅํ•˜๋ ค๋ฉด putFavorites ๋ฉ”์„œ๋“œ์—์„œ ์ธ์ˆ˜๋กœ ์ฃผ์–ด์ง„ instance์˜ ํƒ€์ž…์ด type์œผ๋กœ ๋ช…์‹œํ•œ ํƒ€์ž…๊ณผ ๊ฐ™์€์ง€ ํ™•์ธํ•˜๋ฉด ๋œ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋™์  ํ˜•๋ณ€ํ™˜์„ ์‚ฌ์šฉํ•œ๋‹ค.

public <T> void putFavorites(Class<T> type, T instance) {
    favorites.put(Objects.requireNonNull(type), type.cast(instance));
}

java.util.collection์—๋Š” checkedSet, checkedList, checkedMap ๊ฐ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š”๋ฐ, ๋ฐ”๋กœ ์ด ๋ฐฉ์‹์„ ์ ์šฉํ•œ ์ปฌ๋ ‰์…˜ ๋ž˜ํผ๋“ค์ด๋‹ค.

์ด ์ •์  ํŒฉํ„ฐ๋ฆฌ๋“ค์€ ์ปฌ๋ ‰์…˜(ํ˜น์€ ๋งต)๊ณผ ํ•จ๊ป˜ 1๊ฐœ(ํ˜น์€ 2๊ฐœ)์˜ Class ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š”๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋“ค์€ ๋ชจ๋‘ ์ œ๋„ค๋ฆญ์ด๋ผ Class ๊ฐ์ฒด์™€ ์ปฌ๋ ‰์…˜์˜ ์ปดํŒŒ์ผํƒ€์ž„ ํƒ€์ž…์ด ๊ฐ™์Œ์„ ๋ณด์žฅํ•œ๋‹ค. ๋˜ํ•œ ์ด ๋ž˜ํผ๋“ค์€ ๋‚ด๋ถ€ ์ปฌ๋ ‰์…˜๋“ค์„ ์‹ค์ฒดํ™”ํ•œ๋‹ค. ์ด ๋ž˜ํผ๋“ค์€ ์ œ๋„ค๋ฆญ๊ณผ ๋กœ ํƒ€์ž…์„ ์„ž์–ด ์‚ฌ์šฉํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๊ฐ€ ์ปฌ๋ ‰์…˜์— ์ž˜๋ชป๋œ ํƒ€์ž…์˜ ์›์†Œ๋ฅผ ๋„ฃ์ง€ ๋ชปํ•˜๊ฒŒ ์ถ”์ ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค€๋‹ค.

ex) ๋Ÿฐํƒ€์ž„์— Coin์„ Collection<Stamp>์— ๋„ฃ์œผ๋ ค ํ•˜๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค.

2. ์‹ค์ฒดํ™” ๋ถˆ๊ฐ€ ํƒ€์ž…(์•„์ดํ…œ 28)์—๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

- ์ฆ‰, String์ด๋‚˜ String[]์€ ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด๋„ List<String>์€ ์ €์žฅํ•  ์ˆ˜ ์—†๋‹ค. ์ €์žฅํ•˜๋ คํ•˜๋ฉด ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ๋˜์ง€ ์•Š๋Š”๋‹ค. List<String>์šฉ Class๋ฅผ ์–ป์„ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ํ•ด๋‹น ์ œ์•ฝ์— ๋Œ€ํ•œ ๋งŒ์กฑ์Šค๋Ÿฌ์šด ์šฐํšŒ๋กœ๋Š” ์—†๋‹ค.

- (์˜ฎ๊ธฐ์ด) ํ•ด๋‹น ์ œ์•ฝ์„ ์Šˆํผ ํƒ€์ž… ํ† ํฐ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ์‹œ๋„๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๋ฐฉ๋ฒ•๋„ ์™„๋ฒฝํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜์ž.

TODO: ์Šˆํผ ํƒ€์ž… ํ† ํฐ(super type token)

ยท Favorites๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ํƒ€์ž… ํ† ํฐ์€ ๋น„ํ•œ์ •์ ์ด๋‹ค.

- ์ฆ‰, getFavorite์™€ putFavorite๋Š” ์–ด๋–ค Class ๊ฐ์ฒด๋“  ๋ฐ›์•„๋“ค์ธ๋‹ค.

- ์ด ๋ฉ”์„œ๋“œ๋“ค์ด ํ—ˆ์šฉํ•˜๋Š” ํƒ€์ž…์„ ์ œํ•œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•œ์ • ํƒ€์ž… ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์ž.

- ํ•œ์ • ํƒ€์ž… ํ† ํฐ: ํ•œ์ •์  ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜(์•„์ดํ…œ 29)๋‚˜ ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ(์•„์ดํ…œ 31)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„ ๊ฐ€๋Šฅํ•œ ํƒ€์ž…์„ ์ œํ•œํ•˜๋Š” ํƒ€์ž… ํ† ํฐ

ยท ์• ๋„ˆํ…Œ์ด์…˜ API(์•„์ดํ…œ 39)๋Š” ํ•œ์ •์  ํƒ€์ž… ํ† ํฐ์„ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” AnnotatedElement ์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋กœ ๋Œ€์ƒ ์š”์†Œ์— ๋‹ฌ๋ ค ์žˆ๋Š” ์• ๋„ˆํ…Œ์ด์…˜์„ ๋Ÿฐํƒ€์ž…์— ์ฝ์–ด์˜จ๋‹ค.

publc <T extends Annotation>
    T getAnnoTation(Class<T> annotationType);

์ด ๋ฉ”์„œ๋“œ๋Š” ๋ฆฌํ”Œ๋ ‰์…˜์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ํƒ€์ž…๋“ค(java.lang.Class<T>, java.lang.reflect.Method, java.lang,reflect.Field)์„ ํ”„๋กœ๊ทธ๋žจ ์š”์†Œ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ํƒ€์ž…๋“ค์—์„œ ๊ตฌํ˜„ํ•œ๋‹ค.

annotationType ์ธ์ˆ˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜ ํƒ€์ž…์„ ๋œปํ•˜๋Š” ํ•œ์ •์  ํƒ€์ž… ํ† ํฐ์ด๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ํ† ํฐ์œผ๋กœ ๋ช…์‹œํ•œ ํƒ€์ž…์˜ ์• ๋„ˆํ…Œ์ด์…˜์ด ๋Œ€์ƒ ์š”์†Œ์— ๋‹ฌ๋ ค ์žˆ๋‹ค๋ฉด ๊ทธ ์• ๋„ˆํ…Œ์ด์…˜์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—†๋‹ค๋ฉด null์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- ์ฆ‰, ์• ๋„ˆํ…Œ์ด์…˜๋œ ์š”์†Œ๋Š” ๊ทธ ํ‚ค๊ฐ€ ์• ๋„ˆํ…Œ์ด์…˜ ํƒ€์ž…์ธ ํƒ€์ž… ์ด์ข… ์ปจํ…Œ์ด๋„ˆ๋‹ค.

Class<?> ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ํ•œ์ •์  ํƒ€์ž… ํ† ํฐ์„ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ(getAnnotation)์— ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค๋ฉด?

๊ฐ์ฒด๋ฅผ Class<? extends Annotaion>์œผ๋กœ ํ˜•๋ณ€ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ด ํ˜•๋ณ€ํ™˜์€ ๋น„๊ฒ€์‚ฌ์ด๋ฏ€๋กœ ์ปดํŒŒ์ผํ•˜๋ฉด ๊ฒฝ๊ณ ๊ฐ€ ๋œฌ๋‹ค(์•„์ดํ…œ 27).

Class ํด๋ž˜์Šค๋Š” ์ด๋Ÿฐ ํ˜•๋ณ€ํ™˜์„ ์•ˆ์ „ํ•˜๊ณ , ๋™์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•ด์ฃผ๋Š” asSubClass ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Š” ํ˜ธ์ถœ๋œ ์ธ์Šคํ„ด์Šค ์ž์‹ ์˜ Class ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๊ฐ€ ๋ช…์‹œํ•œ ํด๋ž˜์Šค๋กœ ํ˜•๋ณ€ํ™˜ํ•œ๋‹ค.

- ํ˜•๋ณ€ํ™˜๋œ๋‹ค๋Š” ๊ฒƒ์€ ์ด ํด๋ž˜์Šค๊ฐ€ ์ธ์ˆ˜๋กœ ๋ช…์‹œํ•œ ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋ผ๋Š” ๋œป์ด๋‹ค.

ํ˜•๋ณ€ํ™˜์— ์„ฑ๊ณตํ•˜๋ฉด ์ธ์ˆ˜๋กœ ๋ฐ›์€ ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์‹คํŒจํ•˜๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค.

๋‹ค์Œ์€ ์ปดํŒŒ์ผ ์‹œ์ ์—๋Š” ํƒ€์ž…์„ ์•Œ ์ˆ˜ ์—†๋Š” ์• ๋„ˆํ…Œ์ด์…˜์„ asSubclass ๋ฉ”์„œ๋“œ๋ฅผ ๋Ÿฐํƒ€์ž„์— ์ฝ์–ด๋‚ด๋Š” ์˜ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์˜ค๋ฅ˜๋‚˜ ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ ๋œ๋‹ค.

static Annotation getAnnotation(AnnotatedElement element, String annotationTypeName) {
    Class<?> annotationType = null;   // ๋น„ํ•œ์ •์  ํƒ€์ž… ํ† ํฐ
    try{
        annotationType = Class.forName(annotationTypeName);
    } catch( Exception ex){
        throw new IllegalArgumentException(ex);
    }
    // asSubclass ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ClassCastException ์„ ๋˜์ง„๋‹ค
    return element.getAnnotation( annotationType.asSubclass(Annotation.class));
}

์˜ฎ๊ธด์ด์˜ ๋ง


ยท ๋งค๊ฐœ๋ณ€์ˆ˜(parameter)๋Š” ๋ฉ”์„œ๋“œ์— ์„ ์–ธํ•œ ๋ณ€์ˆ˜์ด๊ณ , ์ธ์ˆ˜(argument)๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ๋„˜๊ธฐ๋Š” '์‹ค์ ฏ๊ฐ’'์ด๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ์—์„œ value๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์ด๊ณ  10์€ ์ธ์ˆ˜๋‹ค.

void add(int value) {...}
add(10)

์ด ์ •์˜๋ฅผ ์ œ๋„ค๋ฆญ๊นŒ์ง€ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ์—์„œ T๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋˜๊ณ , Integer๋Š” ํƒ€์ž… ์ธ์ˆ˜๊ฐ€ ๋œ๋‹ค.

์ž๋ฐ” ์–ธ์–ด ๋ช…์„ธ์—์„œ๋Š” ์ด๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ณ  ์žˆ๋‹ค.

class Set<T> { ... }
    Set<Integer> = ...;

Last updated