Java - equals方法
java提高篇(十三)-----equals()方法总结
equal和==区别
==比较对象基于内存引用,两个引用完全相同返回true
Java 语言里的 equals方法其实是交给开发者去覆写的,让开发者自己去定义满足什么条件的两个Object是equal的。
所以我们不能单纯的说equals到底比较的是什么。你想知道一个类的equals方法是什么意思就是要去看定义。
超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等。该方法的源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
我们知道所有的对象都拥有标识(内存地址)和状态(数据),同时“==”比较两个对象的的内存地址,所以说使用Object的equals()方法是比较两个对象的内存地址是否相等,即若object1.equals(object2)为true,则表示equals1和equals2实际上是引用同一个对象。虽然有时候Object的equals()方法可以满足我们一些基本的要求,但是我们必须要清楚我们很大部分时间都是进行两个对象的比较,这个时候Object的equals()方法就不可以了,实际上JDK中,String、Math等封装类都对equals()方法进行了重写。下面是String的equals()方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
对于这个代码段:if (v1[i++] != v2[j++])return false;我们可以非常清晰的看到String的equals()方法是进行内容比较,而不是引用比较。至于其他的封装类都差不多。
在java中进行比较,我们需要根据比较的类型来选择合适的比较方式:
1) 对象域,使用equals方法 。
2) 类型安全的枚举,使用equals或== 。
3) 可能为null的对象域 : 使用 == 和 equals 。
4) 数组域 : 使用 Arrays.equals 。
5) 除float和double外的原始数据类型 : 使用 == 。
6) float类型: 使用Float.foatToIntBits转换成int类型,然后使用==。
7) double类型: 使用Double.doubleToLongBit转换成long类型,然后使用==。
原因嘛,里面提到了两点:
However, there are two exceptions:
If f1 and f2 both represent
Float.NaN, then the equals method returns
true, even though Float.NaN==Float.NaN
has the value false.
If <code>f1 represents +0.0f while
f2 represents -0.0f, or vice
versa, the equal test has the value
false, even though 0.0f==-0.0f
has the value true.
复写equals()
我们在覆写equals()方法时,一般都是推荐使用getClass来进行类型判断,不是使用instanceof。我们都清楚instanceof的作用是判断其左边对象是否为其右边类的实例,返回boolean类型的数据。可以用来判断继承中的子类的实例是否为父类的实现。注意后面这句话:可以用来判断继承中的子类的实例是否为父类的实现,正是这句话在作怪。我们先看如下实例(摘自《高质量代码 改善java程序的151个建议》)。
public class Person {
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name){
this.name = name;
}
public boolean equals(Object object){
if(object instanceof Person){
Person p = (Person) object;
if(p.getName() == null || name == null){
return false;
}
else{
return name.equalsIgnoreCase(p.getName());
}
}
return false;
}
}
子类:
public class Employee extends Person{
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Employee(String name,int id){
super(name);
this.id = id;
}
/**
* 重写equals()方法
*/
public boolean equals(Object object){
if(object instanceof Employee){
Employee e = (Employee) object;
return super.equals(object) && e.getId() == id;
}
return false;
}
}
上面父类Person和子类Employee都重写了equals(),不过Employee比父类多了一个id属性。测试程序如下:
public class Test {
public static void main(String[] args) {
Employee e1 = new Employee("chenssy", 23);
Employee e2 = new Employee("chenssy", 24);
Person p1 = new Person("chenssy");
System.out.println(p1.equals(e1));
System.out.println(p1.equals(e2));
System.out.println(e1.equals(e2));
}
}
上面定义了两个员工和一个普通人,虽然他们同名,但是他们肯定不是同一人,所以按理来说输出结果应该全部都是false,但是事与愿违,结果是:true、true、false。
对于那e1!=e2我们非常容易理解,因为他们不仅需要比较name,还需要比较id。但是p1即等于e1也等于e2,这是非常奇怪的,因为e1、e2明明是两个不同的类,但为什么会出现这个情况?首先p1.equals(e1),是调用p1的equals方法,该方法使用instanceof关键字来检查e1是否为Person类,这里我们再看看instanceof:判断其左边对象是否为其右边类的实例,也可以用来判断继承中的子类的实例是否为父类的实现。他们两者存在继承关系,肯定会返回true了,而两者name又相同,所以结果肯定是true。
所以出现上面的情况就是使用了关键字instanceof,这是非常容易“专空子”的。故在覆写equals时推荐使用getClass进行类型判断。而不是使用instanceof。
Java - equals方法的更多相关文章
- java equals()方法
java基础学习总结--equals方法 一.equals方法介绍 1.1.通过下面的例子掌握equals的用法 1 package cn.galc.test; 2 3 public class Te ...
- Java equals方法学习
通过某个特征值来判断两个对象是否"等价",当这两个对象等价时,判断结果为true,否则结果为false. Object类(Java的"对象世界"的根)中实现的e ...
- java equals()方法的注意事项
1.在写代码的时候,我们有时候需要判断两个相同类的对象的值是否全部相等,很多人想到的就是equals()方法,但是equals方法真的是可以比较吗?其实equals方法比较的并不是两个对象的值,它只是 ...
- Java——equals方法---18.10.18
一.equals方法定义 public boolean equals(Object obj)方法 //提供对象是否“相等”的逻辑 二.”equals“和“==”的区别 1.“==”比较的是两个变量本身 ...
- java -> equals方法与toString方法
equals方法 equals方法,用于比较两个对象是否相同,它其实就是使用两个对象的内存地址在比较.Object类中的equals方法内部使用的就是==比较运算符(比较内存地址). 在开发中要比较两 ...
- [java] 更好的书写equals方法-汇率换算器的实现(4)
[java] 更好的书写equals方法-汇率换算器的实现(4) // */ // ]]> [java] 更好的书写equals方法-汇率换算器的实现(4) Table of Content ...
- java中的equals()方法重写
如何java中默认的equals方法跟实际不符的话,需要重写equals方法.例如: public class TestEquals { public static void main(String[ ...
- java提高篇(十三)-----equals()方法总结
equals() 超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等.该方法的源码如下: public boolean equals(Object obj) { retu ...
- Java中“==”与equals方法的区别
1. 用“==”比较两个变量,如果两个变量是基本类型变量,且都是数值类,则值相等就返回true 如果两个变量是引用型变量,则两个对象的地址一样,即指向同一个对象,则返回true 2.equals:St ...
随机推荐
- Lily-一个埋点管理工具
本文来自网易云社区 前言 在很多项目中,埋点数据使用表格来统计的,随着项目的进行,数据量越来越复杂,越来越难以维护.所以很多公司都已经开发了一整套系统,从埋点的录入到代码的输出. 我们项目中iOS和A ...
- Android开发重点难点:RelativeLayout(相对布局)详解
https://i.cnblogs.com/EditPosts.aspx?opt=1 重点知识 和线性布局(LinearLayout)一样,RelaiveLayout相对布局也是我们用的比较多的一个布 ...
- underscore.js源码研究(6)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- 【xsy2506】 bipartite 并查集+线段树
题目大意:有$n$个点,你需要操作$m$次.每次操作为加入/删除一条边. 问你每次操作后,这$n$个点构成的图是否是二分图. 数据范围:$n,m≤10^5$. 此题并没有强制在线,考虑离线做法. 一条 ...
- Ubuntu 12.04 安装Redis并设置主从复制
今天想在Ubuntu上安装一个Redis服务器并配置Master-Slave,一开始懒得连VPN就查了一些国内的文章,不知道是没有亲自验证过的转载文章,还是版本问题造成的,发现按照步骤都没能成功完成配 ...
- How to change windows applicatioin's position via Win32 API
可以使用的Win32 API是: [DllImport("user32.dll")] private extern static bool SetWindowPos(IntPtr ...
- (转)Linux top命令的用法详细详解
原文:https://yq.aliyun.com/articles/399004?spm=a2c4e.11153940.blogcont399002.9.3a19f00aHOA3SH# 摘要: 首先介 ...
- centos 7 hadoop的安装和使用
准备工作 安装jdk 用户免密登录 安装参考文章: http://blog.csdn.net/circyo/article/details/46724335 http://www.linuxidc.c ...
- TCP 流量控制、拥塞控制
流量控制: 流量控制是为了控制发送方发送速率,保证接收方来得接收. 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率.将窗口字段设置为 0,则发送方不能发送数据. ...
- Android之混淆心得与亲身体验
project.properties 中设置 proguard.config=proguard-project.txt proguard-project.txt 中设置 -optimizationp ...