java中奇怪的平等行为

java中奇怪的平等行为,java,Java,请看下面的代码: Long minima = -9223372036854775808L; Long anotherminima = -9223372036854775808L; System.out.println(minima==anotherminima); //evaluates to false System.out.println(Long.MIN_VALUE); Long another= 1L

请看下面的代码:

Long minima =          -9223372036854775808L;
        Long anotherminima =   -9223372036854775808L;
        System.out.println(minima==anotherminima); //evaluates to false
        System.out.println(Long.MIN_VALUE); 
        Long another= 1L;
        Long one = 1L;
        System.out.println(another == one); //evaluates to true
我无法理解这种行为。。?我希望第一次评估也是真实的。。
这就是我所期望的。

你应该使用
long
而不是
long
。请注意,
Long
是一个类,因此必须使用
equals()
来比较它的实例。另一方面,如果改用
long
,则可以与
=
进行比较,因为它们是原语。

问题:

(minima==anotherminima)
您正在比较对象的内存位置而不是其值,因此它返回false

如果要比较两个长包装类,需要调用
compareTo


现在,如果您使用-128和127初始化长包装器类,它将导致具有相同引用的装箱转换。

这里只是一个猜测,但可能是1L在常量池中,因此引用等式的计算结果为true(就像有时,即使通过字符串,==也会计算为true),而另一个巨大的数字却不是。不确定如何在启动时检查池中有哪些常量

编辑:Java有特定常量对象的缓存(包括原语的包装类和字符串)。因此,如果你写

String st1 = "A";
如果“A”在常量池中,Java不会创建新的字符串对象——它只会创建对已经存在的字符串对象的引用。那么如果你真的这么做了

String st2 = "A";
System.out.println(st1 == st2);
它会打印出真实的


现在,不是所有的整数、长、短等等。。。是缓存的(有太多),但较低的值是。所以我假设1L是。这意味着在你的问题中,
另一个
一个
引用同一个对象,因此即使引用相等,它也会返回true。

首先,你应该使用
long
而不是
long
。其次==整数之间,Long等将检查引用是否相等。你可以查一下电话号码。Alo
1L
常量池中,因此第二种情况返回true

在旁注中,您应该使用
.equals
来比较长时间

从Oracle文档:

如果要装箱的值p为true、false、字节或 范围从\u0000到\u007f,或介于-128和127之间的整数或短数 (包括),然后让r1和r2为任意两个装箱的结果 p。r1==r2总是这样

理想情况下,装箱一个给定的原语值p,总是会产生一个 相同的参考。在实践中,使用 现有的实现技术。上述规则是务实的 妥协。上述最后一条要求某些通用值 始终将其装入无法区分的对象中。[……]

这确保在大多数常见情况下,行为将是 想要的,不施加不适当的绩效处罚,尤其是 在小型设备上。例如,内存有限的实现可能会更少 例如,缓存所有char和short值,以及int和long值 介于-32K到+32K范围内的值


再加上,从-128到127的所有内容都缓存到永久java内存中的一个实例中,这意味着这些数字(几乎)总是具有引用相等性,因为不会为它们创建新实例。在缓存之外,每次使用该数字时都会创建一个新实例,因此它们在引用上并不相等。JVM使用了一种缓存技术,用于某些范围的自动装箱值。按照规范()

如果要装箱的值p为true、false、一个字节或\u0000到\u007f范围内的字符,或一个介于-128和127(包括-128和127)之间的整数或短数字,则让r1和r2为p的任意两个装箱转换的结果。r1==r2总是这样

理想情况下,装箱一个给定的原语值p,总是会产生一个相同的引用。在实践中,使用现有的实现技术可能不可行。上述规则是一种务实的妥协。上面的最后一条要求将某些公共值始终装箱到不可区分的对象中。实现可以延迟或急切地缓存这些数据。对于其他值,此公式不允许程序员对装箱值的标识进行任何假设。这将允许(但不要求)共享部分或所有这些引用

这确保了在大多数常见情况下,行为将是所需的,而不会造成不适当的性能损失,尤其是在小型设备上。例如,内存限制较少的实现可能会缓存所有char和short值,以及-32K到+32K范围内的int和long值

因此1L在这个缓存的值中,然后自动装箱给出了完全相同的引用,但是如果数字超出这个范围(比如Long.MIN_值),它不会被缓存,因此给出了不同的实例/引用


无论如何,在比较对象时,您应该始终使用.equals()

使用
long
而不是
long
。好吧,所以我决定与众不同,并告诉人们我为什么否决了他们。让我们看看这是怎么回事。为什么-见鬼-这个问题得到了6票?这个问题中的两个主题(平等与身份,包装类)在过去都被问了很多次,所以这个问题永远不应该被问到。但是为什么它在第二种情况下有效呢?常量池包含1,但不是其他的大数字?@Sherz这是一个可能的解释。-1因为你不知道为什么第二个案例是真的。目标不是在这两种情况下都实现。我们的目标是理解两者之间的区别。@BoratSagdiyev OP没有告诉我们他知道原语和对象之间的区别。或者如果只是比较等式,那么他就知道了
equals()
。-1因为你不知道为什么第二种情况是真的。好吧,我们只讨论int和short,而不是long。罗
String st2 = "A";
System.out.println(st1 == st2);