Draft proposal: allow the use of relational operators on Comparable classes

Vilya Harvey vilya.harvey at gmail.com
Tue Mar 10 09:09:18 PDT 2009


I've attached a draft of a proposal to allow classes which implement the
Comparable interface to be used as operands for the relational operators. So
for example if you had two Strings, a and b, you would be able to write

if (a < b) {
    ...
}

instead of

if (a.compareTo(b) < 0) {
    ...
}

and you could do the same with your own classes as well.

Thanks in advance for any feedback,

Vil.
-------------- next part --------------
Proposal to allow the use of relational operators with Comparable classes.


AUTHOR
    Vilya Harvey <vilya.harvey at gmail.com>


OVERVIEW:
    Feature Summary
    ---------------
    Using the results of the compareTo method can be confusing: it's easy to
    get the values the wrong way around. I propose allowing classes that
    implement the Comparable interface to be used with Java's relational
    operators, to help avoid this confusion.


    Major Advantage
    ---------------
    Clearer code. 


    Major Disadvantage
    ------------------
    Could create some confusion with the equality operators as == and != would
    still be checking for reference equality rather than using the results of
    the compareTo method.

    Would need to decide how to handle cases where Comparable objects could be
    unboxed to numeric values (i.e. instances of java.lang.Integer, etc.). In
    that situation, should you treat them as Comparable objects or should you
    unbox them and perform a numeric comparison?


    Alternatives
    ------------
    It is currently possible to use the result of compareTo() directly and
    that's a well known idiom, although still prone to the occasional mistake.

    It is also possible to write utility methods isLessThan(),
    isGreaterThan(), etc. which use the results of compareTo in the same way
    as suggested above.

    The isLessThan() et al. could be added to the Comparable interface,
    although this would break a lot of existing code.


EXAMPLES

    Simple Example
    --------------
    The simplest case is where an existing class already implements the
    Comparable interface:

        String a = ... ;
        String b = ... ;
        System.out.println("Is a < b?  " + (a < b));

    At present, the above would have to be written as:

        String a = ... ;
        String b = ... ;
        System.out.println("Is a < b?  " + (a.compareTo(b) < 0));

    which is a bit less clear.


    Advanced Example
    ----------------
    The trickier details would be around handling of nulls and unboxing of
    numeric objects.

        String a = null;
        String b = "hello";
        if (a > b) { ... }  // Throws a NullPointerException?
        if (b < a) { ... }  // Only throws a NullPointerException if
                            // b.compareTo(a) throws a NullPointerException?

        Integer c = 10;
        Double d = 10.1;
        if (c < d) { ... }  // Compile error or numeric comparison?

    The above could be written in today's Java, with the consequences:

        String a = null;
        String b = "hello";
        if (a.compareTo(b) > 0) { ... } // Throws NullPointerException.
        if (b.compareTo(a) < 0) { ... } // Throws NullPointerException.

        Integer c = 10;
        Double d = 10.1;
        if (c.compareTo(d) < 0) { ... } // Compile error.


DETAILS

    Specification
    -------------
    This proposal would require changing the semantics of the relational
    operators, to allow for the case of objects which implement the Comparable
    interface as the operands. In this case, it is proposed that the operators
    be treated as syntactic sugar for an invocation of the compareTo method of
    the left operand with the right operand as an argument, with the result
    compared to zero.


    The expression 

        a OP b

    where OP is any one of the four relational operators (<, >, <=, >=)
    defined in section 15.20 of the Java Language Specification and both a &
    b are objects implementing the Comparable interface; should be
    de-sugared to

        a.compareTo(b) OP 0

    where OP is the same relational operator as in the sugared form.

    In the case where both a and b are Comparable objects which can be unboxed
    into primitive numeric types, it is proposed that the unboxing should be
    given precedence. That is, the unboxing should be performed and the
    operator be evaluated as per it's current semantics. This will maintain
    the semantics of existing code.

    No grammar modifications are necessary for this change. Likewise no new
    bytecodes are needed. It can be implemented purely as a modification to
    the compiler.


    Compilation
    -----------
    As above.


    Testing
    -------


    Library Support
    ---------------
    This feature requires that classes implement the existing
    java.lang.Comparable interface in order to be used with the relational
    operators. No other library support is required.


    Reflective APIs
    ---------------
    No changes necessary.


    Other Changes
    -------------
    None requried.


    Migration
    ---------
    Where existing code calls compareTo() and compares the result to 0, simply
    replace that with the appropriate relational operator.


COMPATIBILITY

    Breaking Changes
    ----------------
    No existing programs would be broken by this change, providing unboxing
    occurs before the comparison is performed.


    Existing Programs
    -----------------
    Existing programs should be completely unaffected by this change.


REFERENCES

    Existing Bugs
    -------------


    URL for Prototype
    -----------------
    


More information about the coin-dev mailing list