Вопрос по экзамену SCJP-6

При подготовке к экзамену SCJP-6 столкнулся со сложной проблемой. Я не могу найти ответ самостоятельно. Пожалуйста, ответьте на вопрос и дайте краткие комментарии:

abstract class A<K extends Number> {
   // insert code here
}    
  1. public abstract <K> A<? extends Number> useMe(A<? super K> k);

  2. public abstract <K> A<? super Number> useMe(A<? extends K> k);

  3. public abstract <K> A<K> useMe(A<K> k);

  4. public abstract <V extends K> A<V> useMe(A<V> k);

  5. public abstract <V super K> A<V> useMe(A<V> k);

  6. public abstract <V extends Character> A<? super V> useMe(A<K> k);

  7. public abstract <V super Character> A<? super V> useMe(A<K> k);

Какой метод можно вставить в заполнитель выше?

P.S. Попробовал посмотреть спецификацию. Те мне не помогли.


person abatishchev    schedule 26.05.2010    source источник
comment
Это тяжело. Мне любопытно узнать ответ. Проголосовал.   -  person James P.    schedule 26.05.2010
comment
Пожалуйста, исправьте объявление абстрактного класса (часть после ключевого слова «extends»)   -  person Eyal Schneider    schedule 26.05.2010
comment
@Eyal Schneider: Спасибо! Фиксированный.   -  person abatishchev    schedule 26.05.2010


Ответы (4)


Ответ 1,2,3: универсальный тип K затененный тип класса K. В этих методах K — это просто новый универсальный тип. Компилятор пытается пройти условную оценку <K extends Number>. Способ 1,2 проходит, а 3 - не проходит.

Ответ 4 полностью правильный.

Ответ 5,7 содержит синтаксическую ошибку.

Ответ 6 неверный, потому что тест <V extends Number> не пройден.

person Community    schedule 28.07.2010

Лучший способ сделать это — попробовать каждый из них и посмотреть, что скажет вам компилятор. Я получаю следующие результаты для каждого из них (используя NetBeans, поэтому ваши результаты могут незначительно отличаться):

public abstract <K> A<? extends Number> useMe(A<? super K> k);
// seems to work

public abstract <K> A<? super Number> useMe(A<? extends K> k);
// type parameter ? extends K is not within its bound

public abstract <K> A<K> useMe(A<K> k);
// type parameter K is not within its bound

public abstract <V extends K> A<V> useMe(A<V> k);
// seems to work

public abstract <V super K> A<V> useMe(A<V> k);
// > expected
// illegal start of type
// <identifier> expected
// missing method body, or declare abstract
// cannot find symbol
//   symbol: class V
//   location: class A<K>

public abstract <V extends Character> A<? super V> useMe(A<K> k);
// type parameter ? super V is not within its bound

public abstract <V super Character> A<? super V> useMe(A<K> k);
// > expected
// illegal start of type
// <identifier> expected
// missing method body, or declare abstract
person Bill the Lizard    schedule 26.05.2010
comment
Спасибо за ваш ответ! Я также пытался скормить компилятору этот код. Я хочу понять логику компилятора. Например, третий вариант: почему К не в пределах? - person abatishchev; 26.05.2010
comment
@abatishchev: в объявлении класса указано, что K extends Number, но в третьем варианте используется неограниченное K. Я гуглил каждое сообщение об ошибке или проверял Java Generics Учебник для получения более подробной информации о том, что разрешено. - person Bill the Lizard; 26.05.2010

Я попытаюсь объяснить немного больше...

1 не работает, потому что вы не можете заменить A<? super K> на A<K extends Number>... нет гарантии, что суперкласс расширяет тот же класс, что и подкласс.

1, 2 и 3 не работают, потому что параметр начального типа скрывает исходный K, используемый в объявлении класса.

5 не работает, потому что <V super K> не может заменить <K extends Number>... нет гарантии, что суперкласс расширяет тот же класс, что и подкласс.

6 и 7 должны быть очевидны.

4 работает, потому что если мы знаем, что V расширяет K, то мы знаем, что V расширяет Number (поскольку все классы, которые K расширяет V, расширяются). Поэтому мы можем заменить A<V> на <K extends Number>.

Я надеюсь, что это имеет смысл ... кто-то может прийти и объяснить лучше.

person derivation    schedule 26.05.2010

Кажется, работает только второй (public abstract A useMe(A k);), просто подключив его к IDE.

person James Kingsbery    schedule 26.05.2010