考虑这个界面:
@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;
}
有更清洁的方法吗?也就是说,在这种情况下我可以“像编译器一样”吗?
答案 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;
}