如何创建将返回扩展一个超类的任何类的List的方法

时间:2016-06-16 08:33:26

标签: java generics

我正在开发一个小型的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"),但这对我来说并不好。

处理此类内容的正确方法是什么?

1 个答案:

答案 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