Какова цель методов получения и установки java.lang.reflect.Array? - PullRequest
6 голосов
/ 27 мая 2010

Java Class java.lang.reflect.Array предоставляет набор инструментов для динамического создания массива. Однако в дополнение к этому у него есть целый набор методов для доступа к массиву (get, set и length). Я не понимаю смысла этого, так как вы можете (и, вероятно, сделали бы) при создании динамически сгенерированный массив как массив, что означает, что вы можете использовать обычную функциональность доступа к массиву (скобочная запись). Фактически, глядя на исходный код, вы можете увидеть, что все, что делает класс, приведёт массив и сгенерирует исключение, если приведение завершится неудачей.

Так в чем смысл / полезность всех этих дополнительных методов?

Обновление

Все примитивные методы get*() и set*() кажутся особенно бесполезными, учитывая, что вам необходимо заранее знать тип массива, чтобы узнать, какой метод использовать.

Обновление 2

Спасибо всем, ваш вклад был очень познавательным! Я не могу понять, когда я бы использовал этот класс для чего-либо кроме newInstance() (и, возможно, getLength()), но теперь я понимаю, что эти другие методы все еще весьма полезны.

Ответы [ 3 ]

8 голосов
/ 28 мая 2010

Этот класс довольно эзотеричен - большинству применений массивов известен тип массива, поэтому этот класс обычно наиболее полезен при реализации кода, который обрабатывает массивы в общем.

Не существует суперкласса для всех массивов, поэтому нет единого способа доступа к элементам или размеру массива независимо от его типа. java.lang.reflect.Array заполняет этот пробел и позволяет обращаться к массиву одинаково, независимо от типа. Например, чтобы получить значение по заданному индексу из любого массива (возвращенного как объект).

Это параметрический полиморфизм . Конечно, вы могли бы написать это самостоятельно, если знаете тип - вы просто разыгрываете. Если вы не знаете тип массива или он может быть нескольких типов, вы должны проверить возможности и привести его соответствующим образом - это то, что делает код в reflect.Array.

РЕДАКТИРОВАТЬ: в ответ на комментарий. Подумайте, как бы вы решили эту проблему - как посчитать, сколько раз значение дублируется в массиве. Без класса Array, не зависящего от типа, это было бы невозможно закодировать без явного приведения массива, поэтому вам потребуется отдельная функция для каждого типа массива. Здесь у нас есть одна функция, которая обрабатывает любой тип массива.

public Map<Object, Integer> countDuplicates(Object anArray)
{
    if (!anArray.getClass().isArray())
        throw new IllegalArgumentException("anArray is not an array");

    Map<Object,Integer> dedup = new HashMap<Object,Integer>();
    int length = Array.getLength(anArray);
    for (int i=0; i<length; i++)
    {
        Object value = Array.get(anArray, i);         
        Integer count = dedup.get(value);
        dedup.put(value, count==null ? 1 : count+1);
    }
    return dedup;
}

EDIT2: Относительно методов get * () и set * (). Ссылка на исходный код выше ссылается на Apache Harmony. Реализация там не придерживается Sun Javadocs. Например, из метода getInt

@throws IllegalArgumentException If the specified object is not an array, 
or if the indexed element cannot be converted to the return type 
by an identity or widening conversion 

Это означает, что фактический массив может быть byte[], short[] или int[]. Это не относится к реализации Harmony, которая занимает всего int[]. (Между прочим, реализация Sun использует нативные методы для большей части класса Array.) Методы get * () и set * () существуют по той же причине, что и get(), getLength() - для обеспечения (слабо) type- доступ к массиву агностиков.

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

2 голосов
/ 28 мая 2010

Что касается методов set...(), они действительно используются:

Object a = new byte[1], b = new short[1], c = new int[1], d = new long[1];
Array.setByte(a, 0, (byte)1);
Array.setByte(b, 0, (byte)1);
Array.setByte(c, 0, (byte)1);
Array.setByte(d, 0, (byte)1);

Вам не нужно знать, является ли массив, с которым вы имеете дело, int[] или long[], чтобы установить значение, например, 5.

Редактировать Я изменил пример, чтобы, надеюсь, продемонстрировать тот факт, что методы set...() позволяют необязательно статически определять тип примитивного массива.

2 голосов
/ 28 мая 2010

Эти методы освобождают вас от бремени проверки и приведения массива самостоятельно, если все, что вы знаете, это «этот объект является массивом некоторого (возможно, примитивного) типа».

Я сам видел использование этого только в фреймворках и утилитах, таких как commons-beanutils. Эта структура рефлексивно обращается к свойствам Java-бинов и использует методы Array для доступа к элементам свойств массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...