使用 Java 泛型返回包装的对象



我正在尝试为过滤问题编写一个通用解决方案,其中我们有几个列表,这些列表将受到过滤器列表(或约束(的约束。

为了支持这一点,我有以下泛型类:

public class Constrained<T> {
    private T object;
    List<TraitFilter> filters;
    public T getObject() {
        return object;
    }
}

这将允许我让任何类的对象被约束列表包装。

现在,我正在尝试编写一个可以运行筛选器的服务。我希望能够在服务中编写这样的函数:

List<T> filtered(Constrained<T>, traits);

但是Java不喜欢这样。它说T没有定义。我换成了以下内容:

List<? extends Object> filtered(List<Constrained<?>> possible, Traits traits);

像这样的Java,无论是在定义函数的接口中还是在实现中,直到我编写了一个实际尝试使用该函数的测试。

final List<Constrained<DecisionTemplate>> dtList =
   Arrays.asList(ConstrainedDecisionTemplateFixtures.LUO_ONLY_POLICIES(),
                 ConstrainedDecisionTemplateFixtures.LUOA_AGREEMENT());
List<DecisionTemplate> actual = instance.filtered(dtList, expectedTraits);

我的 IDE 报告以下错误消息:

 Wrong 1st argument type. Found
 'java.util.List<Constrained<DecisionTemplate>>', required:
 'java.util.List<Constrained<? extends java.lang.Object>>

我需要更改什么才能使用返回类 T 的解包对象的泛型函数?

为了

能够声明:

List<T> filtered(List<Constrained<T>> traits);

(请注意,我假设您想要的参数实际上是ConstrainedList,而不是单个(...

您需要将方法声明为泛型并使用 T 进行参数化的接口。

您需要将实现范围缩小到特定的参数化类型,即 DecisionTemplate在实施中。

还可以使用以下语法声明泛型方法:

<T extends DecisionTemplate>List<T> filtered(List<Constrained<T>> traits);

。如果您不想拥有通用接口。

// with a generic method...
interface Foo {
    <T extends DecisionTemplate>List<T> filtered(List<Constrained<T>> traits);
}
class Blah implements Foo {
    @Override
    public <T extends DecisionTemplate> List<T> filtered(
        List<Constrained<T>> traits) {
        // TODO populate
        return null;
    }
}
// with a generic class/interface
interface FooGeneric<T> {
    List<T> filtered(List<Constrained<T>> traits);
}
class BlahGeneric implements FooGeneric<DecisionTemplate> {
    @Override
    public List<DecisionTemplate> filtered(
        List<Constrained<DecisionTemplate>> traits) {
        // TODO populate
        return null;
    }
}

客户

// invoking generic method
// TODO populate
List<Constrained<DecisionTemplate>> list = new ArrayList<>(); 
List<DecisionTemplate> filtered = new Blah().filtered(list);
// invoking generic class/interface's method
// TODO populate
List<Constrained<DecisionTemplate>> anotherList = new ArrayList<>();
List<DecisionTemplate> anotherFiltered = new BlahGeneric().filtered(anotherList);

最新更新