2012-03-24 9 views
115

가능한 중복 : 다음 ArrayList의 일부 기능 List에없는 경우 내가 List에서다형성 : "ArrayList list = new ArrayList"대신 "List list = new ArrayList"를 사용해야하는 이유는 무엇입니까?

List<Object> list = new ArrayList<Object>(); 

ArrayList 상속을 사용하므로해야
Why should the interface for a Java class be prefered?

, I의 일부 기능을 잃게됩니다., 맞죠? 그리고 컴파일러는 이러한 메서드에 액세스하려고 할 때 오류가 있음을 알 수 있습니까?

+0

오. 죄송 해요. 왜냐하면 나는 '객체'로 바뀌기 때문에 그것을 잊어 버린다. – hqt

+6

@duffymo - 그 질문은 왜'new List ()'이 작동하지 않는지 묻고 있습니다. 그것은 완전히 다른 질문입니다. –

+2

중복 질문이 아닙니다. 가능한 중복에는 일반적인 질문이 있지만 구체적인 세부 사항이 있습니다. 제목에서이 질문이 더 관련이 있는지/실제로 실제로 질문 한 내용과 동기화되어 있음을 발견했습니다. – Dexters

답변

205

이렇게하는 주된 이유는 인터페이스의 특정 구현에서 코드를 분리하기 위해서입니다. 이 같은 코드를 작성하는 경우 :

List list = new ArrayList(); 

코드의 나머지는 해당 데이터가 당신이 쉽게와 List 인터페이스가 다른 구현 사이를 전환 할 수 있기 때문에 바람직하다 유형 List,이다 알고있다.

예를 들어 상당히 큰 타사 라이브러리를 작성 중이며 LinkedList으로 라이브러리의 핵심을 구현하기로 결정했다고 가정 해 보겠습니다.라이브러리가 이러한 목록의 요소에 액세스하는 데 크게 의존하는 경우 결국 디자인 결정이 잘못되었다는 것을 알게됩니다. LinkedList (O (n) 액세스 시간을 제공) 대신 ArrayList (O (1) 액세스 시간을 제공)을 사용해야 함을 알게 될 것입니다. 인터페이스로 프로그래밍했다고 가정하면 그러한 변경을 쉽게 수행 할 수 있습니다. 당신은 단순히

List list = new LinkedList(); 

List list = new ArrayList(); 

에에서 List의 인스턴스를 변경할 것입니다 그리고 당신은 당신이 List 인터페이스가 제공하는 계약을 따르도록 코드를 작성했기 때문에이 일 것이라는 점을 알고있다.

한편, LinkedList list = new LinkedList()을 사용하여 라이브러리의 핵심을 구현 한 경우 나머지 코드가 메소드를 사용하지 않는다고 보장 할 수 없으므로 그러한 변경을하는 것이 쉽지는 않습니다. LinkedList 클래스에만 적용됩니다.

전체적으로 선택은 디자인의 문제 일 뿐이지 만 이러한 디자인은 나중에 대규모 구현 프로젝트에서 특히 중요합니다. 기존 코드.

+4

명확한 설명. :) – coder247

+44

많은 사람들이 ArrayList = new ArrayList()를 통해 로컬 변수로 인스턴스화하는 것이 완벽하게 용납된다는 것을 언급하지 못했습니다. 메소드 시그니처에서 또는 클래스 레벨 변수의 유형으로 List 인터페이스를 사용하는 것이 실제로 유용합니다. 나중에 다시 가서 로컬 메소드 선언을 변경해야하는 경우 누가 신경 쓰겠습니까? List 나 다른 메소드 나 라이브러리 등을 노출 할 때 모든 이점이 있습니다. – GreenieMeanie

+5

사실, 지적 해 주셔서 감사합니다. 사실, 이제 생각해 보았을 때 프로그래머 자신보다는 클라이언트의 관점에서 본보기를 제시하는 것이 더 나을 것입니다. 두 경우 모두'List list = new ArrayList()'를 사용하면 기존 코드를 깨뜨리지 않아도됩니다. –

63

이것은 프로그래밍 인터페이스라고합니다. 이것은 앞으로 List의 다른 구현으로 이동하고자 할 때 유용 할 것입니다. ArrayList에 몇 가지 메소드가 필요하면 구현에 프로그래밍해야합니다 (ArrayList a = new ArrayList()). 당신이 그것을 변경할 수 있습니다, 나중에

void doSomething() { 
    List<String>list = new ArrayList<String>(); 
    //do something 
} 

:

void doSomething() { 
    List<String>list = new LinkedList<String>(); 
    //do something 
} 

방법의 나머지 부분을 변경하지 않고

6

이것은 당신이 뭔가를 작성할 수 있습니다.

void doSomething() { 
    CopyOnWriteArrayList<String>list = new CopyOnWriteArrayList<String>(); 
    //do something, for example: 
    list.addIfAbsent("abc"); 
} 
: 당신이 CopyOnWriteArrayList 예를 들어, 사용하고자하는 경우는 별도의 방법 (예 : addIfAbsent)를 사용하기를 원한다면

그러나, 당신은 목록 등로 선언, 그리고해야

+1

허용 된 답변의 @GreenieMeanie 설명에 따라이 변경 사항은 로컬 변수이므로 중요하지 않습니다. – Ram

5

문제에 복잡성을 추가하고 싶지 않을 때마다 해당 구성을 사용합니다. 그것은 단지 목록 일 뿐이며 문제가되지 않는다면 어떤 종류의 목록인지 말할 필요가 없습니다. 나는 결국 대부분의 시간 동안, 대부분의 시간 동안, 대부분의 시간 동안, 대부분의 시간 동안, 소프트웨어의 중요한 부분으로서, 내가 보유하고있는 내용이 Collection이고, Collection에 새로운 객체를 추가하고 싶지 않다. .

또한, 사용중인 목록의 구현을 변경하려는 생각이들 때 그 구성을 사용합니다. ArrayList로 생성자를 사용 중이며 문제가 스레드로부터 안전하지 않다고 가정 해 보겠습니다. 이제 스레드를 안전하게 만들고 싶습니다. 예를 들어 솔루션의 일부로 Vector를 사용하도록 변경합니다. 그 목록의 다른 용도는 AraryList 또는 Vector, List 일 뿐이며 새로운 수정은 필요하지 않습니다.

2

일반적으로 인터페이스에 대해 프로그램을 작성하려고합니다. 이를 통해 언제든지 구현을 교환 할 수 있습니다. 특히 모르는 구현을 전달할 때 매우 유용합니다.

그러나 구체적인 구현을 선호하는 특정 상황이 있습니다. 예를 들어 GWT에서 직렬화 할 때.

17

공용 인터페이스를 공개 할 때도 유용합니다. 이 같은 방법을 경우

public ArrayList getList(); 

는 그런 다음에 자신의 코드를 변경해야합니다 ArrayList list = yourClass.getList()을하고 있었다

public LinkedList getList(); 

누구를 변경하기로 결정. 다른 한편, 당신이한다면,

public List getList(); 

구현을 변경해도 API 사용자에게는 아무런 변화가 없습니다.

+0

yourClass.getList() 나는 내가 만났던 가장 실용적인 사례라고 생각합니다. 고마워요 :) –

4

나는 당신의 질문의 핵심은 추측 이유에 program to an interface, not to an implementation 인터페이스 코드를 더 많은 추상화를 제공하고 있습니다

간단하기 때문에보다 유연하고 같은 다른 구현을 사용할 수 있기 때문에, 변화에 탄력적 인터페이스 (이 경우에는 ListList를 ArrayList 대신 linkedList로 변경하려는 경우)를 변경하지 않아도됩니다.

10

@ tsatiz의 답변은 거의 옳다고 생각합니다 (구현보다는 인터페이스로 프로그래밍). 그러나 프로그래밍 인터페이스에 의해 은 어떤 기능도 잃지 않을 것입니다.. 설명하겠습니다.

변수를 List<type> list = new ArrayList<type>으로 선언하면 실제로 의 ArrayList 기능이 손실되지 않습니다.listArrayList으로 전송하면됩니다. 다음 예는 다음과 같습니다

List<String> list = new ArrayList<String>(); 
((ArrayList<String>) list).ensureCapacity(19); 


은 궁극적으로 당신이 더 이상 인터페이스에 코딩하고 ArrayList에 캐스팅 한 번으로 tsatiz이 정확하다고 생각합니다. 그러나 처음에는 인터페이스에 코드를 작성하고 나중에 필요할 경우 구현에 코드를 작성하는 것이 좋습니다.

희망 하시겠습니까?

+0

이것은 매우 쉽고 명확합니다. – CopsOnRoad