说我有三个数字:
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
接口。
答案 0 :(得分:2)
first answer完全正确的为什么你得到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);
}
<强> / EDIT 强>
Comparable
但不要延长Number
如果你甚至不能确定你的变量扩展了Number,并且你可能正在处理一个带有表示数字的类的变量,那么实现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);
答案 1 :(得分:0)
你无法用这种方式比较它们。 Comparable是一个通用接口,它只接受相同的类型。
您可以使用转换方法:
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;
}
答案 2 :(得分:0)
正如人们所提到的,你无法“按原样”比较它们,但你可以实现一个新的比较器,它将接收不同的可能值,并将知道如何处理它们。下面是一个可能的实现,你有不同的构造函数(每个可能的值 - 可能可以改进那个部分),它将给定的值转换为“基本”类型(在我的情况下是double) - 而compareTo方法可以处理所有支持的类型由不同的构造者。
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;
}
}
}