Подтвердить что ты не робот

API java 5 и более: следует ли возвращать массив или коллекцию?

В духе Лучшие практики: всегда возвращайте ____, никогда не ____, я сталкиваюсь с аналогичным вопросом в своем предстоящем переход от JDK1.4.2 к ​​JDK5 и более. (Да, я знаю, JDK1.4.2 - EOL!;-)).

Для функций, возвращающих коллекцию (которые не просто коллекции свойств), я всегда предпочитаю (в JDK1.4.2) возвращать Array вместо общего списка, потому что

  • он применяет возвращаемый тип (MyObject[]вместо List of Objects, гораздо более тип-безопасный) на статическом уровне, как на уровне 'compilation')
  • он предлагает символ "только для чтения" возвращенной коллекции (сложнее добавить элемент в коллекцию, хотя это не так строго, как ключевое слово "только для чтения" в С#). Это не то же самое, что сказать, что это "неизменный", поскольку ссылки внутри массива все еще могут быть изменены...

Конечно, я всегда создаю этот возвращенный массив (я не выставляю никакого "внутреннего" массива)

Теперь, в JDK5 и более, я мог бы использовать List<MyObject>, если захочу.

Каковы веские причины для возврата MyObject[] вместо List или Collection<MyObject> при кодировании в java5?

Бонус, если используется Collection<MyObject>, возможно ли:

  • применять атрибут "только для чтения" для возвращаемой коллекции? (нет add() или remove())
  • обеспечить неизменный аспект возвращенной коллекции? (даже ссылки этой коллекции не могут быть изменены)

PS: JavaGenericFAQ не имел этого.

4b9b3361

Ответ 1

Предпочитайте сборку (или список или установите соответственно) массиву. С generics вы получаете проверку типов, которой не хватало pre-Java 5. Кроме того, выставляя только интерфейс, вы можете позже изменить реализацию (например, переключить ArrayList для LinkedList).

Массивы и дженерики не очень хорошо смешиваются. Итак, если вы хотите воспользоваться дженериками, вы обычно должны избегать массивов.
I.e: Вы не можете создать массив. Например, если T - общий тип, то "новый T [0]" не компилируется. Вам нужно будет сделать что-то вроде "(T []) нового объекта [0]", который генерирует предупреждение без предупреждения. По той же причине вы не можете использовать общие типы с varargs без предупреждений.

Используя Collections.unmodifiableCollection (и аналогичные методы), вы получаете ограничение только для чтения (чего вы не можете достичь с помощью массива - вам нужно будет вернуть клон массива).

Вы не можете обеспечить неизменность членов, но тогда вы не можете сделать это с массивом.

Ответ 2

На самом деле массивы все еще имеют одно преимущество перед Коллекциями/списками. Из-за того, что Java реализует Generics посредством стирания типа, у вас не может быть двух методов, которые принимают Collections в качестве аргументов, но отличаются только общим типом Collection.

Пример:

public void doSomething(Collection<String> strs) { ... }
public void doSomething(Collection<Integer> ints) { ... }

Два вышеуказанных метода не будут компилироваться, потому что компилятор javac использует стирание типа и, следовательно, не может передавать информацию типа в JVM. JVM будет видеть только два метода, которые принимают коллекцию в качестве аргумента.

В вышеприведенных случаях наилучшим решением является то, чтобы методы принимали массивы в качестве их аргументов и использовали метод Collection/List toArray() при передаче им аргументов. Если вы все еще хотите использовать Collection/List внутри указанных выше методов, просто используйте метод java.util.Arrays.asList(), чтобы вернуть свой список.

Пример:

public void doSomething(String[] strs) {
        List<String> strList = Arrays.asList(strs);
        ...
}

public void doSomething(Integer[] ints) {
        List<Integer> intList = Arrays.asList(ints);
        ...
}

public static void main(String[] args) {
        List<String> strs = new ArrayList<String>();
        List<Integer> ints = new ArrayList<Integer>();
        obj.doSomething(strs.toArray());
        obj.doSomething(ints.toArray());
}

Ответ 3

Ознакомьтесь с немодифицируемыми * методами в классе Collections, чтобы сделать возвращенные коллекции доступными только для чтения/неизменяемыми. Это обернет исходную коллекцию в список, который запрещает доступ к изменению самого списка (сами элементы не являются неизменяемыми).

unmodifiableList, например.

Для меня это зависит от того, как будет использоваться возвращенный список. Какие другие методы передаются и как они будут использоваться? В общем, я бы предпочел общую коллекцию над массивом, но изменил бы ее в каждом конкретном случае.

Массив, вероятно, будет работать быстрее, если вы делаете что-то критическое.

Ответ 4

Мой ответ был приостановлен, потому что я использую прокси для класса и использую такие вещи (прокси и отражение), потому что это влияет на производительность некоторых людей (многие люди даже не используют рефлексию, однако они используют спящий режим и spring которые используют relfection, прокси класса и xml).

Enhancer из проекта cglib.sourceforge.net, он позволяет создавать прокси для классов (JDK поддерживает только прокси для интерфейсов). Прокси позволяет управлять методами в объекте, однако вы не можете использовать поля доступа с помощью отражений. если у вас есть вопросы, задайте вопросы.