2017-01-15 1 views
1

Итак, у меня есть ArrayList объектов неизвестного типа, расширяющих Entity (мой собственный класс, не путать java.swing.text.html.parser.Entity) по причинам, не связанным с Эта проблема.Добавить объект неизвестного класса в ArrayList с отражением

private ArrayList<? extends Entity> listedEntities = new ArrayList<>(); 

Это в классе, который в его конструктор принимает строку и присваивает его полю entityClass.

В каком-то момент я выполнение следующего фрагмента кода:

Class<?> clazz = Class.forName(this.entityClass); 
    Object newEntity = clazz.newInstance(); 

    listedEntities.add(newEntity); 

Естественно, это не работает, как ArrayList ожидает объект класса, простирающейся Entity и newEntity имеет Object. Так что сначала нужно было попробовать кастинг.

listedEntities.add(Class.forName(this.entityClass).cast(newEntity)); 

Также не работает. И через несколько минут, не найдя ответа, я здесь печатаю это.

Исключение:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The method add(capture#8-of ? extends Entity) in the type ArrayList<capture#8-of ? extends Entity> is not applicable for the arguments (capture#9-of ?) 
+2

Как насчет забыть о '?' И использовать некоторые 'T' –

+0

Есть ли веская причина, по которой вы используете' String' для 'entityClass' вместо' Class'? – Radiodef

ответ

3

простое решение, как это:

  • Изменение listedEntities в ArrayList<Entity> вместо ArrayList<? extends Entity>. Это не похоже на то, что у вас есть определенная причина использовать подстановочный знак и подстановочный знак запрещает вам добавлять в список.

  • Изменить конструкцию к этому:

    Class<?> clazz = Class.forName(this.entityClass); 
    Entity newEntity = (Entity) clazz.newInstance(); 
    
    listedEntities.add(newEntity); 
    

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

Полностью-родовая версия, как я считаю @RC. намеки на комментарии будут такими:

class Example<E extends Entity> { 
    private List<E> listedEntities = new ArrayList<>(); 
    private Class<E> entityClass; 

    Example(Class<E> entityClass) { 
     this.entityClass = entityClass; 
    } 

    void method() 
    throws IllegalAccessException, InstantiationException { 
     E newEntity = entityClass.newInstance(); 
     listedEntities.add(newEntity); 
    } 
} 

Это более «правильный»; однако, можете ли вы использовать что-то вроде этого или нет, зависит от ваших конкретных потребностей.

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

+0

Что касается побочного примечания: я использую Eclipse Neon 2.0, но исключение является исключением из-за наличия следующей точки входа - public static void main (String [] args) {SwingUtilities.invokeLater (новый Runnable() {public void run() {new Primary();}}); } –

+0

Хорошо, что кажется хорошо. Я думаю, что он должен пометить ошибку во время компиляции, но, к сожалению, я не знаю достаточно о Eclipse, чтобы сказать, почему это может быть не в этом случае. – Radiodef

+0

Относительно предлагаемого решения: Это не соответствует моим потребностям использовать ArrayList . Фактически это была начальная версия, прежде чем использовать отражение вообще.Мне нужно иметь объекты одного класса, и этот класс должен расширять Entity. Полностью общая версия также не делает меня полезной по одной причине: класс, в котором я включен, определяется как Lister , и он никогда не совпадает с классом ArrayList. –