이펙티브 자바
아이템 28. 배열보단 리스트를 사용하라
배열은 A가 B의 하위 타입이면 A[]이 B[]의 하위타입이다. 하지만 제네릭은 List< A > 가 List< B >의 하위타입은 아니다 그래서 불변이다.
어떻게 보면 제네릭이 문제가 있는것 처럼 보이지만 문제는 배열이다.
1 2 3 4 5 6 7 8 9 10 11
| package com.github.sejoung.codetest.generics;
public class Test { public static void main(String[] args) { Object[] objects = new String[2]; objects[0] = 12; } }
|
실행결과
1 2 3 4 5 6
| Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer at com.github.sejoung.codetest.generics.Test.main(Test.java:6)
Process finished with exit code 1
|
위에 코드는 컴파일시에는 문제가 없지만 실행시에 에러가 난다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.github.sejoung.codetest.generics;
import java.util.ArrayList; import java.util.List;
public class Test { public static void main(String[] args) { List<Object> objects = new ArrayList<String>(); objects.add(12); } }
|
이미 위에 코드는 컴파일시에 에러가 난다.
위와 비슷한 코드로
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.github.sejoung.codetest.generics;
import java.util.*; import java.util.concurrent.ThreadLocalRandom;
public class ChooserOld { private final Object[] choiceArray;
public ChooserOld(Collection choices) { choiceArray = choices.toArray(); }
public Object choose() { Random rnd = ThreadLocalRandom.current(); return choiceArray[rnd.nextInt(choiceArray.length)]; }
public static void main(String[] args) { List<String> stringList = Arrays.asList("1","A");
ChooserOld chooser = new ChooserOld(stringList);
for (int i = 0; i < 10; i++) { Integer choice = (Integer) chooser.choose(); System.out.println(choice); } } }
|
위에 코드를 제네릭으로 바꾸면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.github.sejoung.codetest.generics;
import java.util.*; import java.util.concurrent.ThreadLocalRandom;
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())); }
public static void main(String[] args) { List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6); List<String> stringList = Arrays.asList("1","A");
Chooser<String> chooser = new Chooser<>(stringList);
for (int i = 0; i < 10; i++) { String choice = chooser.choose(); System.out.println(choice); } } }
|
위와 같은 코드로 된다. 조금 느리지만 런타임시에 클래스케스팅 에러를 만나지 않으니 더 안전한 코드가 되었다.
참조