[英]How to create method that will return List of any class that extends one superclass
I am developing a small web app in Spring. 我在春季正在开发一个小型Web应用程序。
I would like to avoid repeating code and thus I would like to create one method in service layer that will call appropriate DAO's method based on arguments. 我想避免重复代码,因此我想在服务层中创建一个方法,该方法将基于参数调用适当的DAO方法。
For one abstract payment class i have three subclasses (energy, water, gas). 对于一个抽象的支付类别,我有三个子类别(能源,水,天然气)。 Also I have enum class called Media
. 我还有一个叫做Media
枚举类。
In the service I wanted to create something like this: (based on How to have Java method return generic list of any type? ) 在服务中,我想创建类似以下的内容:(基于如何使Java方法返回任何类型的通用列表? )
@Autowired
ReadingDao<ReadingEnergy, InvoiceEnergy> energy;
@Autowired
ReadingWaterDAO water;
@Autowired
ReadingDao<ReadingGas, InvoiceGas> gas;
@Override
public <T extends ReadingAbstract> List<T> getReadingsForTenant(Apartment apartment, Media media) {
ReadingAbstract gg = new ReadingEnergy();
switch (media) {
case ENERGY:
return energy.getListForTenant(apartment);
break;
case GAS:
return gas.getListForTenant(apartment);
break;
case WATER:
return water.getListForTenant(apartment);
break;
default:
throw new IllegalArgumentException();
}
return null;
}
Unfortunately I get 不幸的是我得到了
Type mismatch: cannot convert from List<ReadingEnergy> to List<T>
I have also tried with this: 我也尝试过这样:
public List<?> getReadingsForTenant(Apartment apartment, Media media) {
switch (media) {
case ENERGY:
System.out.println("getReadingsForTenant - energia");
return energy.getListForTenant(apartment);
case GAS:
System.out.println("getReadingsForTenant - gas");
return gas.getListForTenant(apartment);
case WATER:
System.out.println("getReadingsForTenant - woda");
return water.getListForTenant(apartment);
default:
throw new IllegalArgumentException();
}
}
This generally works BUT when I create a new object 当我创建一个新对象时,这通常可以使用
Apartment ap = (some apartment);
List<ReadingWater> list = (List<ReadingWater>) readingService.getReadingsForTenant(ap, Media.WATER);
I get: 我得到:
Type safety: Unchecked cast from List<capture#3-of ?> to List<ReadingWater>
I could use @SuppressWarnings("unchecked")
but that doesn't look to good for me. 我可以使用@SuppressWarnings("unchecked")
但这对我来说并不好。
What is the proper way to handle such stuff? 处理此类东西的正确方法是什么?
You can't have a return type which depends upon a runtime argument: types have to be known at compile time. 您不能有依赖于运行时参数的返回类型:必须在编译时知道类型。
The only return type of this method which can be matched for all of your return statements is: List<? extends ReadingAbstract>
可以与所有return语句匹配的此方法的唯一返回类型是: List<? extends ReadingAbstract>
List<? extends ReadingAbstract>
. List<? extends ReadingAbstract>
。 It could maybe be List<ReadingAbstract>
, but only if your DAOs return that type. 可能是List<ReadingAbstract>
,但List<ReadingAbstract>
是您的DAO返回该类型。
If you want to know the specific element type of the list, you need a separate method for each media type: 如果要了解列表的特定元素类型,则需要为每种媒体类型使用单独的方法:
public List<ReadingWater> getWaterReadingsForTenant(Apartment apartment);
public List<ReadingGas> getGasReadingsForTenant(Apartment apartment);
// etc.
which works for your example use case, since you are statically specifying Media.WATER
: just statically call getWaterReadingsForTenant
instead. 该方法适用于您的示例用例,因为您静态指定了Media.WATER
:只需静态调用getWaterReadingsForTenant
。
I could use @SuppressWarnings("unchecked") but that doesn't look to good for me. 我可以使用@SuppressWarnings(“ unchecked”),但这对我来说并不好。
Compiler warnings are there for a reason. 出现编译器警告是有原因的。 You could equally have written this: 您同样可以这样写:
List<ReadingWater> list =
(List<ReadingWater>) readingService.getReadingsForTenant(ap, Media.GAS);
and that would cause a runtime failure - just not at this line. 这会导致运行时失败-只是不在此行。 So then you'd have a hog of a time tracking down why you're getting ClassCastException
s in far distant code. 因此,您将花费大量的时间来追踪为什么在远距离的代码中获得ClassCastException
的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.