更清洁的方法来处理@FunctionalInterface中的varags?

时间:2014-12-31 15:52:16

标签: java lambda java-8 type-inference

考虑这个界面:

@FunctionalInterface
public interface ThrowingFunction<T, R>
{
    R tryApply(T t)
        throws Throwable;
}

这节课:

public final class Wrapper<T, R>
{
    private final ThrowingFunction<T, R> f;

    public Wrapper(final ThrowingFunction<T, R> f)
    {
        this.f = f;
    }
}

有了这些,我可以写:

final ThrowingFunction<Path, Path> f = Path::toRealPath;

new Wrapper(f);

但我无法写:

new Wrapper(Path::toRealPath);

问题归因于the method prototype可以LinkOption...作为参数。

然而,编译器能够在此强制“强制”方法引用。我想出来的唯一方法是模仿这个是彻头彻尾的hackish:

@FunctionalInterface
public interface ThrowingFunction<T, R>
{
    R tryApply(T t)
        throws Throwable;

    @FunctionalInterface
    interface WithVarags<T, V, R>
        extends ThrowingFunction<T, R>
    {
        R tryApplyWithVarargs(T t, V... ignored)
            throws Throwable;

        @Override
        default R tryApply(T t)
            throws Throwable
        {
            return tryApplyWithVarargs(t);
        }
    }
}

然后在Wrapper

中添加新的构造函数
public <V> Wrapper(
    final ThrowingFunction.WithVarags<T, V, R> function)
{
    this.function = function;
}

有更清洁的方法吗?也就是说,在这种情况下我可以“像编译器一样”吗?

1 个答案:

答案 0 :(得分:1)

您可以在实例时指定Wrapper的类型。

new Wrapper<Path, Path>(Path::toRealPath);

Wrapper<Path, Path> wrapper = new Wrapper<>(Path::toRealPath);

我认为这与varargs无关。通过指定类型,您还要对编译器说&#34;忽略&#34; varargs参数。


注意,我看到你也可以&#34;忽略&#34;同一函数的返回类型:

ThrowingBiConsumer<Path, LinkOption[]> biConsumer =  Path::toRealPath;
new Wrapper<Path, LinkOption[]>(Path::toRealPath);


public interface ThrowingBiConsumer<T, U> {
    void accept(T t, U u) throws Throwable;
}