假设我有三个数字:
Comparable n1 = new Integer(432);
Comparable n2 = new Long(40);
Comparable n3 = new Double(500.12);
我想通过
Comparable
界面比较这些数字。然而,这会导致 ClassCastException
。
n1.compareTo(n2);
有没有办法(实用函数、外部库……)来比较不同类型的数字?在上面的示例中,从语义上看,数字
n2
小于 n1
,并且 n1
小于 n3
。
在代码中,我不知道数字的具体类型。因此,我依赖
Comparable
界面。
第一个答案完全正确地说明了为什么会出现 ClassCastException - Comparable 接口是通用的,只能用于相同具体类型的对象。
可能还有其他方法可以解决您的问题:原语及其对象包装器
int, long, float, double
) 或表示基元的类的对象 (
Integer, Long, Float, Double
),那么您可以只使用普通的比较运算符,例如相当于
n1.compareTo(n2);
int b = n1 > n2 ? 1 : (n1 < n2 ? -1 : 0);
Number
的子类
Number
的类,即
AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short
,您可以使用以下内容:
private int compareNumbers(Number n1, Number n2)
{
Double n2c = n2.doubleValue();
Double n1c = n1.doubleValue();
return n1c.compareTo(n2c);
}
public static void main (String[] args)
{
Integer n1 = new Integer(432);
Long n2 = new Long(40);
Double n3 = new Double(500.12);
System.out.println(compareNumbers(n1,n2));
}
编辑
为了回应与OP的评论讨论 - 我们注意到,如果比较两个超出Double
范围的
Number
或
BigDecimal
数字,使用
BigInteger
作为
Double
比较的基类可能会给出虚假的相等性(因此
.doubleValue()
根据需要返回
Double.POSITIVE_INFINITY
或
Double.NEGATIVE_INFINITY
)如果这是一个问题,
compareNumbers()
可以更改如下:
private int compareNumbers(Number n1, Number n2)
{
BigDecimal n2c = new BigDecimal(n2.toString());
BigDecimal n1c = new BigDecimal(n1.toString());
return n1c.compareTo(n2c);
}
/编辑
实施Comparable
但不扩展
Number
Comparable n1 = new WierdNonNumberExtendingInteger(432);
Comparable n2 = new WierdNonNumberExtendingLong(40);
Comparable n3 = new WierdNonNumberExtendingDouble(500.12);
Integer b = null;
if (n1.getClass().isInstance(n2))
{
b = n1.compareTo(n2);
}
else
{
System.err.println("Can't compare apples and oranges");
System.err.print("You tried to compare " + n1.getClass().getSimpleName());
System.err.print(" with " + n2.getClass().getSimpleName());
}
System.out.println(b);
可以使用转换方法:
Comparable<Double> n1 = convertNumber(new Integer(432));
Comparable<Double> n2 = convertNumber(new Long(40));
Comparable<Double> n3 = convertNumber(new Double(500.12));
System.out.println(n1.compareTo(n2));
...
public Double convertNumber(Object o) {
if(o instanceof Double) {
return (Double)o;
} else if(o instanceof Long) {
return ((Long)o).doubleValue();
} else if(o instanceof Integer) {
return ((Integer)o).doubleValue();
}
return null;
}
public class MyTestClass
{
public static void main (String[] args) throws java.lang.Exception
{
MyComparator n1 = new MyComparator(new Integer(432));
MyComparator n2 = new MyComparator(new Long(40));
MyComparator n3 = new MyComparator(new Double(500.12));
}
static class MyComparator implements Comparable
{
double baseVal = 0.0d;
public double getValue() {
return baseVal;
}
public MyComparator(double d) {
this.baseVal = d;
}
public MyComparator(Long l) {
this.baseVal = l.doubleValue();
}
public MyComparator(int i) {
this.baseVal = (double)i;
}
public int compareTo(MyComparator toCompare) {
return ((Double)this.getValue()).compareTo(toCompare.getValue());
}
public int compareTo(Object o) {
// implemented only to support required interface methods
return 0;
}
}
}
public class MyTestClass
{
public static void main (String[] args) throws java.lang.Exception
{
MyComparator n1 = new MyComparator(new Integer(432));
MyComparator n2 = new MyComparator(new Long(40));
MyComparator n3 = new MyComparator(new Double(500.12));
}
static class MyComparator implements Comparable
{
double baseVal = 0.0d;
public double getValue() {
return baseVal;
}
public MyComparator(double d) {
this.baseVal = d;
}
public MyComparator(Long l) {
this.baseVal = l.doubleValue();
}
public MyComparator(int i) {
this.baseVal = (double)i;
}
public int compareTo(MyComparator toCompare) {
return ((Double)this.getValue()).compareTo(toCompare.getValue());
}
public int compareTo(Object o) {
// implemented only to support required interface methods
return 0;
}
}
}