比较 Java 中的字符、整数和类似类型:使用 equals 还是 ==?

发布于 2024-07-16 15:23:22 字数 172 浏览 7 评论 0原文

我想确定一下 Java 中的一些事情: 如果我有一个字符、一个整数或一个长整型以及诸如此类的东西,我应该使用 equals 还是 == 就足够了?

我知道对于字符串,不能保证每个唯一字符串只有一个实例,但我不确定其他装箱类型。

我的直觉是使用 equals,但我想确保我没有浪费性能。

I wanted to make sure about something in Java:
If I have a Character or an Integer or a Long and those sort of things, should I use equals or is == sufficient?

I know that with strings there are no guarantees that there is only one instance of each unique string, but I'm not sure about other boxed types.

My intuition is to use equals, but I want to make sure I'm not wasting performance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

妄断弥空 2024-07-23 15:23:22

编辑:该规范对装箱转换做出了一些保证。 来自第 5.1.7 节

如果装箱的值 p 为 true,
false,一个字节,一个范围内的字符
\u0000 到 \u007f,或者 int 或短整型
-128 到 127 之间的数字,然后令
r1 和 r2 是任意两个的结果
p的拳击转换。 总是
r1 == r2 的情况。

请注意,该实现可以使用更大的池。

不过,我真的会避免编写依赖于它的代码。 不是因为它可能会失败,而是因为它并不明显——很少有人会那么了解该规范。 (我之前认为它与实现相关。)

您应该使用 equals 或比较基础值,即

if (foo.equals(bar))

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

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

EDIT: The spec makes some guarantees for boxing conversions. From section 5.1.7:

If the value p being boxed is true,
false, a byte, a char in the range
\u0000 to \u007f, or an int or short
number between -128 and 127, then let
r1 and r2 be the results of any two
boxing conversions of p. It is always
the case that r1 == r2.

The implementation can use a larger pool, mind you.

I would really avoid writing code which relies on that though. Not because it might fail, but because it's not obvious - few people will know the spec that well. (I previously thought it was implementation-dependent.)

You should use equals or compare the underlying values, i.e.

if (foo.equals(bar))

or

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

Note that even if the autoboxing were guaranteed to use fixed values, other callers can always create separate instances anyway.

∞梦里开花 2024-07-23 15:23:22

如果要比较任意两个对象的相等性,请使用 .equals()

即使(尤其是)这些对象是原始包装类型 ByteCharacterShortInteger、<代码>长整型、浮点双精度布尔

对于对象,“==”仅比较对象标识,而这很少是您想要的。 事实上,使用原始包装器你永远无法得到你想要的东西。

仅在这两种情况之一中使用 ==

  1. 比较中涉及的所有值都是原始类型(最好不是浮点数),
  2. 您确实想知道两个引用是否引用同一个对象(这包括enum的比较,因为那里的值绑定到对象标识)

If you want to compare any two objects for equality use .equals().

Even (and especially) if those objects are the primitive wrapper types Byte, Character, Short, Integer, Long, Float, Double and Boolean.

For objects "==" only ever compares the object identity and that's very, very rarely what you want. And you de-facto never what you want with the primitive wrappers.

Only use == in one of those two scenarios:

  1. all values involved in the comparison are primitive types (and preferably not floating point numbers)
  2. you really want to know if two references refer to the same object (this includes comparison of enums, because there the value is bound to the object identity)
毅然前行 2024-07-23 15:23:22

Java 语言规范 5.1.7

如果装箱的值 p 为 true,
false,一个字节,一个范围内的字符
\u0000 到 \u007f,或者 int 或短整型
-128 到 127 之间的数字,然后让
r1 和 r2 是任意两个的结果
p的拳击转换。 总是
r1 == r2 的情况。

和:

讨论

理想情况下,对给定的原语进行装箱
值 p,总是会产生
相同的参考。 在实践中,这
使用现有的可能不可行
实施技术。 规则
以上是务实的妥协。 这
上述最后条款要求
某些共同的值总是被装箱
变成无法区分的物体。 这
实现可能会懒惰地缓存这些
或者热切地。

对于其他值,此公式
不允许任何关于
盒装值的标识
程序员的部分。 这将允许
(但不要求)共享一些或
所有这些参考资料。

这确保了在最常见的情况下
情况下,行为将是
想要的,而不强加不适当的
性能损失,尤其是
小型设备。 内存限制较少
例如,实现可能是
缓存所有字符和短裤,如
以及整数和长整型
范围为-32K - +32K。

因此,在某些情况下 == 会起作用,但在许多其他情况下则不会。 为了安全起见,请始终使用 .equals,因为您无法(通常)授予实例的获取方式。

如果速度是一个因素(大多数 .equals 以 == 比较开始,或者至少它们应该)并且您可以保证它们是如何分配的并且它们符合上述范围,那么 == 是安全的。

某些虚拟机可能会增加该大小,但假设语言规范指定的最小大小比依赖特定虚拟机行为更安全,除非您确实确实需要这样做。

Java Language Spec 5.1.7:

If the value p being boxed is true,
false, a byte, a char in the range
\u0000 to \u007f, or an int or short
number between -128 and 127, then let
r1 and r2 be the results of any two
boxing conversions of p. It is always
the case that r1 == r2.

and:

Discussion

Ideally, boxing a given primitive
value p, would always yield an
identical reference. In practice, this
may not be feasible using existing
implementation techniques. The rules
above are a pragmatic compromise. The
final clause above requires that
certain common values always be boxed
into indistinguishable objects. The
implementation may cache these, lazily
or eagerly.

For other values, this formulation
disallows any assumptions about the
identity of the boxed values on the
programmer's part. This would allow
(but not require) sharing of some or
all of these references.

This ensures that in most common
cases, the behavior will be the
desired one, without imposing an undue
performance penalty, especially on
small devices. Less memory-limited
implementations might, for example,
cache all characters and shorts, as
well as integers and longs in the
range of -32K - +32K.

So, in some cases == will work, in many others it will not. Always use .equals to be safe since you cannot grantee (generally) how the instances were obtained.

If speed is a factor (most .equals start with an == comparison, or at least they should) AND you can gurantee how they were allocated AND they fit in the above ranges then == is safe.

Some VMs may increase that size, but it is safer to assume the smallest size as specified by the langauge spec than to rely on a particular VM behaviour, unless you really really really need to.

无边思念无边月 2024-07-23 15:23:22
//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 或比较它们的原始值。

//Quick test
public class Test {
  public static void main(String[] args) {
    System.out.println("Are they equal? "+ (new Long(5) == new Long(5)));
  }
}

Output:

"Are they equal? 0"

Answer:

No, they're not equal. You must use .equals or compare their primitive values.

聆听风音 2024-07-23 15:23:22

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

if(this == o) return true;

这样的方式开始,因此即使 == 为 true,使用 equals 也不会对性能造成太大影响。

我建议始终*对对象使用 equals 方法。

* 当然,在极少数情况下您不应该接受此建议。

Implementations of the equals(Object o) method almost always start with

if(this == o) return true;

so using equals even if == is true is really not much of a performance hit.

I recommend always* using the equals method on objects.

* of course there are a very few times when you should not take this advice.

一笑百媚生 2024-07-23 15:23:22

一般的答案是,您不能保证对于相同的数值,您获得的 Long 对象是相同的(即使您限制自己使用 Long.valueOf() )。

但是,通过首先尝试测试引用的相等性(使用 ==),然后如果失败,尝试 equals(),您可能会获得性能改进。 这一切都取决于额外的 == 测试和方法调用的比较成本...您的里程可能会有所不同,但值得尝试一个简单的循环测试来看看哪个更好。

The general answer is no, you are not guaranteed that for the same numeric value, the Long objects you get are the same (even if you restrict yourself to using Long.valueOf()).

However, it is possible that you would get a performance improvement by first trying to test the equality of references (using ==) and then, if failed, trying equals(). It all hinges on the comparative costs of the additional == test and the method call... Your mileage may vary, but it is worth trying a simple loop test to see which is better.

听风吹 2024-07-23 15:23:22

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

It is worth noting that auto-boxed values will uses pooled object if they are available. This is why (Integer) 0 == (Integer) 0 but (Integer) 128 != (Integer) 128 for Java 6u13

甜扑 2024-07-23 15:23:22

我喜欢直观地看到结果:

  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
  }

I like to see the result visually:

  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
  }
热鲨 2024-07-23 15:23:22

== 比较对象引用,而 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 实例存在,因此 == 可以安全使用。

== compares the object reference while equals(Object obj) compares for object equality. If there can ever be more than one instance of an equals object in existence then you must use equals for equality comparison.

Examples:

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

these are different object instances but are equal according to Integer's equality, so you must use equals(Object obj)

public enum Gender {
    MALE, FEMALE;
}

in this case there will only be one instance of FEMALE in existence so == is safe to use.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文