0

In Java it is legal to create a comparator object like this:

Comparator<? super Number> comparator = new Comparator<Object>() {
    @Override
    public int compare(Object o1, Object o2) {
        // implementation here
    }
};

But you can't use this object for a simple call like this:

Object o1 = new Object(), o2 = new Object();
comparator.compare(o1, o2);

Why so? I thought ? super Number means Number and all its superclasses.

saidfagan
  • 841
  • 2
  • 9
  • 26

3 Answers3

2

Suppose instead you had used ? super Double:

Comparator<? super Double> comparator = new Comparator<Object>() {
    // ...
};

What you are telling the compiler is that you have a Comparator which

  • might be a Comparator<Double>, or
  • might be a Comparator<Number>, or
  • might be a Comparator<Object>, or
  • might be a Comparator<Serializable>.

Even though you initialized it with a Comparator<Object>, the compiler doesn’t know that, because the compiler doesn’t execute code. The compiler only knows that the variable holds a Comparator of one of the above types.

Since the variable might hold a comparator of a type more specific than Object, the compiler will not assume that it’s okay to pass Object.

VGR
  • 40,506
  • 4
  • 48
  • 63
1

Comparator<? super Number> comparator means that comparator refers to something known to be able to accept a Number (or it's null).

A Comparator<Object> can accept a Number; but the compiler doesn't know if the value referred to by a Comparator<? super Number> is a Comparator<Object>, or a Comparator<Number> any more. All it knows is that it's something that can accept a Number, so that's all it will allow you to pass.

Why so? I thought ? super Number means Number and all its superclasses.

No: it means that Number is an acceptable type to pass as a parameter. To put that another way, Number is a subtype of the acceptable parameter type. To put that another way, the acceptable parameter type is a supertype of Number, so it's fine to pass a Number.

See: What is PECS (Producer Extends Consumer Super)?

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • I still don't get it. If the acceptable parameter type is a supertype of Number and it is fine to pass a Number, why it is not fine to pass an Object, which is a supertype of Number? – saidfagan Jan 13 '20 at 16:55
  • 1
    @saidfagan because it could be a `Comparator` instead: that's also a `Comparator super Number>`. If you pass an `Object` to that, it will fail. – Andy Turner Jan 13 '20 at 17:06
  • Now, I got it, thank you. How about `Comparator extends Number>`? By this logic, does that mean you can't send anything as parameter to `compare` method? – saidfagan Jan 14 '20 at 06:42
1

The reason why o1 and o2 cannot be used as parameters is because they are "more general" than Number and hence they may point to an instance of a class that is part of a different hierarchy starting at some point in parent chain of Number. Something like, Son class is directly in the hierarchical line of Father, but not in the hierarchy of Grandfather class's SecondSon. So, a reference to an instance of Grandfather class cannot be passed since it could be pointing to an instance in its SecondSon's hierarchy.

I have tried to explain a similar point here.

Sree Kumar
  • 2,012
  • 12
  • 9