Dlaczego powinien być preferowany interfejs dla klasy Java?

PMD zgłosi naruszenie dla:

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

Naruszenie polegało na "unikaniu używania typów implementacji, takich jak 'ArrayList'; zamiast tego używaj interfejsu".

Następująca linijka poprawiłaby naruszenie:

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

Dlaczego zamiast ArrayList powinno się używać tego ostatniego z List?

Author: Cœur, 2008-09-29

9 answers

Używanie interfejsów nad konkretnymi typami jest kluczem do dobrej hermetyzacji i luźnego łączenia kodu.

To nawet dobry pomysł, aby stosować się do tej praktyki podczas pisania własnych API. Jeśli to zrobisz, później okaże się, że łatwiej jest dodać testy jednostkowe do kodu (używając technik szyderczych) I zmienić podstawową implementację, jeśli zajdzie taka potrzeba w przyszłości.

Oto dobry artykuł na ten temat.

Mam nadzieję, że to pomoże!

 74
Author: kolrie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 04:20:12

Jest to preferowane, ponieważ oddzielasz Kod od implementacji listy. Korzystanie z interfejsu pozwala na łatwą zmianę implementacji, ArrayList w tym przypadku, na inną implementację list bez zmiany żadnej z pozostałych części kodu, o ile używa tylko metod zdefiniowanych w liście.

 28
Author: AdamC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 04:04:28

Ogólnie zgadzam się, że oddzielenie interfejsu od implementacji jest dobrą rzeczą i ułatwi utrzymanie kodu.

Są jednak wyjątki, które należy wziąć pod uwagę. Dostęp do obiektów poprzez interfejsy dodaje dodatkową warstwę indrection, która spowolni twój kod.

Dla zainteresowania przeprowadziłem eksperyment, który wygenerował dziesięć miliardów sekwencyjnych dostępów do 1 miliona ArrayList długości. Na moim MacBooku 2,4 Ghz, dostęp do ArrayList poprzez listę interfejs trwał średnio 2,10 sekundy, przy deklarowaniu typu ArrayList trwał średnio 1,67 sekundy.

Jeśli pracujesz z dużymi listami, głęboko wewnątrz wewnętrznej pętli lub często nazywanej funkcji, to jest to coś do rozważenia.

 11
Author: Owen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-01 14:49:27

ArrayList i LinkedList to dwie implementacje listy, która jest uporządkowanym zbiorem elementów. Pod względem logicznym nie ma znaczenia, czy używasz ArrayList czy LinkedList, więc nie powinieneś ograniczać tego typu.

To kontrastuje z say, Collection i List, które są różnymi rzeczami(lista oznacza sortowanie, Kolekcja Nie).

 6
Author: SCdF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-06 03:11:05

Dlaczego zamiast ArrayList powinno być używane to drugie z List?

To dobra praktyka: Program do interfejsu, a nie implementacji

Zastępując ArrayList na List, możesz zmienić implementację List w przyszłości, jak poniżej, w zależności od przypadku użycia biznesowego.

List<Object> list = new  LinkedList<Object>(); 
/* Doubly-linked list implementation of the List and Deque interfaces. 
 Implements all optional list operations, and permits all elements (including null).*/

Lub

List<Object> list = new  CopyOnWriteArrayList<Object>(); 
/* A thread-safe variant of ArrayList in which all mutative operations
 (add, set, and so on) are implemented by making a fresh copy of the underlying array.*/

Lub

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

/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/

Lub

Jakieś inne List konkretne wdrożenie.

List interfejs definiuje umowę i specyficzna implementacja List może zostać zmieniona. W ten sposób interfejs i implementacja są luźno powiązane.

Powiązane pytanie:

Co to znaczy "programować do interfejsu"?

 2
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:09

Nawet dla zmiennych lokalnych, użycie interfejsu nad klasą concrete pomaga. Może skończyć się wywołaniem metody, która znajduje się poza interfejsem i wtedy trudno jest zmienić implementację listy, jeśli to konieczne. Ponadto, najlepiej jest użyć najmniej specyficznej klasy lub interfejsu w deklaracji. Jeśli kolejność elementów nie ma znaczenia, użyj kolekcji zamiast listy. Daje to maksymalną elastyczność kodu.

 1
Author: Diastrophism,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 23:09:01

Właściwości Twoich klas / interfejsów powinny być ujawniane poprzez interfejsy, ponieważ daje to Twoim klasom kontrakt zachowania do użycia, niezależnie od implementacji.

Jednak...

W deklaracjach zmiennych lokalnych nie ma sensu robić tego:

public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}

Jeśli jest zmienną lokalną, po prostu użyj type. Nadal jest domyślnie upcastowalny do odpowiedniego interfejsu, a twoje metody powinny mieć nadzieję, że akceptują typy interfejsów dla swoich argumentów, ale dla lokalnych zmienne, To ma sens, aby używać typu implementacji jako kontenera, na wypadek, gdybyś potrzebował funkcji specyficznej dla implementacji.

 1
Author: MetroidFan2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-01 14:49:16

Ogólnie rzecz biorąc dla twojej linii kodu nie ma sensu zawracać sobie głowy interfejsami. Ale jeśli mówimy o API, istnieje naprawdę dobry powód. Mam małą klasę

class Counter {
    static int sizeOf(List<?> items) {
        return items.size();
    }
}

W tym przypadku wymagane jest użycie interfejsu. Ponieważ chcę policzyć rozmiar każdej możliwej implementacji łącznie z moim własnym niestandardowym. class MyList extends AbstractList<String>....

 1
Author: Rastislav Komara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-01 14:50:03

Spring framework bardzo ładnie stosuje pojęcie interfejsów - http://www.springframework.org/

Spring dostarcza implementację do klasy concrete poprzez plik konfiguracyjny, więc Klasa concrete nie musi nic wiedzieć o implementacji.

Badanie Springa jest przykładem zalet programowania opartego na interfejsach w Javie.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-15 03:19:52