item 32 Jung inchul - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

Effective Java 3e ์•„์ดํ…œ 32๋ฅผ ์š”์•ฝํ•œ ๋‚ด์šฉ ์ž…๋‹ˆ๋‹ค.

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

warning: [unchecked] Possible heap pollution from 
    parameterized vararg type List<String>

๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์˜ ๋ณ€์ˆ˜๊ฐ€ ํƒ€์ž…์ด ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ํž™ ์˜ค์—ผ์ด ๋ฐœ์ƒํ•œ๋‹ค. ๋‹ค์Œ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด๋ณด์ž.

static void danferous(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 ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹ค๋ฌด์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์‚ฌ์‹ค ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ์—ฌ๋Ÿฟ ์ œ๊ณตํ•˜๋Š”๋ฐ, **Arrays.asList(T... a), Collections.addAll(Collection<? super T> c, T... elements), EnumSet.of(E first, E...rest)**๊ฐ€ ๋Œ€ํ‘œ์ ์ด๋‹ค.

๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๋Š” ์ด ๊ฒฝ๊ณ  ๋“ค์„ ๊ทธ๋ƒฅ ๋‘๊ฑฐ๋‚˜ (๋” ํ”ํ•˜๊ฒŒ๋Š”) ํ˜ธ์ถœํ•˜๋Š” ๊ณณ๋งˆ๋‹ค @SuppressWarnings("unchkecked") ์—๋„ˆํ…Œ์ด์…˜์„ ๋‹ฌ์•„ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ฒจ์•ผ ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ž๋ฐ” 7์—์„œ๋Š” @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์ด ์ถ”๊ฐ€๋˜์–ด ์ œ๋„ค๋ฆญ ๊ฐ€๋ณ€์ธ์ˆ˜ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. @SafeVarargs ์• ๋„ˆํ…Œ์ด์…˜์€ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ์ž๊ฐ€ ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ํƒ€์ž… ์•ˆ์ „ํ•จ์„ ๋ณด์žฅํ•˜๋Š” ์žฅ์น˜๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด ์•ฝ์†์„ ๋ฏฟ๊ณ  ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ์•ˆ์ „ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒฝ๊ณ ๋ฅผ ๋” ์ด์ƒ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

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

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

static <T> T[] toArray(T... args) {
    return args;
}

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

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, b);
    case 2: return toArray(a, b);
    }
    throw new AssertionError(); // ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋‹ค. 
}

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

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

์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ˆ ๋ณ„๋‹ค๋ฅธ ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์‹คํ–‰ํ•˜๋ ค ๋“ค๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค. Object[]๋Š” String[]์˜ ํ•˜์œ„ ํƒ€์ž…์ด ์•„๋‹ˆ๋ฏ€๋กœ ์ด ํ˜•๋ณ€ํ™˜์€ ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

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

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

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

@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;
}

์ •๋ฆฌ

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

โš ๏ธ **GitHub.com Fallback** โš ๏ธ