java-squid / effective-java

effective java 3e study
105 stars 38 forks source link

[아이템 28] 배열보다는 리스트를 사용하라 #28

Closed wooody92 closed 3 years ago

102092 commented 4 years ago

28-2 code

102092 commented 4 years ago

배열을 제네릭으로 만들 수 없어 귀찮을 때도 있다..

david215 commented 4 years ago

@102092

  • 제네릭 배열 생성을 허용하지 않는 이유에 대해 조금만 더 쉽게 설명해주실 수 있나요?
  • 책 내용은 읽었는데, 이해가 된듯 안된듯 한 느낌을 받고 있네요.

제네릭 도입과 사용의 가장 큰 목적이 type safety인데 제네릭 배열 생성을 허용하는 경우에 책에서 나왔던 예시와 같이 런타임 에러가 발생하는 경우가 발생하게 되죠. 제네릭 배열 생성을 금지함으로써 에러를 모두 컴파일 타임에 잡히도록 강제한 것이죠 (물론 경고 억제가 있기는 하지만)

kses1010 commented 4 years ago

아이템 28을 읽으면서 느낀점은 배열이 리스트에 비해 성능이 약간 좋을 뿐 단점이 너무 많다고 생각했습니다. 그렇다면 배열을 적극적으로 쓰이는 곳은 어디일까요? 그래서 파이썬은 배열을 없애고 처음부터 리스트를 도입한 걸까요?

david215 commented 4 years ago

@102092

배열을 제네릭으로 만들 수 없어 귀찮을 때도 있다..

  • 이 뒤에 나오는 여러가지 상황에 대해 조금 더 설명 해주셨으면 합니다.
  • 내용이 좀 어렵네요...ㅠㅠ
List<String> l = new ArrayList<>();
l.add("hello");
l.add("world");
String[] a = l.toArray(new String[0]);
for (String s : a) {
     System.out.println(s);
}

위에 예시와 같이 <T> T[] toArray(T[] a) 제네릭 메소드를 사용해 Collection<E> 객체를 E[]로 변환하는 것이 가능하기는 합니다. 매개변수로 new String[0]와 같이 지정 타입의 비어있는 배열을 넘겨주는 것을 볼 수 있습니다.
하지만 원소 타입 자체가 제네릭인 경우에는 new E[0]와 같은 제네릭 배열 생성이 불가능하기 때문에 위와 같은 방법으로는 배열로 변환할 수 없습니다.

List<List<String>> l = new ArrayList<>();
l.add(List.of("hello"));
l.add(List.of("world"));
List<String>[] a = l.toArray(new List<String>[0]); // generic array creation error
    for (List<String> sl : a) {
        for (String s : sl) {
            System.out.println(s);
        }
    }
}


뒤에 나오는 vararg에 대한 내용은 나중에 해당 아이템들이 나올 때 천천히 봐야할 거 같네요.

david215 commented 4 years ago

@kses1010

아이템 28을 읽으면서 느낀점은 배열이 리스트에 비해 성능이 약간 좋을 뿐 단점이 너무 많다고 생각했습니다. 그렇다면 배열을 적극적으로 쓰이는 곳은 어디일까요?

컬렉션 프레임워크 같이 로우 레벨로 들어가는 경우에는 성능도 절대 무시할 수 없겠죠. 또 컬렉션을 사용하는 경우에 해당 코드가 전체 성능의 병목이 되는 경우에도 고려를 해봐야겠죠.

그래서 파이썬은 배열을 없애고 처음부터 리스트를 도입한 걸까요?

파이썬 같은 경우는 언어자체가 자바와 다르게 동적 타입 언어라서 상황이 좀 다른 거 같기는 하네요.