【问题标题】:Does == comparison use byte in ArrayList comparisons? [duplicate]== 比较是否在 ArrayList 比较中使用字节? [复制]
【发布时间】:2014-07-18 12:32:38
【问题描述】:

在我正在处理的一个程序中,我遇到了一个数据存储问题,特别是与 ArrayLists 相关。这不是我正在测试的实际代码,但它提供了一个示例来说明我的意思。

public class test
{
  public static void test()
  {
    ArrayList<Integer> bob = new ArrayList<Integer>();
    bob.add(129);
    bob.add(129);
    System.out.println(bob.get(0) == 129 );
    System.out.println(bob.get(1) == 129 );
    System.out.println(bob.get(0)  == bob.get(1) );
  }
}

如果你运行它,你会得到真、真、假。该代码识别出两者都等于 129,但由于某种原因,当它尝试查看它们是否彼此相等时返回 false。但是,如果将值更改为 127,它会返回 true、true 和 true。多次测试不同的值,你会看到接收 true、true 和 true 的最小值是 -128,最大值是 127。这是 byte 的间隔,这让我怀疑 == 操作使用在这种情况下是字节。

有趣的是,如果你修改代码,让它读起来

public class test
{
  public static void test()
  {
    ArrayList<Integer> bob = new ArrayList<Integer>();
    bob.add(129);
    bob.add(129);
    int a = bob.get(0);
    int b = bob.get(1);

    System.out.println(a == 129 );
    System.out.println(b == 129 );
    System.out.println(a == b );
  }
}

它按预期工作。输出真、真、真。为什么在比较之前将值保存为 int 会改变结果?是不是因为如果不保存,比较会默认使用byte进行==比较?

【问题讨论】:

  • Integer 是一个类,您正在将一个 Integer 对象添加到 ArrayList 中。此外,当您 .get() 时,它应该返回 Integer 对象的两个实例。比较结果应该是比较对象实例。当您使用原生类型 int 来保存值并使用比较运算符时,它会比较值。

标签: java arraylist integer byte equals


【解决方案1】:

这是因为第三个测试比较了两个对象,因为 get() 调用的(整数对象)返回没有取消装箱。结果为真的值使用缓存的单例,因此使用相同的对象,但在该范围之外,新的和不同的对象通过自动装箱放入列表中。

请注意,此行为可能因 JVM 和 JVM 以及版本而异;在某些 JVM 上,它甚至可以是基于启发式的动态 - 例如,系统可以想象查看可用内存并缓存 16 位值而不是 8 位。

【讨论】:

    【解决方案2】:

    集合有 2 个 get 方法接受 int 和 Integer 和 Integer 集合,自动装箱正在做一些内部魔法来使用错误的方法(有效的 Java)

    根据需要使用显式装箱或取消装箱。

    【讨论】:

      【解决方案3】:

      这是因为前两个比较是在 int 值上进行的,因为 bob.get() 在比较之前被强制转换为 int。第三,比较对象是对象,这就是你在-128 to 127之外的值得到错误的原因,因为在这个范围内值被缓存了。

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        答案在于 Java 使用的原始包装类的缓存机制。
        在整数的情况下,缓存 -128 到 127 之间的值(即一个字节的值范围)。

        这意味着,如果您将 -128 到 127 之间的任何值装箱,您就会从缓存中获得一个现成的实例。这就是为什么 == 运算符适用于那些,因为它比较引用而不是值。
        另一方面,如果您使用任何其他值,则每次装箱都会获得一个全新的实例,这意味着 == 运算符将失败。

        这是来自 Integer 类的一段代码,负责此操作:

        private static class IntegerCache {
            private IntegerCache(){}
        
            static final Integer cache[] = new Integer[-(-128) + 127 + 1];
        
            static {
                for(int i = 0; i < cache.length; i++)
                    cache[i] = new Integer(i - 128);
            }
        }
        

        【讨论】:

        • 我是 java 初学者(刚刚完成 AP 计算机科学 A),这个答案对我来说最有意义。我读过的所有其他答案都很棒,对于比我更高级的程序员来说可能很容易理解。但是,由于我是初学者,并且对自动装箱或缓存不太了解,所以这个答案对我来说是最清楚的。感谢大家的回应;我非常感谢您的所有帮助。
        【解决方案5】:

        自动装箱和拆箱在起作用,这行得通 -

        bob.add(129);       // Autoboxed to Integer
        int a = bob.get(0); // primitive int a
        int b = bob.get(1); // primitive int b
        
        System.out.println(a == 129 ); // primitive to primitive
        System.out.println(b == 129 ); // primitive to primitive
        System.out.println(a == b ); // primitive to primitive
        

        你也可以使用Integer.intValue()

        Integer a = bob.get(0);
        Integer b = bob.get(1);
        // Here you could omit one, but not both, calls to intValue()
        System.out.println(a.intValue() == b.intValue()); // primitive to primitive
        

        【讨论】:

          【解决方案6】:

          是的,我刚刚意识到我可以解释这一点。不知道我之前在想什么。

          JLS,第 5.1.7 节:

          如果被装箱的值 p 是 int 类型的整数文字,介于 -128 和 127 之间(第 3.10.1 节),或者布尔文字 true 或 false(第 3.10.3 节),或者是 '\ 之间的字符文字u0000' 和 '\u007f' (第 3.10.4 节),然后让 a 和 b 是 p 的任何两个装箱转换的结果。 a == b 总是如此。

          由于129 超出此范围,您最终会在索引 1 和 2 中得到两个不同的 Integer 对象,除非您自己使用 JVM 标志配置范围。

          对于代码第一位中的最后一个比较:由于ArrayList#get() 返回一个类型为ArrayList 参数化的对象,最后一个比较是比较两个Integer 对象,并且因为这两个对象是不同的,结果将是false。前两次比较导致 Integer 对象被拆箱,因为您将 Integer 包装器与 int 文字进行比较,因此结果与您预期的一样。

          第二段代码按预期工作,因为您正在比较 int 文字,并且这些比较更直观。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-06-02
            • 1970-01-01
            • 2016-01-05
            • 2015-01-30
            • 1970-01-01
            • 1970-01-01
            • 2011-04-01
            • 1970-01-01
            相关资源
            最近更新 更多