I fixed this by turning the comparator logic around. A primitive comparison is only executed if both operands are known to be in the domain of the comparison. That said, there should be an architecture that also ensures sane equality for different user-defined number types. Right now it works for bigint/bigint, bigint/int, int/bigint, say, but it does not necessarily work for bigint/decimal.
Code is attached.
public class Comparator {
private static int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7;
private static int typeCode(Object a) {
if (a instanceof Integer) return INT;
if (a instanceof Character) return CHAR;
if (a instanceof Long) return LONG;
if (a instanceof Double) return DOUBLE;
if (a instanceof Float) return FLOAT;
if (a instanceof Byte) return BYTE;
if (a instanceof Short) return SHORT;
return OTHER;
}
/** A rich implementation of the equals method that overrides the default
* equals because Java's boxed primitives are utterly broken. This equals
* is inserted instead of a normal equals by the Scala compiler (in the
* ICode phase, method genEqEqPrimitive ) only when either
* side of the comparison is a subclass of AnyVal , of
* java.lang.Number , of java.lang.Character or
* is exactly Any or AnyRef .
*/
public static boolean equals(Object a, Object b) {
if (a == null)
return b == null;
else if (a.equals(b))
return true;
else {
int acode = typeCode(a);
int bcode = typeCode(b);
int maxcode = (acode < bcode) ? bcode : acode;
if (maxcode <= INT) {
int aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).intValue();
int bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).intValue();
return aa == bb;
} else if (maxcode <= LONG) {
long aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).longValue();
long bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).longValue();
return aa == bb;
} else if (maxcode <= FLOAT) {
float aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).floatValue();
float bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).floatValue();
return aa == bb;
} else if (maxcode <= DOUBLE) {
double aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).doubleValue();
double bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).doubleValue();
return aa == bb;
} else {
return a == b;
}
}
}
}
|