4
 1  class test {
 2      public static int compare0(Comparable x, Comparable y) {
 3          return x.compareTo(y);
 4      }

 5      public static int compare1(Object x, Object y) {
 6          return ((Comparable) x).compareTo((Comparable) y);
 7      }

 8      public static int compare2(Object x, Object y) {
 9          Comparable p = (Comparable) x;
10          Comparable q = (Comparable) y;
11          return (p).compareTo(q);
12      }

13      public static void main(String[] args) {
14          Comparable zero = new Integer(0);
15          Comparable one = new Integer(1);
16          int c = (zero).compareTo(one);
17      }
18  }

Compiling the code above produces 4 warnings:

% javac -Xlint:unchecked test.java
test.java:3: warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable
    return x.compareTo(y);
                      ^
test.java:7: warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable
    return ((Comparable) x).compareTo((Comparable) y);
                                     ^
test.java:13: warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable
    return (p).compareTo(q);
                        ^
test.java:19: warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable
    int c = (zero).compareTo(one);
                            ^
4 warnings

I tried many more variants, but the warnings remain. What's the correct way to write and call the test.compare method above?

Thanks!

PS: test.compare is only an example; I don't need such a function; but I need to implement a function that, like test.compare, needs to have Comparable-implementing objects in its signature.

PS2: I've been programming for 25+ years, I even programmed Java for a while around 10 years ago, but using Java now (required by my job) is driving me berserk. For an experienced programmer, learning Java is much harder than it looks. There's so mu\ ch stuff on learning Java out there, 99% of which is at best outdated, or pitched to rank programming novices (i.e. massively verbose), and at worst is outright garbage... I have yet to find a reference on Java that will let me quickly zero in the answer to the question above.

kjo
  • 33,683
  • 52
  • 148
  • 265
  • 1
    *"I have yet to find a reference on Java that will let me quickly zero in the answer to the question above."* That's probably because it's a very broad subject that you don't seem to have started to research yet. Here's one reference: [The Java Tutorials > Learning the Java Language > Generics - Introduction](http://download.oracle.com/javase/tutorial/java/generics/generics.html) – Mark Peters Aug 03 '11 at 20:47
  • 2
    @Mark Peters: As it turns out, I had read the reference you linked to, even before I'd written the code above, and I found it deficient, for pretty much the reasons I described: verbose, aimed at programming (not just Java) novices, entirely based on trivial examples that don't begin to cover the types of situations a professional programmer has to deal with daily, etc. It certainly does not tell me how to solve the problem described in this post. I'm sure there's a constituency for this sort of material, but it does not help me. – kjo Aug 04 '11 at 22:20

4 Answers4

6

Comparable is generic - you should define the variables with Comparable<Integer>

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
6

You should declare the compare method with a generic argument.

public class ThisTest
{
    public static <T extends Comparable<T>> int compare(T x, T y) {
        if (x == null) 
            return -(y.compareTo(x));
        return x.compareTo(y);
    }

    public static void main()
    {
        // Type inferred
        int c = compare(Integer.valueOf(0), Integer.valueOf(1));
        // Explicit generic type parameter
        c = ThisTest.<Integer>compare(Integer.valueOf(0), Integer.valueOf(1));
    }
}
Jean Hominal
  • 16,518
  • 5
  • 56
  • 90
  • 1
    Yes, there is a syntax error but you're on the right track. If you want to use explicit type paramaters for the `compare` method you would need to invoke it like `ClassName.compare(...)`. However, the explicit parameter has no use here as the type parameter will be inferred properly based on the arguments. – Mark Peters Aug 03 '11 at 20:55
  • @Mark: Thank you. I have only been doing C# recently, I am a bit rusty in Java. – Jean Hominal Aug 03 '11 at 21:02
  • That's a nice way to handle `null`. – erickson Aug 03 '11 at 21:12
  • @erickson but it doesn't handle `x==null && y==null` – ratchet freak Aug 03 '11 at 21:31
  • 1
    @ratchet freak: I think that throwing a `NullPointerException` is a defensible way to "handle" that case. Many `compareTo()` implementations won't accept `null` as a parameter, raising a similar exception. And even if they do accept `null`, it is still reasonable to treat the comparison of `null` and `null` as undefined. – erickson Aug 03 '11 at 21:41
  • 3
    for best results you should use `>` – newacct Aug 04 '11 at 10:17
  • @Jean: thanks, your example compiles; I can't say it entirely makes sense to me (in particular, the recursive dependence of `T` on `Comparable`, in the expression `>`), but it's a start. – kjo Aug 04 '11 at 22:31
  • @kjo: well, generics are a bit difficult to understand - you also should be using newacct's `>` instead of `>`, because that will work in a few more cases than the declaration I made. – Jean Hominal Aug 05 '11 at 04:56
2

The real problem is that you are trying to do your comparisons within a static method. Make the method that does the comparison non-static, instantiate one or more "tester" objects and commit to a type for each. For example:

 test<String> strTester = new test<String>();

then to invoke the comparison method for String objects:

 int retCode = strTester.comp(a, b)

If you want to compare other types of objects such as Integers you will need a new tester object like:

 test<Integer> intTester = new test<Integer>();

If you are willing to do this, then your class can be defined along the lines of:

 class test<T extends Comparable<T>> {
      public int comp(T x, T y) {
           ...
      }
 }
1

Declare zero and one as Integer or Comparable<Integer> rather than raw types.

Angelika Langer has produced a great reference for generics. It's organized as a hierarchical FAQ and should allow you to find specific answers to most generic type problems quickly. In this case, you may find the section on raw types useful.

erickson
  • 265,237
  • 58
  • 395
  • 493