`
liuwei1981
  • 浏览: 752731 次
  • 性别: Icon_minigender_1
  • 来自: 太原
博客专栏
F8258633-f7e0-30b8-bd3a-a0836a5f4de5
Java编程Step-by...
浏览量:156200
社区版块
存档分类
最新评论

68.==和equals()

 
阅读更多

==equals()恐怕是刚刚开始学习Java中,最让人混淆的东西了。下面就可以

 

在Java程序设计中,我们经常需要比较两个变量值是否相等,比如:
 a = 10;
 b = 12;
 if(a == b) {
  //statements
 }

 


再如:
 ClassA a = new ClassA(“abc”);
 ClassA b = new ClassA(“abc”);
 if (a == b){
  //statements
 }


对于第一个例子,比较的是简单类型数据,它们是明显相同的,所以a==b这个值为true。

 

但是,对于第二个例子中的比较表达式,因为它们比较的是这两个变量a和b是否指向同一个对象引用,在这里,因为a指向一个对象,而b指向另一个对象,所以,它们并不指向同一个对象,因此,a==b返回的值是false。


为了方便说明简单类型和引用类型比较,此处用int类型和它的封装类Integer来说明简单类型和封装类型的进行比较时的区别。


我们来看下面的例子。

 

 

public class TestEqual {
 public static void main(String[] args) {
  // 简单类型比较
  int a = 100;
  int b = 100;

 

 

  System.out.println("a==b? " + (a == b));

  // 引用类型比较
  Integer c = new Integer(100);
  Integer d = new Integer(100);

  System.out.println("c==d? " + (c == d));
 }

运行这个程序,在控制台上打印出如下信息:
a==b? true
c==d? false

 // 其他属性略
 public Citizen(String theId) {
  id = theId;
 }
}


可以看出,比较两个引用类型的时候,虽然用了同一个参数构造两个变量,但是它们并不相同。这是为什么呢?


我们知道,对于引用类型,它们指向的是两个不同的对象:这两个对象的值都为100。因为它们指向的对象是两个对象,因此,比较这两个变量会得到false的值。也就是说,对于引用类型变量,运算符“==”比较的是两个对象是否引用同一个对象。

 

那么,如何比较对象的值是否相等?


在Java中,提供了一个equals()方法,用于比较对象的值。我们将上面的程序稍作修改:
 Integer c = new Integer(100);
 Integer d = new Integer(100);  
 System.out.println("c equals d? "+(c.equals(d)));


这个时候表达式c.equals(d)会得到一个true,这是因为,方法equals()进行的是“深层比较”,它会去比较两个对象的值是否相等。


那这个equals()方法是由谁来实现的呢?在所有类的父类Object中,已经定义了一个equals()方法,但是这个方法实际上也只是测试两个对象引用是否指向同一个对象。

 

所以,你可以使用这个方法来进行比较操作,但是,它并不一定能得到你所期望的效果。经常的,还需要自己将定义的类中的equals()进行覆盖。象Integer封装类,就覆盖了Object中的equals()方法。


关于==和equals()两种比较方式,在使用的时候要小心的选择:如果测试两个简单类型的数值是否相等,则一定要使用“==”来进行比较;

 

如果要比较两个引用变量对象的值是否相等,则用对象的equals()方法来进行比较;如果需要比较两个引用变量是否指向同一个对象,则使用“==”来进行比较。对于自定义的类,应该视情况覆盖Object或其父类中的equals()方法。equals()方法只有在比较的两者是同一个对象的时候,才返回true。

 

覆盖equals()方法

 

Object类的equals()方法的用处是用于测试两个对象引用是否是指向同一个对象。这种比较方式在实际应用中并没有多大的用处:我们常常需要的是判断两个对象的值是否相等而并不关心它们是否指向同一个对象。因此,需要在自己定义的类中对它进行覆盖。


我们来考虑如下的这种场景:假设在一个Java应用程序中,创建了两个“公民”对象。现在,我们需要比较两个“公民”对象是否相等,此时,关心的是这两个“公民”对象代表的是否为同一个人,而并不关心它们是否是同一个内存区域里的对象。

 

假设有一个类“Citizen”用于表示公民,它有一个属性id用来表示这个公民的身份证号,我们假设身份证号不会重复,也就是说,一个身份证号对应一个公民。它的类定义如下(为简单起见,省略了其他的属性而只留下用于表示身份证号的id属性):
public class Citizen {
 // 身份证号
 String id; 

 // 其他属性略
 public Citizen(String theId) {
  id = theId;
 }


我们假设在一个Java应用程序中,建立了两个“Citizen”对象,然后,在某个点上需要判断这两个对象是否代表了同一个公民:
Person p1 = new Person("id00001");
Person p2 = new Person("id00001");
... ...
if (p1.equals(p2)){
 ... ...
}


在这个程序中,因为这两个“Citizen”对象的身份证号一样,所以,它们代表的应该是同一个人,但如果用Object的默认方式,它只会去比较两个对象引用变量是否指向同一个对象,因此,它返回false。

 

显然,这个结果不是我们所期待的。此时,就需要在“Citizen”中覆盖Object类中的equals()方法,以满足我们自己的需求。

 

public class Citizen {
 // 身份证号
 private String id; 

 // 覆盖equals方法
 public boolean equals(Object obj) {
  // 首先需要判断需要比较的obj是否为null,
  // 如果为null,返回false
  if (obj == null) {
   return false;
  }
  // 判断测试的是否为同一个对象,
  // 如果是同一个对象,无庸置疑,它应该返回true
  if (this == obj) {
   return true;
  }
  // 判断它们的类型是否相等,
  // 如果不相等,则肯定返回false
  if (this.getClass() != obj.getClass()) {
   return false;
  }
  // 将参数中传入的对象造型为Citizen类型
  Citizen c = (Citizen) obj;
  // 只需比较两个对象的id属性是否一样,
  // 就可以得出这两个对象是否相等
  return id.equals(c.id);
 }
}

 

在这个类“Citizen”中,覆盖了父类(Object)中的equals(),使得它能够根据对象的id属性是否相等来判断这两个对象是否相等。

 

然后,我们来编写一个类来测试它,如下: 

 

public class TestCitizen {
 public static void main(String[] args) {
  Citizen p1 = new Citizen("id00001");
  Citizen p2 = new Citizen("id00001");
  System.out.println(p1.equals(p2));
 }
}



这个类中,定义了一个main()方法,它是一个应用程序。在main()方法中,使用身份证号“id00001”创建了两个Citizen对象,然后,用覆盖的equals()方法比较这两个对象的相等性,此时,因为它们的身份证号相同,equals()方法因此将返回true。编译并运行这个程序,将向控制台输出如下信息:
true


我们可以试着将覆盖的equals()方法删除或注释掉,然后重新编译运行TestCitizen.java,看看运行的结构。

 

在这个覆盖的equals()方法中,还使用到了另一个方法getClass(),它将返回对应的对象的运行期类(runtime class)。


另外,如果一个类的父类不是Object,那么,你首先需要检查它的父类是否定义了equals()方法,如果是的话,在覆盖父类的equals()方法的时候,需要记得在子类的equals()方法中使用下面的方法来调用父类的equals()方法,以确保父类中的相关比较能够得到执行:
super.equals(obj)


例如,假设有一个类“Armyman”用来表示军人,它是一个“Citizen”的子类,此时,如果在Armyman中覆盖Citizen的equals()方法,则需要在覆盖的equals()方法中调用被覆盖的Citizen类中的equals()方法:
public boolean equals(Object obj){
return super.equals(obj)&&(其他比较语句);
}

分享到:
评论

相关推荐

    Java 面试宝典

    11、"=="和 equals 方法究竟有什么区别? ................................................................. 12 12、静态变量和实例变量的区别? ...............................................................

    计算器_java

    if(sf.equals("9")||sf.equals("8")||sf.equals("7")||sf.equals("6")||sf.equals("5")||sf.equals("4")||sf.equals("3")||sf.equals("2")||sf.equals("1")||sf.equals("0")||sf.equals("C")||sf.equals("←")||...

    Android登陆注册

    private String originAddress = "http://100.68.105.216:8080/MyTest/StudentloginServlet";//真机连接 //用于处理消息的Handler @Override protected void onCreate(Bundle savedInstanceState) { super....

    postGIS 用户手册

    1 Introduction 1 1.1 Project Steering Committee . . . . . . . . ....1.2 Contributors Past and Present ....1.3 More Information ....2.1 Short Version ....2.2 Requirements ....2.3 Getting the Source ....

    hibernate3.6 文档(pdf 格式)

    截至 2011-08-29 官方公布的最新 hibernate 文档,此为英文版,配套中文版下载地址:http://download.csdn.net/source/3557584。 详细信息: 版本:3.6.3.Final,作者:Gavin King, Christian Bauer, Max Rydahl ...

    2021年最新java面试题--视频讲解(内部培训84个知识点超详细).rar

    Java面试题07.==和equals的区别 Java面试题08.String Java面试题09.讲一下java中的集合 Java面试题10.ArrayList 和LinkedList的区别 Java面试题11.HashMap和HashTable的区别 Java面试题12.实现一个拷贝文件的工具类...

    史上最全java面试,103项重点知识,带目录

    2. == 和 equals 的区别是什么? 1 3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗? 3 4. final 在 java 中有什么作用? 4 5. java 中的 Math.round(-1.5) 等于多少? 4 6. String 属于基础的数据...

    目录选择器源代码

    68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 ...

    Java常见面试题208道.docx

    2.== 和 equals 的区别是什么? 3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗? 4.final 在 java 中有什么作用? 5.java 中的 Math.round(-1.5) 等于多少? 6.String 属于基础的数据类型吗? 7....

    net学习笔记及其他代码应用

    protected : 保护成员,该类内部和继承类中可以访问。 public : 公共成员,完全公开,没有访问限制。 internal: 在同一命名空间内可以访问。 2 .列举ASP.NET 页面之间传递值的几种方式。 答. 1.使用QueryString,...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ Java面试题07.==和equals的区别.mp4 │ Java面试题08.String.mp4 │ Java面试题09.讲一下java中的集合.mp4 │ Java面试题10.ArrayList LinkedList.mp4 │ Java面试题11.HashMap和HashTable的区别.mp4 │ Java面试...

    ap6212a0_a33_sc3817r_服务器验证通过_bt已经通了_wifi需要修改配置_需要再次验证_20170626_1549.7z

    调通sina33下的AP6212A0版本的BT 大文实验室/大文哥 壹捌陆捌零陆捌捌陆捌贰 ...完成时间:2017/6/26 11:01 版本:V1.0 本文参照: 《A33 wifi移植说明书.pdf》 还有就是全志R16的parrotv1.1的官方SDK(Android...

    人民币小写转大写(Java 实现)

    //金额里面的角和分 private static final String[] jf={ "角","分" }; /** * 处理金额的整数部分,返回"...圆整" * @param integer * @return String * @throws Exception */ public static ...

    dwr验证框架多级联下拉菜单

    strSelectID_P.equals("")) { session.setAttribute("SelectID_P", strSelectID_P); } String sql_P = "SELECT * FROM tb_Area WHERE TypeID=1 or TypeID=4 or TypeID=5"; try { rs_province = connDB....

    java基础题 很全面

    68. Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 15 69. LINUX下线程,GDI类的解释。 15 70. java常用的设计模式?说明工厂模式。 15 71. 内部类可以...

    ap6212a0_a33_sc3817r_神舟验证版本_借用nvram_ap6210这个配置文件_20170626_1834没有外层目录.7z

    调通sina33下的AP6212A0(WIFI+BT) 大文实验室/大文哥 壹捌陆捌零陆捌捌陆捌贰 ...完成时间:2017/6/26 11:01 版本:V1.1 本文参照: 《A33 wifi移植说明书.pdf》 还有就是全志R16的parrotv1.1的官方SDK(Android...

    数据结构题

    System.out.println(s1.equals(s2)); A.true,true B.false,false C.true,false D.false ,true 37.二叉树有( )种不同的基本形态。 A.3 B.4 C.5 D.6 38.设一组初始记录关键字序列为(Q,H,C,Y,P,A,M,S,...

    java面试宝典2012版.pdf

    11、"=="和equals方法究竟有什么区别? 12、静态变量和实例变量的区别? 13、是否可以从一个static方法内部发出对非static方法的调用? 14、Integer与int的区别 15、Math.round(11.5)等於多少? Math.round(-11.5)等...

Global site tag (gtag.js) - Google Analytics