2012-03-23 2 views
0

В:Дженерики с простирается

public class Organic<E> { 
    void react(E e) { 
    } 

    static void main(String[] args) { 
     Organic<? extends Elem> compound = new Organic<Elem>(); 
     compound.react(new Elem()); 
    } 
} 

class Elem {} 

Почему я получаю следующее сообщение об ошибке компиляции?

Метод react(capture#1-of ? extends Elem) в типе Organic<capture#1-of ? extends Elem> не применяется для аргументов (Elem)

+0

Почему вы используете различные параметры для объявления переменной и объекта экземпляра? Чего вы пытаетесь достичь? – biziclop

+0

Я не хочу ничего добиваться. Это просто упражнение из книги. –

ответ

1

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

Список является примером ограниченного шаблона. ? обозначает неизвестный тип, так же как и подстановочные знаки, которые мы видели ранее. Однако в этом случае мы знаем, что этот неизвестный тип на самом деле является подтипом Shape. (Примечание: это может быть сама форма или какой-то подкласс, она не должна буквально расширять форму.) Мы говорим, что Shape является верхней границей шаблона.

Существует, как обычно, цена за гибкость использования подстановочных знаков. Эта цена заключается в том, что теперь незаконно писать в фигуры в теле метода. Например, это не допускается:

public void addRectangle(List<? extends Shape> shapes) { 
    // Compile-time error! 
    shapes.add(0, new Rectangle()); 
} 

Вы должны быть в состоянии понять, почему этот код запрещен. Тип второго параметра для shape.add() есть? extends Shape - неизвестный подтип Shape. Поскольку мы не знаем, что это такое, мы не знаем, является ли он супертипом Rectangle; это может быть или не быть таким супертипом, поэтому небезопасно пропускать Rectangle.

Конкретно говорить о своем решении, вы не можете вызвать реакцию с объектом Elem типа, так как с типом Organic<? extends Elem> вы можете законно назначить compound = new Organic<ElemSubClass>() - и затем реагировать вызовет ошибку компиляции, поскольку вы не можете назвать его пропускание супер объекта класса.

0

Изменив метод reactas согласно ниже, он будет работать:

void react(Elem e) { 

} 
0

? extends SomeClass 'используется для определения общих типов, когда вы хотите разрешить пользователю передавать только SomeClass или его подклассы в качестве общего параметра. Это означает, что вы можете сделать это:

public class Organic<E extends Elem> { 
    void react(E e) { 
} 

, если вы хотите, чтобы Organic параметризоваться с подклассов Elem. В основном методе вы можете сделать что-то вроде этого:

Organic<Elem> compound = new Organic<ElemOrAnyElemSubclass>(); 

, как я знаю, что нет никакой необходимости использовать

Organic<? extends Elem> 

в теле метода.

Весь код:

public class Organic<E extends Elem> { 
void react(E e) { 
} 

static void main(String[] args) { 
    Organic<Elem> compound = new Organic<Elem>(); 
    compound.react(new Elem()); 
    } 
} 
class Elem {} 
class ElemSubClass extends Elem {} // if you need 

Кроме того, вы должны использовать те же самые общие типы в левой и правой части выражения. Это illehal: Органический состав = новый Organic();

Не уверен, что это то, что вы хотели, но надеюсь, что это поможет

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