1

Can someone explain the difference between <T extends Number & Comparable<T>> and T extends Comparable<? extends Number>?

These look similar to me and both of them compiles fine for sub classes type. The invalid type args shows below error

Type parameter is not within bound parameter;should implement 'java.lang.Number'

and

Type parameter is not within bound parameter; should extend 'java.lang.Comparable>'

respectively.

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
s7vr
  • 73,656
  • 11
  • 106
  • 127

2 Answers2

2

You won't be able to use:

Comparable<? extends Number>

because the only methods defined by Comparable are consumers (in the sense of PECS): it needs to accept instances of type ? extends Number into its compareTo method - and there is no type which satisfies that bound safely.

Integer is a Comparable<? extends Number>, but so is Double. Thus, you can't safely call instance1.compareTo(instance2) because it would fail if these instances are concretely Integer and Double respectively, since Integer.compareTo can only accept Integer parameters.

As such, the compiler prevents you from calling this method in the first place.

Community
  • 1
  • 1
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
2

Option 1:

public class A <T extends Number & Comparable<T>>{}

Your Generic Parameter should extend Number and implements Comparable, which means class A is a Number and Comparable.

Option 2:

public class B <T extends Comparable<? extends Number>>{}

T is Comparable on Numbers(can compare Number only) but doesn't have to be a Number, unlike option 1

I will explain by example:

A

public class A <T extends Number & Comparable<T>>{}

B

public class B <T extends Comparable<? extends Number>>{}

IntegerWrapper(Option 2)

    public class IntegerWrapper implements Comparable<Integer>  {

      Integer number;

      public IntegerWrapper(int number) {
        this.number = number;
      }

      @Override
      public int compareTo(Integer o) {
        return number.compareTo(o);
      }
    }

GenericsTest public class GenericsTest {

  public static void main(String args[]){
    A myA = new A<Integer>();

    B myB = new B<IntegerWrapper>();
  }
}

I think option 1 is what you are looking for, because i can't think of many useful scenarios for Option 2(Maybe there is...)

Elia Rohana
  • 326
  • 3
  • 16
  • "T is Comparable on Numbers(can compare Number only) but doesn't have to be a Number" Can you elaborate a little more ? – s7vr May 26 '16 at 18:07
  • 1
    T is Comparable for Number types, but does not have to extend Number class like option 1 -> T extends Number, its only Comparable. and was defined as T extends Number. from my example IntegerWrapper does not extend Number class, but implements Comparable – Elia Rohana May 26 '16 at 22:18