提问一个java的问题:是有关equals()和==的,问题如下

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了提问一个java的问题:是有关equals()和==的,问题如下相关的知识,希望对你有一定的参考价值。

public static void main(String[] args)
Integer a=new Integer(1);
Integer b=new Integer(1);
int c=1;
Long d=new Long(1);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
System.out.println(a.equals(d));
System.out.println("-----------------------");
System.out.println(a==b);
System.out.println(a==c);
System.out.println(b==c);


运行结果是
true
true
true
false
-----------------------
false
true
true

这就怪了,a==c为true,b==c为true,a==b怎么就为false了呢?还有为什么a.equals(d)为false呢?

java中“==”比较的是物理地址,equals比较的是值
int c=1其实是c的指针指向了值为1的物理地址。
java中new关键字就是开辟一个新的地址用来存储。
Integer a=new Integer(1)就是开辟一个地址来存储1,所以A和B的物理地址不同a==b就是false
至于a.equals(d)为什么为false,我可已给你看下equals的api
equals public boolean equals(Object obj)
Compares this object to the specified object. The result is true if and only if the argument is not null and is a Long object that contains the same long value as this object.
也就是说long型的只能和long型的做equals比较
参考技术A 1 a==b 比较的是引用值,new的不同对象,引用值当然不同。
2 数值类型的变量,不建议用equals比较,不过想Interger,Long等类型可以比较。
a跟d比较为false是对的,想true的话,你需要重写Integer类的hashcode方法和equals方法,但是Integer是java自带的类型,所以,以后a和d的比较,直接用=比较就行啦。来自:求助得到的回答
参考技术A Integer b=new Integer(1)是对象 两个对象不相同 ==是值相等 参考技术B == 是比较的地址 equals 是比较值 参考技术C 如果 你了解多态!我建议你看看 equals()是Object对象 而a属于Integer类 看看Integer类是否重写了equals()方法吗? 看看Number重写的equals()方法吗? 没有!会执行Object中的equals()方法,你会发现 其实比较的是hashcode值,那么a的hashcode 会等于 1吗? 参考技术D 一个是值,一个是引用; 第5个回答  2012-10-11 晕,你这里犯好几个错。
你类型都不相同了,还equals什么啊。int即转换为Integer,这个不用说了吧。因此abc相同。你再去object这个类里看看,它有个equals方法。Integer和Long作为对象,必定继承自object,因此各自实现了equals方法。此时,除非你重写Long或Integer中的equals方法,否则这两者必定不同。
然后,你去网上搜下Long和int的区别,大把。

覆盖 Java 中的 hashCode() 和 equals() 方法

【中文标题】覆盖 Java 中的 hashCode() 和 equals() 方法【英文标题】:Overwriting the hashCode() and equals() method in Java 【发布时间】:2020-06-09 12:30:51 【问题描述】:

正如标题所示,我的问题与重写 hashCode() 和 equals() 方法有关。但是,这也不完全正确,我只是不知道用另一种方式来总结我的问题。

我有一个对象Label,它包含多个组件,其中一个是List,它包含多个Node 类型的对象。 Label 的一个示例是:[(n1, n2, n3), (n4, n5)]。我想存储在LinkedHashSet 中生成的所有唯一Label 对象。但是,这并没有按预期工作。假设LinkedHashSet 当前包含上述Label,并且我们现在生成了一个名为other 的新Label,结果证明它包含与已添加标签相同的节点,因此也包含[(n1, n2, n3), (n4, n5)]。由于它具有相同的节点列表,Label 中的其他组件也相同。我不会在这里解释为什么,只是假设它是,因为事实就是如此。但是,当检查LinkedHashSet 是否已经包含Label 时,它会返回false,因为对象具有不同的对象ID。

一种方法是在 LinkedHashSet 上编写一个 for 循环,并将新标签与 LinkedHashSet 中的所有标签进行比较,但这在运行时间方面会非常昂贵,所以我正在寻找一个更便宜的选择。欢迎提出任何建议!

另一种方法是调整 equals() 方法,但这行不通,因为我还必须调整 hashCode() 方法,但我不知道如何更改它才能使其正常工作。

【问题讨论】:

hashCodeequals 是否已在 Label 上被覆盖?除非这些被覆盖,否则将使用hashCode 的默认实现,它对应于对象标识。 看看这篇文章:mkyong.com/java/java-how-to-overrides-equals-and-hashcode 不清楚您的问题与标准“如何在 Java 中覆盖 equals 和 hashCode?”有什么区别 缓存Label对象的哈希码会提供很好的效率。 @kaya3 OP 不确定覆盖 equalshashCode 实际上是他(或她)问题的解决方案。 【参考方案1】:

在这里实现equals(...) 和hashCode(...) 是正确的方法。通常人们使用他们的 IDE 为他们生成这些方法,这是 Java 7+ 的样子:

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Label label = (Label) o;
        return Objects.equal(nodes, label.nodes);
    

    @Override
    public int hashCode() 
        return Objects.hashCode(nodes);
    

如果您有多个字段,则变为:

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Label label = (Label) o;
        return Objects.equal(nodes, label.nodes) &&
                Objects.equal(other, label.other);
    

    @Override
    public int hashCode() 
        return Objects.hashCode(nodes, other);
    

但是,这只有在 Node 的实现也实现 equals(...)hashCode(...) 时才有效。

【讨论】:

【参考方案2】:

您绝对不想“在LinkedHashSet 上循环并比较...” 检测重复项是LinkedHashSet 应该做的事情。为此,它需要equalshashCode 的适当实现。

您可能明白您需要实现equals,以便当Label“等于”另一个Label 时返回true,但是您可以定义它。如果两个标签在它们具有相同节点时相等,那么是的,您几乎必须查看所有节点并检查它们是否相同。

剩下hashCode。您必须实现hashCodeequals 一致,即如果两个标签相等,则它们必须具有相同的哈希码。那是因为LinkedHashSet 将使用哈希码来确定Label 所在的桶,然后使用equals 将新的Label 与桶中已经存在的Label 进行比较。如果两个标签相等但生成不同的哈希码,LinkedHashSet 将无法将它们检测为重复。

最简单的做法是将所有节点的哈希码合并到Label 的哈希码中。比如:

int hashCode() 
    int hc = 1;
    for (Node n : allMyNodes) 
        hc = hc * 31 + n.hashCode();
    
    return hc;

如果有很多节点,并且除非它们“相等”,否则两个标签不太可能共享同一个节点,您可以只使用第一个节点的哈希码,而不是翻遍所有节点。

【讨论】:

由于Java 7+一般不需要自己处理复杂的hashCode实现,可以通过字段列表调用Objects.hashCode(...)。 另外在这里你不需要自己创建列表的 hashCode 作为列表实现可能作为 hashCode 实现。所以你可以做return Objects.hashCode(allMyNodes),仅此而已。 你在这两种情况下都是正确的,事实上List 接口将hashCode 定义为我编写的函数。 (虽然我犯了一个错误,它应该初始化为 1,而不是 0。)但我认为展示实际发生的事情很有用。 修复了这个功能。 @WillisBlackburn 感谢您的清晰解释!我喜欢你对 hashCode 方法的建议,但恐怕这对我的方法来说还不够。如,我必须非常小心,因为我可以有多个标签具有相同的节点,但在列表的不同顺序/部分,因此需要不同的 hashCodes。如果equals()方法返回true,hashCode()返回false,那么新标签是否会被添加到linkedHashSet中?那会是我的偏好。【参考方案3】:

在您的Node(或Label)课程中使用lombok 中的@EqualsAndHashCode

然后您可以将节点添加到您的LinkedHashSet

【讨论】:

如果你一开始还不知道 equals 和 hashCode 是如何工作的,最好不要开始使用 Lombok,它会让你几乎无法理解和调试它。

以上是关于提问一个java的问题:是有关equals()和==的,问题如下的主要内容,如果未能解决你的问题,请参考以下文章

如何实现 equals 方法

有关 java 重写equals 方法, 判断两个点是不是相同,求高手详细解答,谢谢!!!!!

重写了equals方法为何需要重写 hashCode

Java常见面试知识点汇总

Java常见面试知识点汇总

Java常见面试知识点汇总