简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM