2009-09-27 4 views
17

Это настоящий вопрос для начинающих (я все еще изучаю основы Java).Почему переменные объявлены с их именем интерфейса в Java?

Я (вроде) понять, почему методы будут возвращать список < строку >, а не ArrayList < строки >, или почему они принимают параметр List, а не в ArrayList. Если это не имеет никакого значения для метода (то есть, если не требуются специальные методы из ArrayList), это сделает метод более гибким и более простым в использовании для вызывающих. То же самое относится к другим типам коллекций, таким как Set или Map.

То, что я не понимаю: это, кажется, обычная практика для создания локальных переменных, как это:

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

В то время как эта форма встречается реже:

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

В чем преимущество здесь?

Все, что я вижу, является незначительным недостатком: отдельная строка импорта для java.util.List необходимо добавить. Технически «import java.util. *» Можно использовать, но я не вижу этого очень часто, возможно, потому, что строки «импорта» автоматически добавляются некоторой средой IDE.

ответ

20

Когда вы читаете

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

Вы получаете идею, что все, что вы заботитесь о будучи List<String> и вы поставите меньше внимания фактической реализации. Кроме того, вы ограничиваете себя членами, объявленными List<String>, а не конкретной реализацией. Вам все равно, сохранены ли ваши данные в линейном массиве или в какой-то причудливой структуре данных, если она похожа на List<String>.

С другой стороны, чтение второй строки дает вам представление о том, что код заботится о переменной ArrayList<String>. Написав это, вы неявно говорите (будущим читателям), что вы не должны слепо изменять тип фактического объекта, потому что остальная часть кода полагается на то, что это действительно ArrayList<String>.

+5

Это абстрактофилия. Эффективность одной реализации по сравнению с другой зависит от кода, который _uses_ переменной: я не вижу, что когда-нибудь захочу что-нибудь, кроме плотной связи между ними. –

+0

«Я не вижу, что мне когда-либо понадобится что-то, кроме плотной связи между ними». Разве не вся концепция интерфейсов основана на том, что вы на самом деле хотите получить свободную связь? –

+1

Конечно.Но когда вам нужна свободная связь между работой функции и ее локальными переменными? Особенно при выборе реализации коллекции, поскольку коллекции часто оптимизируются для конкретных ситуаций. –

1

Если позже вы хотите изменить реализацию списка и использовать, например, LinkedList (возможно, для повышения производительности), вам не нужно изменять весь код (и API, если его библиотека). если заказ не имеет значения, вы должны вернуть Collection, поэтому позже вы можете легко изменить его на «Установить», если вам нужны элементы для сортировки.

+0

«почему методы возвратили бы список , а не ArrayList « <- так его API;) – IAdapter

1

Лучшее объяснение, которое я могу придумать (потому что я не программирую на Java так часто, как на других языках), заключается в том, что упростить изменение типа списка «back-end» при сохранении того же кода/интерфейс, на который все опирается. Если вы сначала объявите его как более конкретный, а затем решите, что хотите другого рода ... если что-то случается с использованием метода ArrayList, это дополнительная работа.

Конечно, если вы на самом деле необходимо Атрибут, характерный для ArrayList, вместо этого вы перейдете к определенному типу переменной.

7

Использование интерфейса позволяет быстро изменить базовую реализацию List/Map/Set/etc.

Речь идет не о сохранении нажатий клавиш, а о быстром внедрении.В идеале вы не должны раскрывать базовые конкретные методы реализации и просто использовать требуемый интерфейс.

2

Я бы предложил подумать об этом с другого конца. Обычно вам нужен список или набор или любой другой тип коллекции, и вам действительно не нравится, как именно это реализовано. Следовательно, ваш код просто работает со списком и делает все, что ему нужно (также обозначается как «всегда код для интерфейсов»).

Когда вы создаете Список, вам нужно решить, какую фактическую реализацию вы хотите. Для большинства целей ArrayList «достаточно хорош», но вашему коду действительно все равно. Придерживаясь использования интерфейса, вы передаете это будущему читателю.

Например, у меня есть привычка иметь отладочный код в моем основном методе, который сбрасывает системные свойства System.out - обычно гораздо удобнее сортировать их. Самый простой способ - просто «Map map = new TreeMap (свойства)»; и THEN прокручивают их, так как TreeMap возвращает отсортированные ключи.

Когда вы узнаете больше о Java, вы также увидите, что интерфейсы очень полезны при тестировании и издевательстве, поскольку вы можете создавать объекты с поведением, указанными во время выполнения, соответствующим данному интерфейсу. Продвинутый (но простой) пример можно увидеть на http://www.exampledepot.com/egs/java.lang.reflect/ProxyClass.html

-2

В основном это происходит от людей, которым приходится запускать большие проекты, возможно, по другим причинам - вы слышите это все время. Почему, я действительно не знаю. Если вам нужен список массивов, или Hash Map или Hash Set, или что-то еще, что я не вижу смысла в устранении методов путем литья в интерфейс.

Скажем, например, недавно я научился использовать и реализовывать HashSet в качестве основной структуры данных. Предположим, по какой-то причине я пошел на работу в команду. Разве этот человек не должен был знать, что данные были связаны с подходами хэширования, а не с их помощью? Вспомогательный подход, отмеченный Twisol, работает на C/C++, где вы можете разоблачить заголовки и продать библиотеку таким образом, если кто-то знает, как это сделать на Java, я бы предположил, что они будут использовать JNI - в этот момент мне кажется более простым использовать C/C++, где вы можете выставлять заголовки и создавать библиотеки с помощью установленных инструментов для этой цели.

К тому времени, когда вы можете получить кого-нибудь, кто может установить файл jar в расширении dir, мне кажется, что сущность может быть в нескольких шагах от меня - я сбросил несколько crypto-библиотек в каталог расширений, что было удобно, но Я бы очень хотел, чтобы ясность и краткость были выяснены. Я думаю, они все это время делают.

На данный момент это звучит как классическое обфускация, но будьте осторожны: у вас есть некоторая кодировка, прежде чем проблема будет иметь последствия.

+0

Ты полностью потерял меня до конца. – user183037

+2

И меня. Кажется, вы пропустили точку интерфейса. Кроме того, здесь нет кастинга. – DNA

0

Целью является определить поведение, которое вы хотите/нуждаетесь, а затем использовать интерфейс, который обеспечивает такое поведение. Это тип переменной. Затем используйте реализацию, которая отвечает вашим потребностям - эффективность и т. Д. Это то, что вы создаете с помощью «нового». Эта двойственность является одной из основных идей, лежащих в основе OOD. Проблема не имеет особого значения, когда вы имеете дело с локальными переменными, но редко приходится постоянно следить за хорошими методами кодирования.