developer tip

Enumeration이 java.utils의 List가 아닌 ArrayList로 변환되는 이유는 무엇입니까?

optionbox 2020. 10. 22. 07:55
반응형

Enumeration이 java.utils의 List가 아닌 ArrayList로 변환되는 이유는 무엇입니까?


패키지 Collections.list () 메서드 java.utilsArrayList<T>대신 List<T>?를 반환하는 좋은 이유가 있습니까?

분명히이 ArrayListA는 List,하지만 난 그것을 구현 유형 대신 인터페이스 형식을 반환하는 일반적으로 좋은 연습이 있다는 인상입니다.


면책 조항 : 저는 JDK 작성자가 아닙니다.

인터페이스에 자신의 코드 를 작성하는 것이 옳다는 데 동의 하지만 변경 가능한 컬렉션을 제 3 자에게 반환하려는 경우 제 3 자에게 어떤 종류 의 코드 가 반환되는지 알려주는 것이 중요합니다 List.

LinkedListArrayList다양한 작업을 위해, 현명 성능, 매우 다릅니다. 예를 들어,의 첫 번째 요소를 제거하는 ArrayList것은 O(n)이지만 a의 첫 번째 요소를 제거하는 LinkedList것은 O(1)입니다.

반환 유형을 완전히 지정함으로써 JDK 작성자는 어떤 종류의 객체를 반환하는지에 대한 명확한 코드로 추가 정보를 전달 하므로이 메서드를 올바르게 사용하도록 코드를 작성할 수 있습니다. 정말 필요한 경우 LinkedList여기에 지정해야합니다.

마지막으로, 구현을 통해 인터페이스를 코딩하는 주된 이유는 구현이 변경 될 것이라고 생각하는 경우입니다. JDK 작성자는 이 방법을 절대로 변경 하지 않을 것이라고 생각할 것입니다 . LinkedList또는 a 를 반환하지 않습니다 Collections.UnmodifiableList. 그러나 대부분의 경우 다음을 수행 할 수 있습니다.

List<T> list = Collections.list(enumeration);

를 반환하면 프로그램을 인터페이스List 로 승격하게 됩니다 . 이는 매우 좋은 방법입니다. 그러나이 접근법에는 한계가 있습니다. 예를 들어 인터페이스 ArrayList정의되어 있고 존재하지 않는 일부 메서드를 사용할 수 없습니다 . 자세한 내용 List이 답변 을 참조하십시오.

Java ™ 튜토리얼에서 API 디자인인용하고 있습니다 .

... 컬렉션 인터페이스 중 하나 구현 하거나 확장 하는 모든 유형 의 개체를 반환하는 것이 좋습니다. 이는 인터페이스 중 하나이거나 이러한 인터페이스 중 하나를 확장하거나 구현하는 특수 목적 유형일 수 있습니다.

.. 어떤 의미에서 반환 값은 입력 매개 변수의 반대 동작을 가져야합니다 . 가장 일반적인 .. 보다는 가장 구체적인 적용 가능한 컬렉션 인터페이스 를 반환하는 것이 가장 좋습니다 . 예를 들어 항상를 반환 할 것이라고 확신하는 경우 관련 메서드에 . 아닌 반환 유형을 지정해야합니다 . 인스턴스는 일반 인스턴스 보다 빌드하는 데 더 많은 시간이 소요되며 더 강력합니다. 모듈이을 빌드하는 데 이미 시간을 투자 했으므로 사용자에게 향상된 성능에 대한 액세스 권한을 부여하는 것이 좋습니다. 또한 사용자는 반환 된 객체를 a를 요구하는 메소드 .SortedMapSortedMapMapSortedMapMapSortedMapSortedMapMap

ArrayList본질적으로 배열 이기 때문에 "컬렉션 배열"이 필요할 때 첫 번째 선택입니다. 따라서 열거 형을 목록으로 변환하려면 배열 목록을 선택합니다.

다른 경우에도 다음과 같이 작성하는 것이 유효합니다.

List<T> list = Collections.list(e);

새로 생성 된 가변 객체의 "배타적 소유권"을 반환하는 함수는 종종 가장 구체적인 유형이 실용적이어야합니다. 불변 객체를 반환하는 객체, 특히 공유 될 수있는 경우에는 종종 덜 구체적인 유형을 반환해야합니다.

구별되는 이유는 전자의 경우 객체가 항상 지정된 유형의 새 객체를 생성 할 수 있고 수신자가 객체를 소유하고 수신자가 수행하려는 작업을 말할 수 없기 때문입니다. 일반적으로 객체를 반환하는 코드가 대체 인터페이스 구현이 수신자의 요구를 충족 할 수 있는지 여부를 알 수있는 방법이 아닙니다.

후자의 경우 객체가 불변이라는 사실은 함수가 정확한 내용을 고려 하여 더 복잡한 유형이 할 수있는 모든 작업을 수행 할 수있는 대체 유형을 식별 할 수 있음을 의미합니다 . 예를 들어 Immutable2dMatrix인터페이스는 ImmutableArrayBacked2dMatrix클래스와 클래스에 의해 구현 될 수 있습니다 ImmutableDiagonal2dMatrix. 정사각형을 반환해야하는 함수 는 주 대각선의 모든 요소가 0이면 인스턴스 Immutable2dMatrix를 반환할지 ImmutableDiagonalMatrix아니면 그렇지 않으면를 반환할지 결정할 수 있습니다 ImmutableArrayBackedMatrix. 전자 유형은 저장 공간을 훨씬 적게 차지하지만받는 사람은 그 차이에 대해 신경 쓰지 않아야합니다.

Immutable2dMatrix구체적이 아니라 반환 ImmutableArrayBackedMatrix하면 코드가 배열에 포함 된 내용을 기반으로 반환 유형을 선택할 수 있습니다. 또한 배열을 반환해야하는 코드가 적절한 구현을 보유하고 Immutable2dMatrix있는 경우 새 인스턴스를 생성하지 않고 간단히 반환 할 수 있습니다. 이 두 가지 요소는 불변 객체로 작업 할 때 주요 "승리"가 될 수 있습니다.

그러나 변경 가능한 객체로 작업 할 때는 두 요소 모두 작동하지 않습니다. 가변 배열이 생성 될 때 주 대각선을 벗어나는 요소가 없을 수 있다는 사실은 그러한 요소가 전혀 없다는 것을 의미하지 않습니다. 결과적으로 an ImmutableDiagonalMatrix은의 하위 유형 Immutable2dMatrix이지만 a MutableDiagonalMatrix는 a의 하위 유형이 아닙니다. Mutable2dMatrix왜냐하면 후자는 주 대각선에서 상점을받을 수있는 반면 전자는 허용하지 않기 때문입니다. 또한 변경 불가능한 객체는 공유 할 수 있고 공유해야하는 경우가 많지만 일반적으로 공유 할 수 없습니다. 특정 콘텐츠로 초기화 된 새 변경 가능한 컬렉션을 요청하는 함수는 백업 저장소가 요청 된 유형과 일치하는지 여부에 관계없이 새 컬렉션을 만들어야합니다.


객체에서 직접 호출하기보다는 인터페이스에서 var 메서드를 호출 할 때 약간의 오버 헤드가 있습니다.

이 오버 헤드는 종종 1 개 또는 2 개의 프로세서 명령어를 넘지 않습니다. 메서드 호출의 오버 헤드는 JIT가 메서드가 최종임을 알면 훨씬 더 낮습니다. 이것은 대부분의 코드에서 측정 할 수 없지만 java.utils의 저수준 메서드의 경우 문제가되는 일부 코드에서 사용할 수 있습니다.

또한 다른 답변에서 지적했듯이 반환되는 객체의 구체적인 유형 (인터페이스 뒤에 숨겨져 있더라도)은 그것을 사용하는 코드의 성능에 영향을 미칩니다. 이러한 성능 변화는 매우 클 수 있으므로 호출 소프트웨어가 작동하지 않을 정도입니다.

분명히 작성자는 java.utilsCollections.list ()를 호출하는 모든 소프트웨어가 결과로 무엇을하는지 알 수있는 방법이 없으며 Collections.list () 이식을 변경하는 경우이 소프트웨어를 다시 테스트 할 방법이 없습니다. 따라서 유형 시스템이 허용하더라도 다른 유형의 List를 반환하기 위해 Collections.list () 이식을 변경하지 않을 것입니다!

자신의 소프트웨어를 작성할 때 모든 코드를 포괄하는 자동화 된 테스트가 있고 코드가 상호 관계되는 방식을 잘 이해하고 성능이 문제가되는 부분을 알 수 있습니다. 호출자를 변경하지 않고도 메서드를 변경할 수 있다는 것은 소프트웨어 디자인이 변경되는 동안 큰 가치가 있습니다.

따라서 두 가지 상충 관계는 매우 다릅니다.

참고 URL : https://stackoverflow.com/questions/32356762/why-does-enumeration-get-converted-to-arraylist-and-not-list-in-java-utils

반응형