结合番石榴的ImmutableList和varargs

Sta*_*lin 9 java generics variadic-functions guava

我想创建构造函数,它将采用一个或多个整数并将其作为ImmutableList保存到字段中.根据Bloch的第42项"使用varargs传递一个或多个论点的正确方法",我创建了smt

class Foo{
    private final ImmutableList<Integer> bar;
    public Foo(Integer first, Integer... other) {
        this.bar = ImmutableList.<Integer>builder()
                .add(first)
                .addAll(Arrays.asList(other))
                .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么构建器不会自动获得通用?而且,因为它闻起来.我怎么能改写它?

UPD qustion泛型解决.任何有关重构的建议都非常有用.

Boz*_*zho 14

因为在调用时builder()没有左侧的表达式.编译器无法推断要添加的类型.(它无法从后续方法调用中推断出来)

如果将其更改为以下内容,则可以:

Builder<Integer> builder = ImmutableList.builder();
this.bar = builder.add(first).addAll(Arrays.asList(other)).build();
Run Code Online (Sandbox Code Playgroud)

但是,您可以安全地保留当前代码 - 这很好.甚至比上面的例子更好(它更短)

关于重构 - 为什么不使用.add(first).add(other)?该add方法具有varargs版本.


Eti*_*veu 8

关于你的第二个问题(如何重构你的构造函数,使其更短/更可读),我会这样做:

class Foo{
    private final ImmutableList<Integer> bar;
    public Foo(Integer first, Integer... other) {
        this.bar = ImmutableList.copyOf(Lists.asList(first, other));
    }
}
Run Code Online (Sandbox Code Playgroud)

这两个Lists.asList在设计时考虑到这一目标的方法,根据自己的javadoc:

当varargs方法需要使用诸如(Foo firstFoo,Foo ... moreFoos)之类的签名时,这是有用的,以避免过载歧义或强制执行最小参数计数.

它比ImmutableList.Builder更高效,因为它避免了在Builder内部创建/调整临时ArrayList.