我知道对于字符串来说,没有保证每个唯一字符串都只有一个实例,但我不确定其他包装类型是否也是这样。
我的直觉是使用equals方法,但我想确保不会浪费性能。
编辑:规范保证了一些装箱转换的情况。第5.1.7节:
如果正在装箱的值 p 为 true、false、位于 \u0000 到 \u007f 范围内的 byte、char 类型或在 -128 到 127 之间的 int 或 short 数字,则令 r1 和 r2 分别为 p 的任意两个装箱转换的结果。恒有 r1 == r2。
当然,实现可以使用更大的池。
我真的建议避免编写依赖此功能的代码。不是因为它可能会失败,而是因为它不明显 - 很少有人会那么熟悉规范。(我先前认为这取决于实现.)
应该使用 equals
或比较基础值,即:
if (foo.equals(bar))
或者if (foo.intValue() == bar.intValue())
请注意,即使自动装箱保证使用固定的值,其他调用者仍然可以创建单独的实例。.equals()
。Byte
, Character
, Short
, Integer
, Long
, Float
, Double
和Boolean
,也要这样做(尤其是)。 ==
:
enum
,因为该值绑定到对象标识)如果要装箱的值 p 是 true、false、一个字节、Unicode 编码在 \u0000 到 \u007f 范围内的字符,或者一个介于 -128 和 127 之间的整数或短整型数,则让 r1 和 r2 分别是 p 进行两次装箱转换的结果。那么 r1 == r2 总是成立。
并且:
讨论
理想情况下,对给定的基本类型值 p 进行装箱总是产生相同的引用。但实际上,使用现有的实现技术可能无法做到这一点。上述规则是一种实际妥协方案。上面的最后一条子句要求将某些常见的值始终装箱为不可区分的对象。实现可以懒惰地或即时地缓存它们。
对于其他值,此公式禁止程序员在包装值的标识上做出任何假设。这允许(但不强制)共享某些或所有这些引用。
这确保在大多数常见情况下,行为将是所需的行为,而不会对小型设备产生过度的性能损失。内存限制较少的实现可能会缓存所有字符和短整型数,以及范围在 -32K 到 +32K 范围内的整数和长整型数。
因此,在某些情况下,"==" 运算符可以正常工作,但在许多其他情况下,它无法正常工作。始终使用 .equals 是安全的,因为您通常无法保证实例是如何创建的。
如果速度很重要(大多数 .equals 方法都以 "==" 运算符比较,或者至少应该这样做),而且您可以保证它们是如何分配的并且它们符合以上范围,则 "==" 是安全的。
一些虚拟机可能会增加这个范围的大小,但除非您确实需要这样做,否则最好假设语言规范指定的最小大小比依赖于特定的虚拟机行为更为安全。
//Quick test
public class Test {
public static void main(String[] args) {
System.out.println("Are they equal? "+ (new Long(5) == new Long(5)));
}
}
输出:
"它们相等吗?0"
答案:
不,它们不相等。您必须使用.equals方法或比较它们的基本值。
在实现equals(Object o)方法时,几乎总是以以下方式开始:
if(this == o) return true;
因此,即使使用 ==
返回 true,使用 equals
也不会对性能造成太大的影响。
我建议始终对对象使用 equals
方法。
* 当然,在极少数情况下,您不应遵循此建议。
一般来说,不保证对于相同的数值,您得到的Long对象是相同的(即使您限制自己使用Long.valueOf())。
然而,通过首先尝试测试引用的相等性(使用==),然后如果失败,则尝试equals(),可能会获得性能提升。这完全取决于额外的==测试和方法调用的比较成本...您的结果可能会有所不同,但值得尝试一个简单的循环测试以查看哪个更好。
public static void main(String[] args)
{
Integer a = 126; //no boxed up conversion, new object ref
Integer b = 126; //no boxed up conversion, re-use memory address
System.out.println("Are they equal? " + (a == b)); // true
Integer a1 = 140; //boxed up conversion, new object
Integer b1 = 140; //boxed up conversion, new object
System.out.println("Are they equal? " + (a1 == b1)); // false
System.out.println("Are they equal? " + (new Long(5) == new Long(5))); // false
}
==
比较对象引用,而 equals(Object obj)
比较对象相等性。如果有可能存在多个相等的对象实例,那么你必须使用 equals
进行相等性比较。
示例:
Integer i1 = new Integer(12345);
Integer i2 = new Integer(12345);
这些是不同的对象实例,但根据 Integer 的相等性它们是相等的,因此您必须使用 equals(Object obj)
public enum Gender {
MALE, FEMALE;
}
FEMALE
实例,因此使用==
是安全的。