Дженерики Java: Предупреждение потребностей бросок непроверенный для приспосабливания <InterfaceName>

Многие люди не понимают, что они могут сравнивать строки, используя: OrdinalIgnoreCase вместо необходимости выполнять someString.ToUpper (). Это устраняет дополнительные накладные расходы на выделение строк.

if( myString.ToUpper() == theirString.ToUpper() ){ ... }

становится

if( myString.Equals( theirString, StringComparison.OrdinalIgnoreCase ) ){ ... }
5
задан Tom Hawtin - tackline 24 July 2009 в 17:27
поделиться

4 ответа

Вторая версия интерфейса неверна. В нем говорится, что getValue вернет любой подкласс, который вы запрашиваете - тип возвращаемого значения будет выведен на основе выражения в левой руке.

Итак, если вы получите ссылку на x (назовем его obj ), вы можете законно сделать следующий вызов без предупреждений компилятора:

x obj = ...;
B b = obj.getValue();

Что, вероятно, неверно в вашем примере, потому что если вы добавите другой класс C , который также расширяет A , вы также можете законно сделать вызов:

C c = obj.getValue();

Это потому, что T не является переменной типа, принадлежащей интерфейсу, а только самому методу.

4
ответ дан 14 December 2019 в 04:44
поделиться

В основном, когда вы выполняете , вы говорите, что вам нужен конкретный подкласс A, а не какой-либо A, потому что тогда вы могли бы просто сделать:

 A getValue();

Компилятор предупреждает вас, что он не может гарантировать, что будет возвращен конкретный определенный подкласс A, только сам A.

РЕДАКТИРОВАТЬ: Чтобы попытаться объяснить это лучше, B является подклассом A, но не t должен быть единственным подклассом A. Рассмотрим следующую иерархию.

B расширяет A C расширяет A, но не B

Теперь у меня есть метод:

public void someMethod(x value) {
    C c = x.getValue();
}

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

Но что, если вы передадите экземпляр y этому методу?

Что ж, теперь я получаю B вместо C. предупреждает, что это могло произойти.

3
ответ дан 14 December 2019 в 04:44
поделиться

Компилятор сообщает вам, что нет никакого способа разрешить общий. T нигде не определен, кроме как output - о каком T вы говорите? Если бы интерфейс был сгенерирован как тип T:

interface x <T extends A> {
    T getValue()
}

, тогда это сработало бы, или если бы метод принял значение, которое определило бы, какой тип возврата вы хотите:

interface x {
    <T extends A> T getValue(T someArgument)
}

или

interface x {
    <T extends A> T getValue(Class<T> someArgument)
}

, тогда предупреждения не будет.

править: См. Сообщение свиристеля для объяснения того, почему вы НЕ должны использовать дженерики для этой конкретной проблемы. Я просто показываю, насколько подходят дженерики.

1
ответ дан 14 December 2019 в 04:44
поделиться

Итак, чтобы опираться на два ответа от AlbertoPL и Yishai, попробуйте следующее:

class y implements x {
    A getValue(){ return new B();}
}

B расширяет A, так что это нормально. Вызывающему не нужно знать, какой подкласс A возвращается, только то, что он расширяет A. Итак, мы идем :)

0
ответ дан 14 December 2019 в 04:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: