为什么这会返回错误和真实?

时间:2013-02-06 02:17:26

标签: java

public class Test {
    public static final Double DEFAULT_DOUBLE = 12.0;
    public static final Long DEFAULT_LONG = 1L;

    public static Double convertToDouble(Object o) {
        return (o instanceof Number) ? ((Number) o).doubleValue()
                : DEFAULT_DOUBLE;
    }

    public static Long convertToLong(Object o) {
        return (o instanceof Number) ? ((Number) o).longValue() : DEFAULT_LONG;
    }

    public static void main(String[] args){
        System.out.println(convertToDouble(null) == DEFAULT_DOUBLE);
        System.out.println(convertToLong(null) == DEFAULT_LONG);
    }
}

2 个答案:

答案 0 :(得分:8)

修改

三元运算符some type conversions under the hood。在你的情况下,你是混合原语和包装类型,在这种情况下包装类型被取消装箱,然后三元运算符的结果被“重新装箱”:

  

如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,则条件表达式的类型为T. / p>


所以你的代码基本上等同于(longValue doubleValue应该是public static void main(String[] args){ Double d = 12.0; System.out.println(d == DEFAULT_DOUBLE); Long l = 1L; System.out.println(l == DEFAULT_LONG); } 的错字除外):

==

可以在某些JVM上缓存长值,因此equals比较可以返回true。如果您与true进行了所有比较,那么在这两种情况下都会得到public static final Long DEFAULT_LONG = 128L;

请注意,如果您使用Long l = 128L; System.out.println(l == DEFAULT_LONG); 并尝试:

char

它可能会打印为false,因为Long值通常仅在-128和+127之间缓存。

注意:JLS要求缓存介于-127和+128之间的byteintlong值但不说{{1}} 。因此,您的代码实际上可能会在不同的JVM上打印两次错误。

答案 1 :(得分:4)

要理解这种奇怪的行为,你需要选择它的作用:

(o instanceof Number) ? ((Number) o).longValue() : DEFAULT_LONG

我们这里有一个方法调用,它返回一个long和一个Long的实例。两个不同的类型。但是条件运算符?需要生成单个类型; longLong。并且为了做到这一点,要么必须装箱第二个操作数,要么必须取消装箱第三个操作数。

在这种情况下,JLS表示必须取消装箱第三个操作数。 JLS 15.25

  

“如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是应用装箱转换(第5.1.7节)到T的结果,那么条件表达式的类型是T。“

这意味着您的常量将被取消装箱,然后重新装箱。

现在通过调用盒装类型的valueof()方法来装箱基本类型。这些方法根据基本类型略有不同。

  • 对于浮点类型,valueof始终会创建新对象
  • 对于整数类型,valueof方法有时会创建一个新对象,有时会返回一个现有对象。

后者就是这里发生的事情。 Long.valueof(1L)始终返回相同的值,与==的比较结果为true


有两个“修复”...假设您要解决此问题:

  • 将三元运算符替换为if / else并在两个分支中都有return
  • 投射第二个操作数以强制它装箱:

    return (o instanceof Number) ? 
            (Long) ((Number) o).longValue() : DEFAULT_LONG;