1
 public class Test3{


public static void main(String[] args)
{
    String s="1";
    String s1="2";
    System.out.println(Compare.compare(s, s1));


}
}

class Compare {
public static Comparable compare ( Comparable o1, Comparable o2 ) {
if (o1.compareTo(o2) > 0)
return o1;
else
return o2;
}
}

The above code output 2, which is correct if String.compareTo(String str) is used. However the type of o1 is actually raw type Comparable not Comparable<String> and even if it is Comparable<String>, Comparable o2 cannot be passed as parameter.

So, what o1.compareTo(o2) actually call? and How it actually work

Eran
  • 387,369
  • 54
  • 702
  • 768
dnjsdnwja
  • 389
  • 1
  • 7
  • 17
  • 2
    Can you explain, what you mean by "However the type of o1 is actually Comparable not Comparable and even if it is Comparable, Comparable o2 cannot be passed as parameter."? Comparable is an generic interface. If none is given, Java will handle them as Object and use its compareTo() implementation. – Arman Apr 11 '18 at 07:08
  • What I meant is raw type Comparable not Comparable < String > and even if it is Comparable< String >. Sorry, I didn't know we cannot simply write <> symbol in stackoverflow. – dnjsdnwja Apr 11 '18 at 07:16
  • @Arman in this case not, `String#compareTo` will be used – Eugene Apr 11 '18 at 07:41

1 Answers1

1

This is a really unclear question to begin with. Your first example uses raw types, so Comparable#compareTo expects a certain type that T (but because you are using raw types, this is an Object) that it should compare against, well a raw Comparable (o2 in your case) fits that case (it is an Object after all).

When you change your class to be:

static class Compare {
    public Comparable<String> compare(Comparable<String> left, Comparable<String> right) {
        if (left.compareTo(right) > 0) {
            return left;
        } else {
            return right;
        }
    }
}

This does not work because compareTo expects a type T (String actually), but you are passing Comparable<String>. This is actually really easy to understand once you look at the Comparable interface in the jdk sources...

A correct implementation using generics IMO would be:

static class Compare<T extends Comparable<? super T>> {
    public T compare(T left, T right) {
        if (left.compareTo(right) > 0) {
            return left;
        } else {
            return right;
        }
    }
}
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Do you mean that the raw type would work something like Comparable? – dnjsdnwja Apr 11 '18 at 08:04
  • the thing I don't really get is that String class only has compareTo(String) method and Comparable would have abstract method of compareTo(Object); there won't be any dynamic binding between them. Then, how can compareTo(Object) be called while there is no implementation for it? – dnjsdnwja Apr 11 '18 at 08:11
  • 1
    @최원우 they are not the same, after erasure you will have something like `interface Comparable { int compare(Object o) }`, it's not going to be `Comparable....` – Eugene Apr 11 '18 at 08:39
  • 1
    @최원우 the thing, you want to know about is called [*bridge method*](https://stackoverflow.com/q/5007357/2711488). – Holger Apr 11 '18 at 09:24