Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an alternate way to specify an additional bound when first bound is a type parameter?

Tags:

java

typing

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

}
like image 992
Panda TG Attwood Avatar asked Dec 29 '15 10:12

Panda TG Attwood


People also ask

Can a parameterized type have several bounds?

A type parameter can have multiple bounds.

Which of these is the correct way to declare a bounded type?

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 .

How do you restrict the types used as type arguments in generic classes and methods?

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 upper bounded wildcards and bounded type parameters?

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.


1 Answers

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.

like image 50
Javier Martín Avatar answered Sep 24 '22 23:09

Javier Martín