Непроверенное предупреждение о конверсии - PullRequest
1 голос
/ 27 декабря 2011

Ниже приведено определение моего интерфейса

interface IStorage {
   <T extends ICommon> Collection<T> find(String name, boolean isExact);
}

И это реализация

Storage implements IStorage {
    Collection<IOrganization> find(String name, boolean isExact) {
       //some code
    }
}

IOrganization является подтипом ICommon.

Почему я все еще вижу предупреждение о непроверенной конверсии?

Ответы [ 4 ]

3 голосов
/ 27 декабря 2011

Поскольку, как вы уже написали, ваш интерфейс указывает, что find() возвращает Collection из что-то , что расширяет ICommon

Ваша реализация возвращает Collection из определенный подкласс из ICommon.Насколько компилятор может сказать, это непроверенное преобразование;что произойдет, если Collection действительно содержит какой-то другой подкласс ICommon?

1 голос
/ 27 декабря 2011

Если целью вашего интерфейса является определение метода find с аргументами String name, boolean isExact, чтобы клиенты могли знать, какой конкретный элемент ICommon возвращается (например, клиент может просто получить Collection<IOrganization> вместо Collection<? extends ICommon>, тогда ваша подпись интерфейса должна быть следующей:

interface IStorage<T extends ICommon> {
Collection<T> find(String name, boolean isExact);
}

Затем реализация изменится на следующее:

class Storage implements IStorage<IOrganization> {
Collection<IOrganization> find(String name, boolean isExact) {
return null; // whatever you would return.
}
}

Обратите внимание, что это отличается тем, что вы определили интерфейс, который объявляет определенный тип, который будет возвращен через метод find, тогда как ранее можно было только сказать, что был возвращен тип ICommon или какой-то неизвестный подтип, поэтому вы пытались привести к ICollection, компилятор не смог убедиться, что вы всегда могли это сделать (если вы дали ему реализацию, которая не была ICollection, вы можете получить ClassCastException во время выполнения).

0 голосов
/ 27 декабря 2011

Если у вас есть универсальный метод, такой как <T extends ICommon> Collection<T> find(..., это означает, что вызывающая сторона может запросить, чтобы T было чем угодно.Это означает, что метод должен работать с любым таким типом T, а не иметь возможность выбирать конкретный тип T (что вы, похоже, хотите сделать).Чтобы продемонстрировать, ваш универсальный метод позволяет вызывающей стороне сказать

IStorage obj = ...;
Collection<SomeRandomClassImplementingICommon> foo = obj.find(...);

, но ваш Collection<IOrganization> find(... метод не совместим с вышеупомянутым, потому что он не возвращает тип Collection<SomeRandomClassImplementingICommon>.

0 голосов
/ 27 декабря 2011

Сохраняйте ту же подпись, пока вы определяете Storage, потому что вы все еще определяете метод find (и не используете его):

Storage implements IStorage {
    <T extends ICommon> Collection<T> find(String name, boolean isExact) {
       //some code
    }
}

Вы будете указывать конкретный параметр типа, когда вы фактически вызываетеэтот универсальный метод:

Storage s = new Storage();
s.<IOrganization>find("hello world", true);

Но тип параметра T, который вы вводите с помощью <T extends ICommon> в универсальном методе, бесполезен, поскольку его нет в списке параметров.

Может быть, то, что вы, вероятно, хотите, не является универсальным методом.Но что-то следующее:

interface IStorage {
    public Collection<? extends ICommon> find(String name, boolean isExact);
}

//and
class Storage implements IStorage {
    public Collection<IOrganization> find(String name, boolean isExact) {
        //some code                
    }
}

//or 
class Storage implements IStorage {
    public Collection<? extends ICommon> find(String name, boolean isExact) {
        //some code  
    }
}
...