Closed Leeyerimearth closed 2 years ago
저는 아이템 33의 교훈(?)을 클래스 리터럴을 적극적으로 활용하라는 것으로 봤습니다. 실제로 컬렉션을 배열로 변환해주는 메서드는 있으나, @SuppressWarnings을 사용하고 있더라구요. 예를 들어 java.util.ArrayList를 보면 5번째 줄에서 비검사 형변환 경고가 뜹니다.
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
toArray의 매개변수로 클래스 리터럴을 사용해보는 메서드를 만들어봤습니다. 리터럴을 사용하니 형변환 경고가 뜨지 않았습니다. 제가 제대로 한 건지는 모르겠습니다...🤣
class WrappedArrayList<T> {
private final Object[] elementData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
private final int size = 10;
public <A> A[] toArray(Class<A[]> type) {
// 비검사 형변환 경고가 뜨지 않습니다.
return Arrays.copyOf(elementData, size, type);
}
}
public static void main(String[] args) {
var b = new WrappedArrayList<Integer>();
Integer[] c = b.toArray(Integer[].class);
}
민성님이 하신 말씀에 덧붙여서 이야기 해보겠습니다 호호하하
제네릭 컬렉션에서는 자신의 원소 타입을 담은 배열을 반환하는 게 보통은 불가능하다.
이제 보통이 아닌 케이스들을 하나씩 보게 될텐데
먼저 29장 이왕이면 제네릭 타입으로 만들라 - 171p 예시를 보면
new E[INITIAL_CAPACITY]; 와 같은 실체화 불가 타입으로 배열을 만들 수 없다.
그래서 29장에서는 다음의 예시에서 이를 우회하는 방법을 두가지 말해줍니다.
1. E[] elements = (E[]) new Object[INITIAL_CAPACITY]
와 같이 변경해줍니다.
-- 이 경우 E[]는 object[]의 하위타입이므로 바뀌지만 object[]안에 어떤것이든 들어갈 수 있으니 런타임 안정성이 떨어집니다
2. object[] element
로 변경하고, (E) elements[size]
와 같이 값을 꺼낼때마다 E로 형변환 해줍니다.
-- 이경우 element에 넣어주는 것이 E라는 것을 개발자는 알고있지만 컴파일러는 알아볼수 없습니다.
심지어 이런 경우에는 컴파일러가 보장할수없으니
저희가 @SuppressWarnings("unchecked")
와 같은 문구로 내가 봤는데 안전할거야(?) 라고 약속을 또 해줘야 합니다.
여기서 이렇게 제네릭 배열(?) 을 우회해서 사용하는것이 귀찮고 덜 안전하다는 사실을 알 수 있습니다.
이제 33장을 보면 새롭게 우회할 수 있는 방법을 알려줍니다.
3. 클래스리터럴 (String.class, Integer.class) 을 이용한 방법인데,
이는 위에서 말한 E[]같은걸 반환은 하지만 타입 안전하지 않은 상황을 해결해줍니다.
여기서 마지막 type.cast(favirotes.get(type))
이부분에서 컴파일 에러를 발생시킬 수 있습니다.
타입토큰을 사용하면 Integer[]와 String[]를 잘 반환할 수 있습니다..
결과적으로는 이렇게 본인에 타입매개변수를 직접 사용하는것이 아니라
키를(여기서는 Class) -> 타입 매개변수로 사용하면
타입 안전 이종 컨테이너
(컬렉션)라고 하고, 이를 사용하면 맨 위에서 시작한 질문인
자신의 원소 타입을 담은 배열을 타입 안전하게 반환할 수 있다는 것 같습니다..
-> 컬렉션에 이미 구현되어있는 메서드 중에서 컬렉션을 배열로 변환해주는 메서드가 없다는 뜻 인가요?
컬렉션이 데이터를 담는 컨테이너라고 생각한다면 제네릭한 배열은 생성할 수 없기 때문에(new E[INITIAL_CAPACITY];) 제네릭한 배열을 (안전하게) 반환해주는 방법 또한 없다- 라는 의미인 것 같습니다!
166p.의 3번째 문단의 내용이 이해가 가지 않습니다. 혹시 설명해주실 분 계신가요?
이 뜻이, 컬렉션에 이미 구현되어있는 메서드 중에서 컬렉션을 배열로 변환해주는 메서드가 없다는 뜻 인가요? 아이템 33에서는 가능한 방법을 설명해준다는데.. 봐..봐도 모르겠습니다 🥲 아이템 33에 배열로 반환하는게 있던가요