在构造函数中指定重复的泛型类型?

时间:2017-08-03 21:42:41

标签: java generics types constructor

假设我有以下课程:

import java.util.function.Function
import java.util.List

class Foo<X, Y> {
    public Function<X, Y> converter;
    public List<X> inputs;

    public Foo(Function<X, Y> converter, List<X> inputs) {
        this.converter = converter;
        this.inputs = inputs;
    }
}

我想添加一个构造函数,该构造函数接受List<X>个输入,并自动提供一个标识函数以与其一起使用:

public Foo(List<X> inputs) {
    this(Function.identity(), inputs);
}

但是,这给了我一个错误:The constructor Foo<X, Y>(Function<Object,Object>, List<X>) is undefined。 另一方面,以下编译:

public static <X> Foo<X, X> makeFoo(List<X> inputs) {
    return new Foo<>(Function.identity(), inputs);
}

事实上,以下内容也有效:

public Foo(List<X> inputs) {
    this.converter = (Function<X, Y>)Function.identity();
    this.inputs = inputs;
}

然而,我必须在Function<Object, Object> to Function<X, Y>进行未经检查的演员表。它会起作用,但我了解到通常有一种方法可以处理不需要转换的泛型(或Java中的任何东西)。

有没有办法让构造函数使用它而不是使用静态方法或者转换?

我尝试使用this((Function<X, X>)Function.identity(), inputs)调用其他构造函数,将构造函数重写为public Foo<X, X>(List<X> inputs),并使用<X, X>this(Function.identity(), inputs)调用其他构造函数,但无效。

似乎应该有一种方法让编译器知道Function.identity()参数或Foo创建的类型<X, X>类型,但我不能想出任何好的地方。我环顾四周,找不到以任何方式强制转换或指定类型的方法。我能找到的最接近主题的是类型证人,&#34; BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);&#34;来自here,但这似乎是一个不同的场景。还有一些有趣的&#34; new <TypeWitnessForConstructor> Box<TypeArgumentsForInstance>(...)&#34;来自this SO回答的建议,但这似乎也不适用。我认为原因既不适用也是因为我的构造函数没有任何类型参数,例如public <Z> Foo(...)

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

不,没有更好的方法。您不能将此构造函数限制为仅在XY相同类型时才起作用,因此构造函数必须假设它们不同,并且Function.identity()相应地不一定是正确的类型。

也就是说,使用静态工厂方法通常比暴露构造函数更好,如果你这样做,你会没事的。