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();

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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