繁体   English   中英

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

[英]Why does this return false and true?

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);
    }
}

编辑

三元运算符在引擎盖下进行某些类型的转换 在你的情况下,你是混合原语和包装类型,在这种情况下包装类型被取消装箱,然后三元运算符的结果被“重新装箱”:

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


所以你的代码基本上等同于(除了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上缓存长值,因此==比较可以返回true。 如果您使用equals进行了所有比较,那么在这两种情况下都会得到true

注意,如果你使用public static final Long DEFAULT_LONG = 128L; 并尝试:

Long l = 128L;
System.out.println(l == DEFAULT_LONG);

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

注意: JLS要求缓存-127和+128之间的charbyteint值,但不要说long任何内容。 因此,您的代码实际上可能会在不同的JVM上打印两次false。

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

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

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

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

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

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

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

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

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


有两个“修复”...假设你想解决这个问题:

  • 与更换三元运算符if / elsereturn的两个分支。
  • 转换第二个操作数以强制它装箱:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM