A cleaner way to handle varags in @FunctionalInterface?

Consider this interface:

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

      

And this class:

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

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

      

With these words, I can write:

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

new Wrapper(f);

      

but I cannot write:

new Wrapper(Path::toRealPath);

      

The problem is with the prototype of the method . It can take a value as an argument LinkOption...

.

However, the compiler is capable of "coercing" a method reference here. The only way I have come up with to emulate this is completely useless:

@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);
        }
    }
}

      

Then add a new constructor to Wrapper

:

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

      

Is there a cleaner way to do this? That is, can I do "like a compiler" in this case?

+3


source to share


1 answer


You can specify types Wrapper

at initialization.

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

      

or

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

      



I think it has nothing to do with varargs. By specifying the types, you are also telling the compiler to "ignore" the varargs parameter.


Note, I've seen that you can also "ignore" the return type of the same function:

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;
}

      

+1


source







All Articles