T
в getPayService
будет расширяться Animal
, конечно.Это означает, что код, вызывающий его с другим типом, не будет компилироваться:
Fruit fruit = animalLocator.getPayService("Banana")
Чтобы проиллюстрировать вашу текущую проблему , посмотрите на это:
Cat cat = animalLocator.getPayService("Dog");
T
в данном случае Cat
, но ваш код будет возвращать Dog
.
Чтобы обойти ошибку компилятора, вы можете добавить приведение типа:
return (T) applicationContext.getBean(...
Но этовсе равно не будет безопасным, потому что компилятор по-прежнему не сможет гарантировать, что фактический тип возвращаемого значения будет таким, как T
в контексте вызывающего во время выполнения, и у вызывающего будет исключение приведения класса.
Если мы можем предположить, что getBean
является безопасным вызовом, то вы должны изменить свой метод на эту реализацию:
public <T extends Animal> T getPayService(String name, Class<T> cls) {
return applicationContext.getBean(name, cls);
}
Это не сильно изменится с точки зрения вызывающего, но зависит отфакт (или предположение), что applicationContext.getBean(name, cls);
вернет объект типа T
.Это означает, что ваш код безопасен по типу, как getBean
, но компилятор этим доволен.