I know that specifying an additional bound when the first bound is a type parameter is not possible in Java; however, I was wondering if anybody knows an alternate way to do something similar and to keep it safe at compile time? I've provided an example below.
In the following code what I'm referring to is this: <E extends T & Comparable<T>>
. In this situation, I want to be able to use the inbuilt comparator if the type of T
is comparable, otherwise, I want to specify my own comparator.
Is there any alternate way to do this while keeping type-safety at compile time?
public class ExampleClass<T, U> {
[...]
public <E extends T & Comparable<T>> ExampleClass(Function<U, E> function) {
this.function = function;
this.comparator = (E a, E b) -> a.compareTo(b);
}
public ExampleClass(Function<U, T> function, Comparator<U> comparator) {
this.function = function;
this.comparator = comparator;
}
}
A type parameter can have multiple bounds.
To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number .
Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.
What is the difference between a wildcard bound and a type parameter bound? A wildcard can have only one bound, while a type parameter can have several bounds. A wildcard can have a lower or an upper bound, while there is no such thing as a lower bound for a type parameter.
You can solve your problem by implementing the first constructor as a static method that delegates to your second constructor, like this:
import java.util.Comparator;
import java.util.function.Function;
public class Test<T,U> {
private final Function<U,T> function;
private final Comparator<T> comparator;
public Test(Function<U,T> function, Comparator<T> comparator) {
this.function = function;
this.comparator = comparator;
}
public static <E extends Comparable<E>, V> Test<E,V> withNatOrder(Function<V,E> function) {
// Any of these two will do
final Comparator<E> comp = (E a, E b) -> a.compareTo(b);
final Comparator<E> comp2 = Comparator.naturalOrder();
return new Test<>(function, comp);
}
}
The static function does not have access to the class type parameters T and U, so it defines new, independent ones. The return type is now Test<E,V>
where E does implement Comparable and V is unbounded like your U parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With