比较Java中的字符型、整型和类似类型:是否使用等于或==?

j8ag8udp  于 2023-03-11  发布在  Java
关注(0)|答案(9)|浏览(107)

我想确认一下Java中的一些东西:如果我有一个字符型或者整型或者长整型之类的变量,我应该用equals还是==就足够了?
我知道字符串不能保证每个唯一字符串只有一个示例,但我不确定其他装箱类型。
我的直觉是使用equals,但我希望确保不会浪费性能。

hgncfbus

hgncfbus1#

编辑:规范对装箱转换做了一些保证。来自5.1.7节:
如果要装箱的值p为true、false、byte、\u0000到\u007f范围内的char,或者-128到127之间的int或short数字,则令r1和r2为p的任意两个装箱转换的结果。r1 == r2总是这种情况。
请注意,该实现 * 可以 * 使用更大的池。
我真的会避免写依赖于它的代码,不是因为它可能会失败,而是因为它不明显--很少有人会那么了解这个规范(我以前认为它是依赖于实现的)。
您应该使用equals或比较基础值,即

if (foo.equals(bar))

if (foo.intValue() == bar.intValue())

请注意,即使自动装箱保证使用固定值,其他调用方也始终可以创建单独的示例。

pes8fvy9

pes8fvy92#

如果要比较任意两个对象是否相等,请使用.equals()
即使(尤其是)这些对象是原语 Package 器类型ByteCharacterShortIntegerLongFloatDoubleBoolean
对于对象,“==“只比较对象的标识,这是非常,非常少的,你想要的,事实上你从来没有用原始 Package 器得到你想要的。
仅在以下两种情况之一中使用==
1.比较中涉及的所有值都是原语类型(并且优选地不是浮点数)。
1.您确实想知道两个引用是否指向同一个对象(这包括enum s的比较,因为在那里值绑定到对象标识)

yhqotfr8

yhqotfr83#

Java语言规范5.1.7:
如果要装箱的值p为true、false、byte、\u0000到\u007f范围内的char,或者-128到127之间的int或short数字,则令r1和r2为p的任意两个装箱转换的结果。r1 == r2总是这种情况。
以及:
讨论
理想情况下,装箱一个给定的原始值p,将总是产生一个相同的引用。在实践中,使用现有的实现技术,这可能是不可行的。上述规则是一个实用的妥协。上述最后一个子句要求某些公共值总是被装箱到不可区分的对象中。实现可以延迟或急切地缓存这些值。
对于其他值,这个公式不允许程序员对装箱值的身份做任何假设。这将允许(但不要求)共享这些引用中的一些或全部。
这确保了在大多数常见情况下,行为将是所需的,而不会造成不适当的性能损失,特别是在小型设备上。例如,内存限制较少的实现可能会缓存所有字符和短整型,以及-32K -+32K范围内的整型和长整型。
因此,在某些情况下==可以工作,而在其他许多情况下则不行。始终使用.equals是为了安全,因为你不能授权(通常)如何获得示例。
如果速度是一个因素(大多数.equals以==比较开始,或者至少他们应该),并且你可以保证他们是如何分配的,并且他们适合上述范围,那么==是安全的。
有些VM可能会增加该大小,但假定语言规范指定的最小大小比依赖特定VM行为更安全,除非您确实需要。

pod7payv

pod7payv4#

//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或比较它们的原始值。

vom3gejh

vom3gejh5#

equals(Object o)方法的实现几乎总是以

if(this == o) return true;

因此即使==为真,使用equals也不会对性能造成太大影响。
我建议总是 * 在对象上使用equals方法。

*当然,有极少数时候你不应该接受这个建议。

mlmc2os5

mlmc2os56#

一般的答案是no,您不能保证对于相同的数值,您得到的Long对象是相同的(即使您限制自己使用Long.valueOf())。
然而,通过首先尝试测试引用的相等性(使用==),然后,如果失败,尝试equals(),您可能会获得性能改进。这一切都取决于附加的==测试和方法调用的成本比较...您的里程可能会有所不同,但值得尝试一个简单的循环测试,看看哪一个更好。

3pmvbmvn

3pmvbmvn7#

值得注意的是,自动装箱值将使用池化对象(如果它们可用),这就是为什么对于Java 6 u13,(Integer)0 ==(Integer)0,而(Integer)128!=(Integer)128

r8xiu3jd

r8xiu3jd8#

我喜欢直观地看到结果:

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
  }
mhd8tkvw

mhd8tkvw9#

==比较对象引用,而equals(Object obj)比较对象相等性。* 如果存在多个equals对象示例 *,则您必须使用equals进行相等性比较。
示例:

Integer i1 = new Integer(12345);
Integer i2 = new Integer(12345);

它们是不同的对象示例,但根据Integer的等式是相等的,因此必须使用equals(Object obj)

public enum Gender {
    MALE, FEMALE;
}

在这种情况下,将仅存在FEMALE一个示例,因此==是安全的。

相关问题