Java 长比较和双重比较(=)的行为不同

Java 长比较和双重比较(=)的行为不同,java,Java,在执行以下代码段时,它的行为与Double不同 长v1=1L; 长v2=1L; 双d1=1.0; 双d2=1.0; System.out.println(v1==v2);//打印正确 System.out.println(d1==d2);//打印错误 System.out.println(v1.equals(v2));//打印正确 System.out.println(d1.等于(d2));//打印正确 为什么Double==的行为与Long不同 Long v1 = 1L; Long v2 =

在执行以下代码段时,它的行为与Double不同

长v1=1L;
长v2=1L;
双d1=1.0;
双d2=1.0;
System.out.println(v1==v2);//打印正确
System.out.println(d1==d2);//打印错误
System.out.println(v1.equals(v2));//打印正确
System.out.println(d1.等于(d2));//打印正确
为什么Double
==
的行为与Long不同

Long v1 = 1L;
Long v2 = 1L;
Double d1 = 1.0;
Double d2 = 1.0;
这里创建了两个对对象的引用,并使用Java的自动装箱行为实例化了两个对象

Java在v1和v2的池中重新使用了相同的长对象实例,Double不使用池来记忆值,这可以在这篇信息丰富的博客文章中看到

以下是Java 5的一些规则:

自动装箱为布尔值和字节总是从池中返回一个对象
自动装箱为Char、Short、Integer和Long将从 自动装箱值介于-128和127(含)之间时的池
浮动和双精度的自动装箱不使用池,并且始终 返回新对象

然后,您的代码将通过自动装箱(某些池是java用于缓存某些值的池的可视化):

这意味着d1和d2不是相等的实例,因此它们在==
这意味着v1和v2是相等的实例,因此它们在==


v1.equals
返回true,因为这里会查看实际值,而不是快速检查内存地址是否相同。

@Tschallacka我怀疑它是否正确。很可能在很长一段时间内也会发生类似的事情。也就是说,对于较小的值,将使用一个现有的
实例池,而不是一直创建新实例。因为
==
检查对象标识,而不是equality@a_horse_with_no_name嘿,没注意到他调用了对象。是的,那就可以了。与这个问题无关,但是比较浮点值通常并不像人们想象的那么容易。请参见,例如,这将创建两个对象,并从池中检索一个对象,而不是创建四个。顺便说一句,
new Long
不使用池,自动装箱由
Long完成。valueOf
@kaya3实际上,Double不会在池中得到缓冲。我没有说Double使用池。OP的代码创建了两个双对象。它创建零个长对象,因为Long for 1L已经存在,并且是从池中检索的。“您在这里创建了四个具有Java自动装箱行为的对象。”这句话仍然不正确。看起来您是在说,对Long对象的两个引用是两个对象,而它们不是(这正是==为true的原因)。这四条语句要么创建2个新对象(仅两个),要么创建258个(不太可能的情况是,256个池长尚未创建)。
class SomePoolJavaUses {
   static Long _l1 = new Long(1L);
   static Long _l2 = new Long(2L);
   static Long _l3 = new Long(3L);
   ...
}

Long v1 = SomePoolJavaUses._l1;
Long v2 = SomePoolJavaUses._l1;
Double d1 = new Double(1.0);
Double d2 = new Double(1.0);