【问题标题】:What is the difference between being shallowly and deeply equal? How is this applied to caching?浅平等和深平等有什么区别?这如何应用于缓存?
【发布时间】:2011-08-07 21:33:34
【问题描述】:

在我的笔记中找到以下内容,但我无法理解:

原始类型包装类实现有限数量的缓存 价值观。
这保证了有限数量的深度相等的包装对象是 也很浅地相等: 如果o1.equals( o2 ) 那么o1 == o2
例如,new Integer( 0 ) == new Integer( 0 )
一般来说,这并不总是有效。
例如,新整数(666)==新整数(666)
可能不成立。
缓存的原因是它可以节省内存。
一般来说,缓存适用于“小”原始值。

我不明白这是什么意思,或者深 (.equals()) 和浅 (==) 之间的区别是什么。我知道在实践中,.equals 必须用于对象,== 用于 Integral 值,但实际的推理暗示了我。

我假设浅的名称可能只是检查两个值的类型和名称是否相同,而深层检查两个变量是否指向同一个对象?不过,我不明白缓存将如何在这里发挥作用,也不知道它为什么有用。

【问题讨论】:

  • 好吧,你的笔记完全错了。 new Integer( 0 ) == new Integer( 0 )永远、永远、永远为真,new Integer( 666 ) == new Integer( 666 ) 也不会。我建议你问你的教授澄清他的意思,因为如果他期望在考试中这样,他对 Java 知之甚少。

标签: java caching deep-copy shallow-copy


【解决方案1】:

当您执行== 时,您正在比较引用是否相等。这意味着您是在说“两个对象的内存地址是否相同?”

当您执行.equals() 时,您正在比较对象本身是否相等。这意味着您是在说“这两个对象是否认为自己相等?”

给出的例子很糟糕。 JLS 要求对这些数字进行的唯一缓存是 .valueOf() 方法。构造函数没有被缓存。

此外,JLS 仅指定您必须缓存的最小值 [-128:127]。如果他们愿意,JVM 实现可能会缓存更多。这意味着Integer.valueOf(500) == Integer.valueOf(500) 在某些机器上可能是false,但在其他机器上可能是true

class biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

结果:

C:\Documents and Settings\glow\My Documents>java biziclop
false
false
true
false

C:\Documents and Settings\glow\My Documents>

在此处查看更详细的答案(cmets 是一颗宝石!):Why do people still use primitive types in Java?

【讨论】:

  • 嗨,System.out.println(Integer.valueOf(5) == Integer.valueOf(5)); 的输出怎么样? System.out.println(Integer.valueOf(500) == Integer.valueOf(500));不一样??
  • 这就是答案的全部要点:5 足够小,JVM 可以缓存它,而500 则没有。虽然它可能是,所以在一些罕见的机器上它可能是相同的(两者都是正确的)但在大多数机器上 5 将被 cahced 并因此返回相同的 Integer 对象,而 500 不会这样 valueOf 将创建new Integers.
【解决方案2】:

嗯,实际上浅/深解剖不同于==/等解剖:

  1. == 比较对象身份,即您检查是否 操作数实际上是相同的 (对同一内存区域的两次引用), 而equals 比较对象 等价,即“逻辑”值 两个,可能不相同 对象,是一样的。如果两个 对象

    a == b
    

    那是真的

    a.equals(b) // if a != null
    

    ,但并非完全相反 案例。

  2. 浅/深的区别是有意义的 仅用于equals 比较。 浅意味着你只比较 两个对象的直接内容 找出它们是否“相等”在您的 感觉,而深意味着你 比较对象的内容 递归直到你需要 比较是原始字段。如果 你定义你的equals 方法 对象作为调用序列 equals 在这些实例字段上 对象,您使用深度比较。如果 您使用 == 定义 equals 运算符比较复合类型, 比如字符串,那么你使用浅比较——这在 Java 中是不正确的。

所有这一切的精神是,你绝不能使用== 来比较两个复合对象,除非你认为它们只有在它们相同时才相等。

【讨论】:

  • 你说的是真的,但看起来讲师使用“浅”表示参考身份,“深”表示等价。逻辑当然是合理的。
【解决方案3】:

首先:new Integer(0) == new Integer(0)从不 评估为 true,因为 new 总是 创建一个新对象,回避任何可能存在的自动装箱缓存机制.

您可能听说过的是自动装箱(即在必要时将原始值自动转换为其各自的包装类)。自动装箱使用的机制也可以使用包装类valueOf() 方法访问。换句话说:将int 自动装箱到Integer 与调用Integer.valueOf(int) 几乎相同。

Integer.valueOf(0) == Integer.valueOf(0) 评估为true,因为公共值(即具有低绝对值的值)被缓存。当您连续两次调用valueOf(0) 时,您将获得相同 Integer 对象。对于更高的值(例如您的示例中的 666),这不一定是正确的。

【讨论】:

    【解决方案4】:

    equals() 测试两个对象是否本质上相同,但是对于两个不同的对象它可以返回true;即,两个不同的回形针是“相等的”。引用类型的“==”测试两个引用是否引用同一个对象——即,一个回形针是 == 只对它自己。 == 测试身份equals 测试等价性

    您可以有两个不同的 Integer 对象,其中包含 0(它们是 equals());缓存意味着保存对象并在可能的情况下重用它们。

    【讨论】:

      【解决方案5】:

      你所说的“浅相等”是身份:如果两个引用(即对象)是完全相同的实例,则它们是相同的。如果您知道其他语言中的指针是什么,则可以将标识与指针相等进行比较。

      你所说的“深度相等”是相等:如果a.equals(b) 返回true,则两个对象ab 相等(希望反之亦然)。相等的正确性很大程度上取决于equals 方法的实现方式。有关详细信息,请参阅 Object 类的 Javadoc。

      【讨论】:

        猜你喜欢
        • 2015-11-05
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        • 2016-04-24
        • 2013-04-28
        • 2010-09-16
        • 2014-10-10
        相关资源
        最近更新 更多