Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
 Снова про дженерики  [new]
Molasar
Member

Откуда:
Сообщений: 767
Всем привет!

Почему нет ошибки в реализации metodA в MyClass1? Ведь необходимо указать использование дженерика.
Правильно ли реализован metodA в классе MyClass2 или криво?
public interface MyInterface {

    <T> void metodA(List<T> objectList);
    
}
public class MyClass1<T> implements MyInterface {
    
    private List<T> objectList;

    @Override
    public void metodA(List objectList) {
        this.objectList = objectList;
    }

}
public class MyClass2<T> implements MyInterface {
    
    private List<T> objectList;

    @Override
    public <V> void metodA(List<V> objectList) {
        this.objectList = (List<T>) objectList;
    }

}
23 июл 19, 17:39    [21932950]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7934
Molasar
Ведь необходимо указать использование дженерика.

Зачем?

Странно, что он на второй класс не ругается, т.к. что может означать конструкция " <V> void" я вообще не представляю.
23 июл 19, 18:39    [21932998]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2149
Я так понимаю, что метод ничего не возвращает. Значит просто void. Imho
23 июл 19, 18:52    [21933018]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1279
Generic methods это "отдельная песня" в мире генериков. Это generic на уровне метода, а не на уровне классов/интерфейсов.

Пример с потолка.
public class Utils {
    
    public static <T> T findBean(ApplicationContext applicationContext, Class<T> requiredClass) {
        return applicationContext.getBean(requiredClass);
    }

    public static void main(String[] args) {
        ApplicationContext applicationContext = ...;
        // тут никаких кастов нет, иммено благодаря generic method
        Dao dao = findBean(applicationContext, Dao.class); 
        Service serviec = findBean(applicationContext, Dao.class);
    }
    
}
на самом деле applicationContext.getBean уже использует generic methods, так что тут конечно пример притянут за уши.
23 июл 19, 19:14    [21933035]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2149
vas0
пример притянут за уши.
да притянут. Давай другой.
Приведение типов есть.
Вот тут не будет:
var obj = findBean(...
23 июл 19, 19:26    [21933050]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1279
PetroNotC Sharp,

Я там наделал кучу ошибок, но в целом идея то должна быть понятна.
public class Utils {
    
    public static Object findBean(ApplicationContext applicationContext, Class requiredClass) {
        return applicationContext.getBean(requiredClass);
    }

    public static <T> T findBeanEx(ApplicationContext applicationContext, Class<T> requiredClass) {
        return applicationContext.getBean(requiredClass);
    }

    public static void main(String[] args) {
        ApplicationContext applicationContext = ...;

        // тут нужны касты и можешь получить ошибки в runtime
        Dao dao = (Dao) getBean(applicationContext, Dao.class);
        Service service = (Service) getBean(applicationContext, Service.class);


        // тут приведение типов не нужно и еще получаешь проверку во время компиляции
        Dao dao = getBeanEx(applicationContext, Dao.class);
        Service service = getBeanEx(applicationContext, Service.class);
    }
    
}
23 июл 19, 19:34    [21933056]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2149
vas0,
Да. Теперь лучше))
23 июл 19, 19:36    [21933060]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
Molasar
Member

Откуда:
Сообщений: 767
Если во 2-м классе оставляем только один <T>
public class MyClass2<T> implements MyInterface {
    
    private List<T> objectList;

    @Override
    public <T> void metodA(List<T> objectList) {
        this.objectList = objectList;
    }

}
, то получим ошибку:
incompatible types: List<T#1> cannot be converted to List<T#2>
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>metodA(List<T#1>)
T#2 extends Object declared in class MyClass
----

Leonid Kudryavtsev
Molasar
Ведь необходимо указать использование дженерика.

Зачем?

Странно, что он на второй класс не ругается, т.к. что может означать конструкция " <V> void" я вообще не представляю.
24 июл 19, 09:26    [21933238]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1279
Molasar
Если во 2-м классе оставляем только один <T>
public class MyClass2<T> implements MyInterface {
    
    private List<T> objectList;

    @Override
    public <T> void metodA(List<T> objectList) {
        this.objectList = objectList;
    }

}

здесь параметризованый тип <T> у метода "затеняет" параметризованый тип <T> твоего класса.
<T> void metodA(List<T> objectList)

здесь лучше написать
<U> void metodA(List<U> objectList)

а так как List<T> и List<U> разные типы, то компилятор потребует приведения типов
    public <U> void metodA(List<U> objectList) {
        this.objectList = (List<T>) objectList;
    }

либо можно изменить сигнатуру метода (думаю компилятор это должно "успокоить")
    public <U extends T> void metodA(List<U> objectList)
24 июл 19, 09:55    [21933253]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
Molasar
Member

Откуда:
Сообщений: 767
Как тогда объявлять в интерфейсе такой метод?
public <U extends T> void metodA(List<U> objectList)


vas0
Molasar
Если во 2-м классе оставляем только один <T>
public class MyClass2<T> implements MyInterface {
    
    private List<T> objectList;

    @Override
    public <T> void metodA(List<T> objectList) {
        this.objectList = objectList;
    }

}

здесь параметризованый тип <T> у метода "затеняет" параметризованый тип <T> твоего класса.
<T> void metodA(List<T> objectList)

здесь лучше написать
<U> void metodA(List<U> objectList)

а так как List<T> и List<U> разные типы, то компилятор потребует приведения типов
    public <U> void metodA(List<U> objectList) {
        this.objectList = (List<T>) objectList;
    }

либо можно изменить сигнатуру метода (думаю компилятор это должно "успокоить")
    public <U extends T> void metodA(List<U> objectList)
24 июл 19, 10:16    [21933269]     Ответить | Цитировать Сообщить модератору
 Re: Снова про дженерики  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1279
Molasar,

В интерфейсе это будет просто генерик метод
<Z> void metodA(List<Z> objectList);

А уже конкретные реализации могут добавлять деталей
<Z extends Number> void metodA(List<Z> objectList);

При этом типы лучше не затенять (чтобы не терять понимание). У меня ни разу не было случая чтобы я переопределял generic методы в наследниках, так как они уже и так сами по себе очень "параметризуемые и гибкие".
24 июл 19, 10:32    [21933282]     Ответить | Цитировать Сообщить модератору
Все форумы / Java Ответить