Добавление Java в общий список неизвестного типа

Я столкнулся с чем-то, с чем раньше не сталкивался в Java, а именно: мне нужно создать новый экземпляр, скажем, класса ArrayList во время выполнения без назначения известного типа, а затем добавить данные в список. Звучит немного расплывчато, поэтому вот пример:

Class<?> c = i.getClass();

Constructor<?> con = ArrayList.class.getConstructor();
ArrayList<?> al = (ArrayList<?>)con.newInstance();

al.add("something");

Теперь причина, по которой я делаю это, а не просто использую дженерики, заключается в том, что дженерики уже широко используются, и переменная «i» в этом примере будет задана для использования как тип «?». Я действительно предпочел бы не добавлять еще один дженерик, так как это потребовало бы дополнительной работы для пользователя и было бы гораздо менее гибким в конечном дизайне. Есть ли способ использовать что-то вроде ниже (Примечание: то, что ниже, не работает). У кого-нибудь есть идеи?

ArrayList<c> al = (ArrayList<c>)con.newInstance();

person ars265    schedule 29.06.2011    source источник
comment
Generics предназначен для проверки времени компиляции. Во время выполнения вы можете не беспокоиться об универсальных типах и просто использовать неуниверсальный ArrayList.   -  person Bala R    schedule 29.06.2011
comment
@Bala R Вы правы, я могу просто удалить дженерики, мне просто интересно, есть ли способ вытащить их из класса, чтобы обеспечить проверку. Спасибо, ваша идея, вероятно, сработает для моих целей.   -  person ars265    schedule 29.06.2011
comment
Я должен спросить, для чего нужен список, для которого вы не знаете тип данных, которые он будет содержать?   -  person Bringer128    schedule 29.06.2011
comment
Это часть API, над которым я работаю. Причина, по которой я не знаю, что такое данные, потому что они поступают из внешнего источника, который может меняться в зависимости от конфигурации пользователя. По сути, многое определяется во время выполнения по сравнению с временем компиляции.   -  person ars265    schedule 30.06.2011


Ответы (3)


Вы не можете добавлять объекты в коллекцию, определенную с помощью универсальных шаблонов. Эта тема может вам помочь.

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

Я предлагаю вам прочитать ветку и увидеть, что она также применима к тому, что вы хотите сделать.

Ваша коллекция слишком общая, чтобы в нее можно было что-то добавить. Проблема не имеет ничего общего с правой частью присваивания (с использованием синглтона или отражения), она находится в типе объявления левой стороны с использованием подстановочных знаков.

person Snicolas    schedule 29.06.2011

Если я понимаю, что вы имеете в виду, у вас есть класс C, который неизвестен во время компиляции, и вы хотите создать ArrayList<C> безопасным способом. Это возможно:

Class<?> c = ...;
ArrayList<?> al = listOf(c);

static <T> ArrayList<T> listOf(Class<T> clazz)
{
    return new ArrayList<T>();
}

Это теоретически правильный способ сделать это. Но кого это волнует. Мы все знаем о стирании типов, и нет никаких шансов, что Java откажется от стирания типов и добавит тип времени выполнения для параметров типа. Таким образом, вы можете просто использовать необработанные типы и свободно использовать их, если вы знаете, что делаете.

person irreputable    schedule 29.06.2011
comment
Да, вы можете создать неизвестный универсальный ArrayList, но тогда вы не сможете что-то добавить к нему, и именно здесь возникает мой вопрос. - person ars265; 30.06.2011
comment
чем это отличается от ArrayList<?> al = new ArrayList<SomeRandomType>();? - person newacct; 27.11.2011
comment
@newacct предположительно, существует внеплановое соглашение, в какой-то момент список можно безопасно (по логике приложения) преобразовать в ArrayList<X>, и к нему будет добавлен объект X. со стиранием ни приведение, ни добавление не проблема. с овеществлением другая история. - person irreputable; 27.11.2011

Вы можете просто использовать ArrayList<Object>, к которому вы можете add() что угодно.

person Bohemian♦    schedule 29.06.2011
comment
Верно, но тогда они относятся к типу Объекта, а не к неизвестному типу. Это будет работать до добавления, но возвращает приведенный Object ArrayList. Затем пользователю придется отбрасывать каждый обратно. Я считаю, что Java начиная с 1.4 сохраняет дополнительные данные из своих подклассов, но не то, что мне нужно. - person ars265; 30.06.2011
comment
@ ars265: но, поскольку вы не знаете тип во время компиляции, вам все равно придется вернуть его обратно - person newacct; 27.11.2011
comment
@newacct: Это правда, но я разрабатываю фреймворк, чтобы пользователь фреймворка получил результат. Я искал что-то немного другое. В итоге я создал класс типа linq для среды. - person ars265; 02.12.2011