2013-06-11 4 views
0

У меня есть следующий код:Использование Java Generics ошибки

String test = "[{\"color\":\"red\"}]"; 
Class<? extends Base> baseObject = Base.class; 
Collection<? extends Base> elements = new ArrayList<Base>(); 
if (test.startsWith("[")) { 
    elements.addAll(new ObjectMapper().readValue(test, Collection.class)); 
} else { 
    elements.add(new ObjectMapper().readValue(test, baseObject)); 
} 

Однако я получаю на

elements.addAll(new ObjectMapper().readValue(test, Collection.class));

предупреждение сборник:

The expression of type Collection needs unchecked conversion to conform to Collection<? extends capture#1-of ? extends Base> 

и elements.add(new ObjectMapper().readValue(test, baseObject));

ошибка компиляции:

The method add(capture#2-of ? extends Base) in the type Collection<capture#2-of ? extends Base> is not applicable for the arguments (capture#3-of ? extends Base) 

Что не так?

+0

* Какие ошибки? –

+1

Почему бы не просто 'Collection elements = new ArrayList ();'? – assylias

+2

'String test =" [{"color": "red}]"; '<- Я думаю, что вы забыли избежать котировок –

ответ

1

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

http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

В частности:

Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E , the element type of the collection. When the actual type parameter is ? , it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null , which is a member of every type.

Тип стиранием это ... ну, вы знаете.

+1

Не совсем. Вы можете добавлять вещи в коллекцию, которая использует 'super', например. вы можете добавить любой подкласс 'InputStream' в' Collection ' – Brian

+0

Ударьте меня на это :) – LexLythius

+0

Я все еще получаю предупреждение о компиляции для elements.addAll (new ObjectMapper(). readValue (jsonRep, Collection.class)); – Dejell

2

Ошибка может быть легко объяснена. Ваша коллекция определена для хранения экземпляров классов, которые расширяются до Base. ObjectMapper.readValue определяется следующим образом:

public <T> T readValue(JsonParser jp, Class<T> valueType)

Это означает, что он возвращает экземпляр класса, заданного в качестве второго аргумента. Если вторым аргументом является Collection.class, этот метод возвращает Collection. Только Collection, а не Collection<? extends Base> и не Collection<Base>. Таким образом, java-компилятор не может быть уверен, что вы собираетесь разместить коллекцию, содержащую правильные объекты, в elements, определенную как Collection<? extends Base>. Более того, синтаксис java не позволяет поставлять в качестве класса параметров дженериков, т. Е. Вы не можете позвонить по номеру readValue(c, Collection<Base>.class).

Второй случай сложнее. baseObject определяется как Class<? extends Base>. elements коллекция определена как Class<? extends Base>. Так в чем проблема. Проблема заключается в ?. Значок вопроса означает «что-то, что расширяет базу». Но это два разных «чего-то» в обоих случаях.

Решение может быть либо определение изменения в коллекции Class<Base> или использовать один класс или метод общего параметра в обоих случаях, например:

public <T extends Base> myMethod() { 
    Class<T> baseObject = Base.class; 
    Collection<T> elements = new ArrayList<T>(); 
    elements.add(new ObjectMapper().readValue(test, baseObject)); 
} 

Теперь оба baseObject и elements использовать один и тот же тип T, что на самом деле проходит Base.

Смежные вопросы