浅层平等和深度平等有什么区别?这如何应用于缓存?
在我的笔记中发现以下内容,但我无法理解它:
原始类型包装类实现有限数量的缓存 价值观。
这保证了有限数量的深度相等的包装对象 也浅等于: 如果o1.equals( o2 )
则o1 == o2
。
例如,new Integer( 0 ) == new Integer( 0 )
。
一般来说,这并不总是有效。
例如,new Integer( 666 ) == new Integer( 666 )
可能不成立。
缓存的原因是它节省内存。
一般来说,缓存适用于“小”原始值。
我不明白这是什么意思,也不明白深层 (.equals()) 和浅层 (==) 等于之间的区别。我知道在实践中, .equals 必须用于对象, == 必须用于积分值,但实际的推理暗示了我。
我假设浅层的名称可能只是检查两个值是否具有相同的类型和名称,而深层检查两个变量是否指向同一个对象?我不明白缓存如何在这里发挥作用,或者为什么它会有用。
Found the following in my notes, but I am unable to make sense of it:
Primitive type wrapper classes implement caching for a limited number
of values.
This guarantees that a limited number of deeply equal wrapper objects are
also shallowly equal:
Ifo1.equals( o2 )
theno1 == o2
.
For example,new Integer( 0 ) == new Integer( 0 )
.
In general this does not always work.
For example, new Integer( 666 ) == new Integer( 666 )
may not hold.
The reason for caching is that it saves memory.
In general caching works for “small” primitive values.
I don't understand what is meant by this, or what the difference is between a deep (.equals()) and shallow(==) equals. I know in practice, .equals must be used to objects and == for Integral values, but the actual reasoning for this alludes me.
I assume by the names that shallow maybe just checks that both the values are of the same type and name, which deep checks that both variables point to the same object? I don't see how the caching would come into play here though, or why it would be useful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当您执行
==
时,您正在比较引用是否相等。这意味着您说“两个对象在内存中的地址是否相同?”当您执行
.equals()
时,您正在比较对象本身是否相等。这意味着您是在说“这两个对象认为它们自己相等吗?”给出的例子很糟糕。 JLS 强制执行的对这些数字的唯一缓存是
.valueOf()
方法。 构造函数不会被缓存。此外,JLS 仅指定您必须缓存的最小值[-128:127]。 JVM 实现可以缓存更多(如果他们愿意的话)。这意味着
Integer.valueOf(500) == Integer.valueOf(500)
在某些机器上可能为false
,但在其他机器上可能为true
。结果:在
这里查看更详细的答案(评论是宝石!):为什么人们仍然在 Java 中使用原始类型?
When you do
==
you are comparing the references for equality. This means you're saying "is the address in memory the same for both Objects?"When you do
.equals()
you are comparing the Objects themselves for equality. This means you're saying "do these two Objects consider themselves equal?"The example that was given was poor. The only caching done for these numbers that's mandated by the JLS is the
.valueOf()
method. The constructor is not cached.Furthermore, the JLS only specifies the minimum you must cache [-128:127]. JVM implementations may cache more if they so choose. This means
Integer.valueOf(500) == Integer.valueOf(500)
may befalse
on some machines, buttrue
on others.Results in:
See a more detailed answer here (the comments are a gem!): Why do people still use primitive types in Java?
好吧,实际上浅/深剖析与 ==/等剖析不同:
== 比较对象标识,即检查是否
操作数实际上是相同的
(对同一内存区域的两次引用),
而
equals
比较对象等价性,即“逻辑”值
两个,可能不相同
对象,是一样的。如果两个人
对象
<前><代码>a == b
那么这是真的
,但事实并非如此
仅用于
等于
比较。浅薄意味着你只比较
两个对象的直接内容
找出它们在你的中是否“相等”
感觉,而深度意味着你
比较对象的内容
递归地直到你需要的为止
比较是原始字段。如果
您定义您的
equals
方法对象作为调用序列
这些实例字段上的
equals
对象,您使用深度比较。如果
您可以使用
==
定义equals
比较复合类型的运算符,
例如字符串,那么您可以使用浅比较——这在 Java 中是不正确的。
所有这一切的原则是,您绝不能使用
==
来比较两个复合对象,除非您仅在它们相同时才认为它们相等。Well, actually shallow/deep dissection is different from ==/equal dissection:
== compares for object identity, that is you checking whether
operands are the same in fact
(two references to the same area of memory),
whereas
equals
compares for objectequivalence, that is "logical" value
of two, possibly not identical
objects, is the same. If for two
objects
then it's true that
, but opposite isn't true in all
cases.
only for
equals
comparison.Shallow means that you compare only
immediate contents of two objects to
find whether they "equal" in your
sense, whereas deep means that you
compare contents of your objects
recursively until all you need to
compare is primitive fields. If
you define
equals
method of yourobjects as sequence of calls to
equals
on instance fields of theseobjects, you use deep comparison. If
you define
equals
using==
operator to compare compound types,
such as Strings, then you use shallow comparison -- and that's incorrect in Java.
Morale of all of this is that you must never use
==
to compare two compound objects, unless you consider them equal only if they are the same.您所说的“浅相等”是身份:如果两个引用(即对象)是完全相同的实例,则它们是相同的。如果您知道其他语言中的指针是什么,则可以将同一性与指针相等性进行比较。
您所谓的“深度相等”是相等:如果
a.equals(b)
,则两个对象a
和b
相等code> 返回true
(希望反之亦然)。相等的正确性很大程度上取决于 equals 方法的实现方式。有关更多详细信息,请参阅Object
类的 Javadoc。What you call "shallow equal" is identity: two references (i.e. objects) are identical if they are the very same instances. If you know what pointers are in other languages, you can compare identity to pointer equality.
What you call "deep equal" is equality: two objects
a
andb
are equal ifa.equals(b)
returnstrue
(and hopefully vice versa). The correctness of equality strongly depends on the way theequals
method is implemented. See the Javadoc of theObject
class for more details.首先:
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),情况不一定如此。First off:
new Integer(0) == new Integer(0)
will never evaluate totrue
, asnew
always creates a new object, sidestepping any autoboxing-caching mechanism that might exist.What you probably heard about was autoboxing (i.e. automatic conversion of primitive values to their respective wrapper classes when necessary). Autoboxing uses a mechanism that's also accessible using the wrapper classes
valueOf()
methods. In other words: auto-boxing anint
to anInteger
works pretty much the same as callingInteger.valueOf(int)
.Integer.valueOf(0) == Integer.valueOf(0)
will evaluate totrue
, because common values (i.e. values with a low absolute value) are cached. You'll get the sameInteger
object when you callvalueOf(0)
twice in a row. This is not necessarily true with higher values (such as 666 in your example).equals() 测试两个对象是否本质上相同,但对于两个不同的对象可以返回 true;即,两个不同的回形针是“相等的”。引用类型的“==”测试两个引用是否引用同一个对象——即回形针仅==其自身。 == 测试同一性,其中
等于
测试等价。您可以有两个不同的 Integer 对象,其中包含 0(它们是
equals()
);缓存意味着保存对象并在可能的情况下重用它们。equals() tests whether two objects are essentially the same, but it can return true for two distinct objects; i.e., two different paper clips are "equals". "==" for reference types tests whether two references refer to the same object -- i.e., a paper clip is == only to itself. == tests identity, which
equals
tests equivalence.You could have two distinct Integer objects with a 0 in them (they are
equals()
); caching means saving objects and reusing them when possible.