Prev: Java crash
Next: NullPointerException
From: Roedy Green on 24 Feb 2010 02:50 If Comparable were just an ordinary interface you could say things like this: Comparable a = "abc"; Comparable b = Double.valueOf ( 10.0d ); Comparable c = Double.valueOf ( 12.9d ); int x = b.compareTo( c ); But generics butt in and it seems to be impossible to keep around arrays of Comparables for sorting columns. One way, which I find ugly is to sort Objects instead of Comparables then cast them to specific types before calling compareTo. That should not be necessary. All the JVM should need to know at compile time is that a reference is implements comparable. -- Roedy Green Canadian Mind Products http://mindprod.com Imagine an architect who would never admit to making sketches, blueprints or erecting scaffolds. In his view, the finished building speaks for itself. How could a young architect learn from such a man? Mathematicians traditionally refuse ever to disclose the intuitions that lead them to a conjecture, or the empirical tests to see if it were likely true, or the initial proofs. They are like chefs who refuse to disclose their recipes, ingredients or techniques.
From: Thomas Pornin on 24 Feb 2010 07:49 According to Roedy Green <see_website(a)mindprod.com.invalid>: > If Comparable were just an ordinary interface you could say things > like this: > > Comparable a = "abc"; > Comparable b = Double.valueOf ( 10.0d ); > Comparable c = Double.valueOf ( 12.9d ); > > int x = b.compareTo( c ); Well, you can. Try it; it compiles and runs. The Java compiler grumps a bit because it uses runtime typing. Comparable.compareTo() throws a ClassCastException on type mismatch; generics are meant to let the compiler check such things, rather than issuing a runtime exception at runtime. In your situation, you have to "know" which instances of Comparable can be compared to each other and which cannot. Nevertheless, Java supports dynamic typing and the raw type is not deprecated in any way. Generics are a handy tools, not a mandatory regulation. --Thomas Pornin
From: Lew on 24 Feb 2010 09:19 Thomas Pornin wrote: > According to Roedy Green <see_website(a)mindprod.com.invalid>: >> If Comparable were just an ordinary interface you could say things >> like this: >> >> Comparable a = "abc"; >> Comparable b = Double.valueOf ( 10.0d ); >> Comparable c = Double.valueOf ( 12.9d ); >> >> int x = b.compareTo( c ); > > Well, you can. Try it; it compiles and runs. > > The Java compiler grumps a bit because it uses runtime typing. > Comparable.compareTo() throws a ClassCastException on type mismatch; > generics are meant to let the compiler check such things, rather than > issuing a runtime exception at runtime. In your situation, you have to > "know" which instances of Comparable can be compared to each other and > which cannot. > > Nevertheless, Java supports dynamic typing and the raw type is not > deprecated in any way. Generics are a handy tools, not a mandatory > regulation. You can do it generically, too, if you write a helper class or method that takes the type of the column you want to sort (see the original post), either at compile time or with a Class<T> run-time type token. You get your type safety at a cost of a slight increase in verbosity. You can also declare Comparable <String> a = "abc"; Comparable <Double> b = Double.valueOf ( 10.0d ); Comparable <Double> c = Double.valueOf ( 12.9d ); int x = b.compareTo( c ); Untried: public static <T> int compare( Comparable <T> a, Comparable <T> b ) { return a.compareTo( b ); } I'm not even sure you can call that more verbose since you add a method but subtract the variable declarations in the caller. -- Lew
From: Roedy Green on 24 Feb 2010 13:00 On 24 Feb 2010 12:49:17 GMT, Thomas Pornin <pornin(a)bolet.org> wrote, quoted or indirectly quoted someone who said : >In your situation, you have to >"know" which instances of Comparable can be compared to each other and >which cannot. In the old days, so long as each column contained compatible things, you could just use Comparable.compareTo and all would automagically sort itself out. Today you get squawking if you do it because, for example, String no longer implements Comparable, it implements Comparable<String> which will not cast to Comparable or Comparable<Object> -- Roedy Green Canadian Mind Products http://mindprod.com The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that cannot possibly go wrong goes wrong it usually turns out to be impossible to get at or repair. ~ Douglas Adams (born: 1952-03-11 died: 2001-05-11 at age: 49)
From: markspace on 24 Feb 2010 13:10
Roedy Green wrote: > If Comparable were just an ordinary interface you could say things .... > But generics butt in and it seems to be impossible to keep around > arrays of Comparables for sorting columns. The problem here is that the Comparable interface is designed for the class itself to compare to other objects. If you were the one implementing this method, how many classes would you want to compare it to? Using your example of comparing Strings and Double, let's look at String method: public int compareTo( Object o ) { if( o instanceof String ) ... normal string compare... else if( o instanceof Double ) ... compare String to Double... else if( o instanceof Integer ) ... how many of these do you want? It just goes on and on. Frankly, I think your question lacks any sort of critical thought. It's pretty obvious what would happen if one actually tried to implement your idea. Not good things. And of course, this code would have to be duplicated inside Double, and Integer, and every other class that you wanted to compare to. That the real issue for me. It's just a stinky idea. > > One way, which I find ugly is to sort Objects instead of Comparables Ugly is as ugly does, I suppose. Maybe don't use Object? A little effort wouldn't hurt here. Let's see, off the top of my head. We don't want to compare Objects, so we do want to make our own type. public interface MyColumnType {} It's just a marker interface for now. So we want to compare Strings, but we can't extend String. We'll have to use composition. Fortuneately, there's a string-like interface, CharacterSequence that will help public class MyStringType implements CharacterSequence, MyColumnType private final String value; public MyStringType( String v ) { value = v; } .... } We can't extend Double either, but there is a common Number class we can use: public class MyNumericType extends Number implements MyColumnType private final Number value; public MyNumericType( Number n ) { value = n; } ... } Now we can use a Comparator to implement the actual comparison public class MyColumnComparator implements Comparator<MyColumnType> { public void compare(MyColumnTye o1, MyColumnTye o2 ) { .. implement here.. } } Now at least it looks like someone made some sort of effort. I don't have an algorithm for comparing Strings and Numbers for you, but then I don't know how you want to compare them. It's a critical detail you conveniently left out. I don't think there is a standard way of comparing them, do you? So I'll just leave the rest of it to you then. |