Forum Stats

  • 3,825,886 Users
  • 2,260,571 Discussions
  • 7,896,720 Comments

Discussions

Simple method but hard with generics: compareTo()

416044
416044 Member Posts: 1,570
edited Nov 23, 2005 4:13PM in Generics
I adjusted my getMaximum() method to generics to avoid the compiler warnings:
    static public Comparable<Comparable> getMaximum(Comparable<Comparable> comparable1, Comparable<Comparable> comparable2) {
        Comparable<Comparable> result = (comparable1 != null) ? comparable1 : comparable2; //init
        
        if (comparable1 != null && comparable2 != null) {
            int c = comparable1.compareTo(comparable2);
            result = (c > 0) ? comparable1 : comparable2; //comparable1 > comparable2?
        }
        
        return result;
    }//getMaximum()
But now, my other classes that call this method e.g. with 2 dates or with 2 numbers don't compile anymore. I tried
    static public Comparable<? extends Comparable> getMaximum(Comparable<? extends Comparable> comparable1, Comparable<? extends Comparable> comparable2) {
        Comparable<? extends Comparable> result = comparable1; //default
        
        if (comparable1 != null && comparable2 != null) {
            int c = comparable1.compareTo(comparable2); //compile error
            if (c <= 0) {
                result = comparable2;
            }
        } else if (comparable1 == null) {
            result = comparable2;
        }
        
        return result;
    }//getMaximum()
but this code doesn't compile:

Bound mismatch: The method compareTo(? extends Comparable) of type
Comparable<? extends Comparable> is not applicable for the arguments
(Comparable<? extends Comparable>). The wildcard parameter ? extends
Comparable has no lower bound, and may actually be more restrictive than argument
Comparable<? extends Comparable>
«1

Comments

  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    public class Test {
    
        static public <T extends Comparable<T>> T getMaximum(T comparable1, T comparable2) {
            T result = (comparable1 != null) ? comparable1 : comparable2;
            
            if (comparable1 != null && comparable2 != null) {
                int c = comparable1.compareTo(comparable2);
                result = (c > 0) ? comparable1 : comparable2;
            }
            
            return result;
        }
    
        static <T extends Comparable<T>> void test(T t1, T t2) {
    	System.out.printf("max(%s, %s) = %s%n", t1, t2, getMaximum(t1,t2));
        }
        public static void main(String... args) {
    	test(1, 2);
    	test(1.0, 2.0);
    	test("aaaa", "bbbb");
        }
    
    }
    You really need to read the generics tutorial:
    http://java.sun.com/j2se/5/pdf/generics-tutorial.pdf
  • 416044
    416044 Member Posts: 1,570
    Thanks, I already browsed this tutorial. I just don't understand why the "?" isn't working.
  • 416044
    416044 Member Posts: 1,570
    I also tried to translate the 1.4 code of TableSorter.java (code from Java Tutorial) but wasn't able to fix the warning of this code:
        public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() {
            public int compare(Object o1, Object o2) {
                return ((Comparable) o1).compareTo(o2); //warning
            }
        };
    Type safety: The method compareTo(Object) belongs to the raw type Comparable. References to generic type Comparable<T> should be parameterized

    I tried to adjust it with similar code as your suggestion, but without success.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    I also tried to translate the 1.4 code of
    TableSorter.java (code from Java Tutorial) but wasn't
    able to fix the warning of this code:
    <div class="jive-quote">public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() {<br />
    public int compare(Object o1, Object o2) {<br />
    return ((Comparable) o1).compareTo(o2); //warning<br />
    }<br />
    };</div>
    There is no way to do that without getting a warning. The
    type system is not expressive enough.
  • 416044
    416044 Member Posts: 1,570
    Now, that's what I call a default behaviour (show warnings) that wasn't thought through to the end. I guess, most developers want to avoid not only errors but also warnings. And you say, that for this code, it's impossible to resolve this warning?
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    I also tried to translate the 1.4 code of
    TableSorter.java (code from Java Tutorial) but wasn't
    able to fix the warning of this code:
    public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() {
    public int compare(Object o1, Object o2) {
    return ((Comparable) o1).compareTo(o2);  //warning
    }
    };
    Type safety: The method compareTo(Object) belongs
    to the raw type Comparable. References to generic
    type Comparable<T> should be parameterized


    I tried to adjust it with similar code as your
    suggestion, but without success.
    How about this:
    class Comparables {
        static <T extends Comparable<T>> Comparator<T> comparatorOfComparables() {
            return new Comparator<T>() {
                public int compare( final T first, final T second ) {
                    return first.compareTo( second );
                }
            };
        }
    }
    ??
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    Now, that's what I call a default behaviour (show
    warnings) that wasn't thought through to the end.
    The warnings are thought through to the end. However,
    we had multiple constraints. An important constraint is
    compatibility as discussed by Neal Gafter on his blog:

    http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html

    Maintaining compatibility means to accept programs that
    can't be expressed in the new type system. To accomplish this,
    we give a warning instead of a error.

    But sometimes it is just impossible to make your pre-generics
    code generic because you can't redesign your entire application
    with generics in mind. So you will be able to suppress unchecked
    warnings on per-method basis. Use the @SuppressWarnings(&quot;unchecked")
    annotation. Currently, the compiler will simply ignore it, but
    that will change in future versions.
  • 416044
    416044 Member Posts: 1,570
    How can we use this @SuppressWarnings(&quot;unchecked")? I didn't found an answer in this forum or in the Annotations doc (http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html).
  • 416044
    416044 Member Posts: 1,570
    I found an article "What is the SuppressWarnings annotation?" (http://www.langer.camelot.de/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20the%20SuppressWarnings%20annotation?) on the internet, so I added
    @SuppressWarnings("unchecked")
    public class TableSorter extends AbstractTableModel { ...
    but I still get the warnings:

    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.

    I also tried this:
    @SuppressWarnings(value={"unchecked","unsafe"})
    public class TableSorter extends AbstractTableModel {...
    with no success. (Note: this TableSorter class is the only class with unchecked warnings, so there are no other classes that can cause these warnings.)
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    Go back and read the last sentence of what Peter said more carefully.
This discussion has been closed.