Search code examples
javagenericscomparatorcomparable

Java,generic class class with comparator or comparable


I need to create a parametric class where I have two constructors, the first has a comparator as an argument, the second hasn't any argument but I can use it only if the parameter implements comparable or throws an exception otherwise.

To be more clear I need to do something like this:

class Storage<T>{
   private Comparator<? super T> comparator = null;
   public Storage() {
       //T sould implement comparable, but how I can check it?
   }
   public Storage(Comparator<? super T> t){
       //T doesn't implement comparable but i can use comparator!
       comparator = t
   }
   public static void main(String[] args) {
       //Just a test
       Comparator<prova> comp = (a, b) -> 1;
       MinMaxStorage<Integer> uno = new MinMaxStorage<>();
       //Should thow an exception
       MinMaxStorage<NotComparable> due = new MinMaxStorage<>();
       //Should be ok       
       MinMaxStorage<NotComparable> due = new MinMaxStorage<>(comp);
   }
}

Solution

  • You can't constrain direct invocations of this no-arg constructor: it can be called for any T within the bounds. Given that there is no bound, this means it can be invoked for incomparable T.

    Instead, make the no-arg constructor private, and make a generic static factory method:

    private Storage() {}
    
    // ...
    
    public <T extends Comparable<? super T>> Storage<T> create() {
      return new Storage<>();
    }
    
    

    Then, this:

    MinMaxStorage<NotComparable> due = MinMaxStorage.create();
    

    won't throw an exception, but even better: it will not compile.