#FunctionalInterface that also implements andThen? - java

I'm trying to create a functional interface that can throw an custom exception, what I've come up with is.
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
#FunctionalInterface
public interface ThrowingFunction<T, R> {
R apply(T t) throws MyException;
}
This works great for using the apply function but the problem is I'd also like to use the andThen capabilities of Java's functions. When I try to do something like.
ThrowingFunction<Integer, Integer> times2WithException = (num) -> {
if(num == null) {
throw new MyException("Cannot multiply null by 2");
}
return num * 2;
};
times2WithException.andThen(times2WithException).apply(4);
I get the error
Cannot find symbol: method andThen(ThrowingFunction<Integer, Integer>)
Is there something I should use instead of FunctionalInterface? Or is there another function I need to implement to get it to work with andThen?
Thanks!

Functional interfaces are only allowed to specify one unimplemented function. But you can specify default functions that already have an implementation like this:
#FunctionalInterface
public interface ThrowingFunction<T, R> {
R apply(T t) throws MyException;
default <U> ThrowingFunction<T, U> andThen(ThrowingFunction<R, U> follow) {
Objects.requireNonNull(follow); // Fail fast
return t -> follow.apply(this.apply(t));
}
}

Where are you expecting the andThen method to come from? You haven't defined it anywhere!
#FunctionalInterface
interface ThrowingFunction<T, R> {
R apply(T t) throws MyException;
default <V> ThrowingFunction<T, V> andThen(ThrowingFunction<R, V> after) {
return (T t) -> after.apply(apply(t));
}
}
Here, you can take advantage of default methods in interfaces to create an andThen function.

Related

Label a generic type argument bounded with super

To specify my rather tricky problem, a bit of explanation is required so please bear with me.
I'm designing minimalist interfaces for an observable pattern that uses managing ListenerHandles instead of a removeListener(...) method in the observable class.
This is the idea:
public interface ListenerHandle<T> {
boolean isRemoved();
void remove();
Listener<T> managedListener();
Observable<T> containingObservable();
}
public interface Observable<T> {
T get();
void set(T value);
ListenerHandle<T> addListener(Listener<T> listener);
}
public interface Listener<T> {
void onChange(ListenerHandle<T> handle, T value);
}
Now this works perfectly fine.
But what if I wanted Observable<T> to accept more general Listeners? Listener<? super T>s to be precise. This makes sense, since a listener that expects ? super T will also accept T (it is contravariant).
As a consequence, ListenerHandle would need to differentiate between T of the Observable it was obtained from, and T of the managed Listener:
public interface ListenerHandle<TL, TO> {
// ...
Listener<TL> managedListener();
Observable<TO> containingObservable();
}
public interface Observable<TO> {
// ...
<TL> ListenerHandle<TL, TO> addListener(Listener<TL> listener);
}
public interface Listener<TL> {
void onChange(ListenerHandle<TL, ? extends TL> handle, TL value);
}
Even though these interfaces will compile, we know that TL in
<TL> ListenerHandle<TL, TO> addListener(Listener<TL> listener);
is a bit too generic, because it can now be anything. However, Observable should only be able to take listeners, that expect TO or its super types:
<TL super TO> ListenerHandle<TL, TO> addListener(Listener<TL> listener);
This will not work since super can only be used on wildcards. So another option is:
ListenerHandle<? super TO, TO> addListener(Listener<? super TO> listener);
In this case, however, the caller will lose the information that the returned ListenerHandle's ? super TO and listener's ? super TO will be identical:
Observable<Number> o = ...;
Listener<Object> l = ...;
// does not work, but should (since we know that we passed a Listener<Object>)
ListenerHandle<Object, Number> h = o.addListener(l);
// works but Object is now generalized to ? super Number
ListenerHandle<? super Number, Number> h2 = o.addListener(l);
l = h2.managedListener(); // fails because ? super Number is not (necessarily) Object
So, what I need is a way to specify a labeled type argument bounded with super, to demonstrate, that the bounded generic type of the argument is identical to the bounded generic type of the return type. How could I do this?
Instead of adding a generic parameter TL for the type of Listener, you could make it a Listener<? super T>:
public interface ListenerHandle<T> {
boolean isRemoved();
void remove();
Listener<? super T> managedListener();
Observable<T> containingObservable();
}
public interface Observable<T> {
T get();
void set(T value);
ListenerHandle<T> addListener(Listener<? super T> listener);
}
public interface Listener<T> {
<TO extends T> void onChange(ListenerHandle<TO> handle, TO value);
// or:
// void onChange(ListenerHandle<? extends T> handle, T value);
}
If you really need to add the TL parameter to ListenerHandle, I think the only way to do it would be the static method workaround:
public interface ListenerHandle<TL, TO extends TL> {
boolean isRemoved();
void remove();
Listener<TL> managedListener();
Observable<TO> containingObservable();
}
public interface Observable<TO> {
TO get();
void set(TO value);
// #Deprecated
ListenerHandle<?, TO> addListener(Listener<? super TO> listener); // implies ListenerHandle<? super TO, TO>
#SuppressWarnings("unchecked")
static <TL, TO extends TL> ListenerHandle<TL, TO> addListener(Observable<TO> observer, Listener<TL> listener) {
return (ListenerHandle<TL, TO>) observer.addListener(listener);
}
}
public interface Listener<TL> {
void onChange(ListenerHandle<TL, ?> handle, TL value); // implies ListenerHandle<TL, ? extends TL>
}
You would have to remember never to call obs.addListener(lis) directly, but instead use Observable.addListener(obs, lis). Marking it as #Deprecated would give you a warning, but you'd need to put that on all the overriding methods as well.

How to not throw a generically specified exception?

I created a "producer" interface (to be used with method references, respectively to be easily mocked for unit tests):
#FunctionalInterface
public interface Factory<R, T, X extends Throwable> {
public R newInstanceFor(T t) throws X;
}
which I created like that, as my first use case actually had to throw some checked WhateverException.
But my second use case doesn't have an X to throw.
The best I could come up with to make the compiler happy is:
Factory<SomeResultClass, SomeParameterClass, RuntimeException> factory;
That compiles, and does what I need, but still ugly. Is there a way to keep that single interface, but not provide an X when declaring specific instances?
You cannot do that in Java. The only way is to create a sub interface.
public interface DefaultExceptionFactory<R, T>
extends Factory<R, T, RuntimeException>
The only way to do it is subclassing - but I bet you knew that. To make my argument stronger, look at BinaryOperator that extends BiFunction.
This is more of a "social engineering" answer: we place a contract on the lambda form that it doesn't throw anything:
public interface Factory<T, R, X> {
public R newInstanceFor(T arg) throws X;
public static Factory<R, U, AssertionError> neverThrows(Factory<U, V, ?> input) {
return u -> {
try {
return input.newInstanceFor(u);
}
catch(Throwable t) {
throw new AssertionError("Broken contract: exception thrown", t);
}
};
}
}
Usage is like this, or something along the lines of:
class MyClass {
Factory<MyInput, MyOtherClass, AssertionError> factory;
MyClass(Factory<MyInput, MyOtherClass, ?> factory) {
this.factory = Factory.neverThrows(factory);
}
public void do() {
factory.newInstanceFor(new MyInput()).do();
}
}
Downside of this approach: you can't really specify the contract in the type signature, the contract is then an implementation detail. If you want to have this in type signature, you will need a second sub-interface.
You can define the method as generic like below code, if it is possible for you:
#FunctionalInterface
public interface Factory<R, T> {
public <X extends Throwable> R newInstanceFor(T t) throws X;
}
You can use Project Lombok's #SneakyThrows annotation:
#FunctionalInterface
public interface Factory<R, T> {
#SneakyThrows
R newInstanceFor(T t);
}
This allows you to throw any exception (checked or unchecked). But read the documentation because this feature must be handled with care.
Do you have to make the exception generic? Why not define the interface as
#FunctionalInterface
public interface Factory<R, T> {
public R newInstanceFor(T t) throws Throwable;
}
You can always catch your exception and check the type if you need in your calling function.

How can I implement Function and BiFunction at the same time?

I created a class GenericFunction that implements Function and BiFunction. But it cannot be compiled.
public class GenericFunction<T, U, R> implements
Function<T, R>, BiFunction<T, U, R> {
#Override
public R apply(T t, U u) {
return null;
}
#Override
public R apply(T t) {
return null;
}
}
The error message is:
src\obscure\test\GenericFunction.java:6: error:
types BiFunction<T,U,R> and Function<T,R> are incompatible;
both define andThen(java.util.function.Function<? super R,? extends V>),
but with unrelated return types
public class GenericFunction<T, U, R> implements
^
where T,U,R are type-variables:
T extends Object declared in class GenericFunction
U extends Object declared in class GenericFunction
R extends Object declared in class GenericFunction
1 error
How can I do that?
I have no idea why you would want something like this, but it seemed like an interesting challenge...
The main problem is that both Function & BiFunction implement a default andThen function, both having the exact same signature, so your class doesn't know which to call. You just have to provide your own implementation, then its not ambiguous anymore. However the implementation is tricky.
The java docs say the method:
Returns a composed function that first applies this function to its input, and then applies the after function to the result.
... so that means returning a new GenericFunction, where both apply methods are now compositions.
I give you this monstrosity:
public class GenericFunction<T, U, R> implements Function<T, R>, BiFunction<T, U, R> {
#Override
public R apply(T t, U u) {
return null;
}
#Override
public R apply(T t) {
return null;
}
#Override
public <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
return new GenericFunctionAndThen<>(after);
}
private class GenericFunctionAndThen<V> extends GenericFunction<T, U, V> {
private final Function<? super R, ? extends V> after;
public GenericFunctionAndThen(Function<? super R, ? extends V> after) {
this.after = after;
}
#Override
public V apply(T t) {
return after.apply(GenericFunction.this.apply(t));
}
#Override
public V apply(T t, U u) {
return after.apply(GenericFunction.this.apply(t, u));
}
}
}
This uses the most obscure feature of Java that I know of... I don't even know the name! ClassName.this is used in a nested class to refer to a method (or field) in the enclosing instance, if the method is shadowed.
Extending from #romacafe's answer, one thing that I don't like about it is that GenericFunctionAndThen extends GenericFunction without reusing any of the behaviour of its super class – which looks to me as a bad smell.
Things will be cleaner if you implemented GenericFunction as an interface instead:
public interface GenericFunction<T, U, R> extends Function<T, R>, BiFunction<T, U, R> {
#Override
default <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
return new GenericFunction<T, U, V>() {
#Override
public V apply(final T t, final U u) {
return after.apply(GenericFunction.this.apply(t, u));
}
#Override
public V apply(final T t) {
return after.apply(GenericFunction.this.apply(t));
}
};
}
}
This way you have a simple implementation of the generic behaviour (the andThen method), and you can implement your specific behaviour (the 2 apply methods) in a specific class without relying on inheritance.

Functional Interface Inheritance Quirk

I have a custom interface I've been using for some time that looks something like this:
public interface Function<T, R> {
R call(T input);
}
I'd like to retrofit this interface with both Java's Function as well as Guava's Function, while keeping it a FunctionalInterface. I thought I had the perfect arrangement:
#FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
Both superinterfaces declare the same apply() method, which has been implemented in my interface, leaving only the abstract call() method. Strangely, it won't compile, telling me
Invalid '#FunctionalInterface' annotation; Function<T,R> is not a functional interface
Stranger still, the following variations compile just fine:
#FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
#FunctionalInterface
public interface Function<T, R> extends
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
#FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
#Override
R apply(T input);
}
Is there a reason the first version won't compile?
As stated in the comments, it compiles fine with the oracle compiler.
It is an eclipse bug.
Awaiting for a bug fix, personally i will remove the annotation #FunctionalInterface (your 3rd variation):
public interface Function<T, R>
extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
The major inconvenient of this solution is that the eclipse compiler bug prevent from using the Function as a lambda target type.
If you really want to keep #FunctionalInterface on your Function, a (ugly) workaround might be to introduce an intermediate interface:
public interface AdapterFunction<T, R>
extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
#Override
default R apply(T input) {
return null;
}
}
and let your Function extends this AdapterFunction:
#FunctionalInterface
public interface Function<T, R>
extends
AdapterFunction<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
In this case, the Function is a valid target type for eclipse too:
Function<String, Object> function = st -> st.toString();

How to define a generic parameter which should extend Map or Collection?

I want to defined a generic parameter, which should extend Map or Collection, but I don't know how to do it:
public <T> void test(T t) {}
I can write it as:
public <T extends Map> void test(T t) {}
or
public <T extends Collection> void test(T t) {}
But I don't know is it possible to let T extend Map or Collection in a single method.
Short answer: no.
What do you intend to do with the t parameter within the method? Since Map and Collection have only Object as their common supertype, the only methods you can call on t will be those on Object. (Even methods on both interfaces, such as size(), will be rejected by the compiler.)
With that in mind, is there any reason you can't overload the method in this case? That is, define one implementation for each desired parameter type:
public void test(Map<?,?> t) { ... }
public void test(Collection<?> t) { ... }
If you don't want to do that for whatever reason, then it seems that you could equally just declare the method to take Object and perform a run-time type check of the class. This is semantically equivalent since you'd have to cast to call Map or Collection-specific methods anyway, though it does mean that the type check is done at compile time instead of runtime. Java's type system doesn't let you express this union-type dependency though, so I don't see any other alternative.
No it is not possible, but you can create two separate methods:
public <T extends Map> void test(T t) {
// do the map part
}
public <T extends Collection> void test(T t) {
// do the collection part
}
If you want to mix them in a handling method you can also write it like this:
private void mixedTest(Object t) {
if (t instanceof Map) {
// map part
} else if (t instanceof Collection) {
// collection part
} else {
throw new RuntimeException("Unknown object");
}
}
and call:
public <T extends Map> void test(T t) {
mixedTest(t);
}
public <T extends Collection> void test(T t) {
mixedTest(t);
}
But I'm not sure it will lead to a nice code anyway. I would stick with the first part with the different implementation for the different type of objects.
What about
public <T extends Map> void test(Map t) {}
and
public <T extends Collection> void test(Collection t) {}
...and then let Java choose the correct one to use?

Categories