我正在开发一个小型的Web应用程序。
我想避免重复代码,因此我想在服务层中创建一个方法,它将根据参数调用适当的DAO方法。
对于一个抽象支付类,我有三个子类(能源,水,天然气)。
我还有一个名为Media
的枚举类。
在服务中我想创建这样的东西: (基于How to have Java method return generic list of any type?)
@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;
}
不幸的是我得到了
Type mismatch: cannot convert from List<ReadingEnergy> to List<T>
我也试过这个:
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();
}
}
这通常在我创建新对象时起作用
Apartment ap = (some apartment);
List<ReadingWater> list = (List<ReadingWater>) readingService.getReadingsForTenant(ap, Media.WATER);
我明白了:
Type safety: Unchecked cast from List<capture#3-of ?> to List<ReadingWater>
我可以使用@SuppressWarnings("unchecked")
,但这对我来说并不好。
处理此类内容的正确方法是什么?
答案 0 :(得分:2)
您不能拥有依赖于运行时参数的返回类型:必须在编译时知道类型。
此方法的唯一返回类型可以匹配所有返回语句:List<? extends ReadingAbstract>
。它可能可能为List<ReadingAbstract>
,但前提是您的DAO返回该类型。
如果您想知道列表的特定元素类型,则需要为每种媒体类型使用单独的方法:
public List<ReadingWater> getWaterReadingsForTenant(Apartment apartment);
public List<ReadingGas> getGasReadingsForTenant(Apartment apartment);
// etc.
适用于您的示例用例,因为您静态指定Media.WATER
:只是静态调用getWaterReadingsForTenant
。
我可以使用@SuppressWarnings(“unchecked”),但这对我来说并不好。
编译器警告是有原因的。你也可以这样写:
List<ReadingWater> list =
(List<ReadingWater>) readingService.getReadingsForTenant(ap, Media.GAS);
这会导致运行时失败 - 只是不在这一行。那么你就要花时间追踪为什么你会在遥远的代码中获得ClassCastException
。