您好, 访客   登录/注册

JAVA中“相等性比较”的实现技巧

来源:用户上传      作者:

   摘要:本文主要研究JAVA语言中如何进行基本类型和引用类型数据的“相等性比较”.通过介绍JAVA程序运行时的内存、运算符==、方法equals知识,解析String类中equals源码,研究具体程序的运行过程,阐明各类数据“相等性比较”的实现技巧.
   关键词:相等性比较;常量池;==;equals();方法重写
  中图分类号:TP312  文献标识码:A  文章编号:1673-260X(2019)04-0053-02
  1 引言
   Java语言具有面向对象、跨平台、多线程等优良特性,在历年TIOBE世界编程语言排行中多居榜首,是世界上使用范围最广的编程语言之一[1].在Java编程过程中,有时需要对数据是否相等进行比较.Java语言的数据类型分两大类:基本类型、引用类型.基本类型的变量中存储的是具体的数据值,变量比较大小时比较的是具体数据值;引用类型变量中存储的是对象的引用,在根类Object类的toString()方法中声明为:getClass().getName() + "@" + Integer.toHexString(hashCode()),各子孙类可以根据需要将其改写.
  2 知识介绍
  2.1 Java程序运行时的内存
   Java程序运行时,需要占用内存空间,每一片区域都有特定的处理数据方式和内存管理方式[2].Java程序运行时的内存区域主要划分为:栈区、堆区、静态数据区、代码区等5个区域,现主要介绍前三个区域.
   (1)栈区(VM Stack):虚拟机栈中存放了一个个栈帧,当程序执行一个方法时,就入创建一个栈帧并压入栈中,一个栈帧中主要包括有局部变量表、操作数栈等,方法执行完毕后,此栈帧从VM Stack中移除.
   (2)堆区(Heap):存放所有new出来的东西,如对象实例、数组等.
   (3)方法区(Method Area):用于存放被虚拟机加载的类信息、常量、静态常量等,运行时常量池也在方法区中.常量池中所有相同的常量被合并,只占用一个空间.
   (4)本地方法栈(Native Method Stack).
   (5)程序计数器(Program Counter Register).
  2.2 Java中如何比较数据是否相等
   方法一:使用操作符“==”,比较两个操作数在栈区的值是否相等.若为基本类型数据,比较的是具体的数据值是否相等[3];若为引用类型数据,比较的是两个对象的引用值,当且仅当两个对象的引用值相同时,即是指向堆区或方法区的同一个对象实体时,结果为true.
   方法二:使用equals()方法[4].根结点类Object类的equals(Object obj)方法体为:return (this == obj); 各子孙类可以根据需要修改.
  2.3 方法重写
   日常生活中,我们比较两个对象是否相同,主要比较的是两个对象的主要属性值是否相同.比如说我们的书丢失了,需要买一本一樣的书,意思是买一本ISBN相同的书即可,也就是说出版社、作者名、书名、版次、价格等信息相同即可,不是非得就是原来的那本书.
   具体类可以制定相应的规则用于比较两个此类对象是否相等,一般来讲,这种规则的制定通过重写父类中的equals方法来实现.在此,我们来研究String对象的比较规则.
  2.4 String类源码解析
   解析:每一个String对象内部都有一个重要的成员变量:char类型的数组value[],用于存放字符串对象所对应的字符序列.
   解析:String对象的equals方法,在两种情况下方法返回值为true:1、当前对象与形参对象的引用值相同,即指向同一对象实例时,返回值为true.2、当形参为字符串对象,且当前对象与形参对象的成员变量value数组的长度相同,则依次比较两个value数组中每一个数组元素的值,若所有字符数组元素都相同,则返回值为true.在前面已知,字符串对象的value数组中存放的是字符串对象所对应的字符序列.简而言之,若当前字符串对象与形参字符串对象的字符序列相同,则返回为true.
  3 程序举例
   执行代码3、4后,JVM在栈区开辟空间i1、i2、i3、s1、s2、s3、s4.
   执行代码5、6、7后,栈区空间i1被赋值88、i2被赋值10000、i3被赋值88.
   执行代码8,输出“i1==i2”的比较结果,比较栈区i1与i2空间的整型常量值是否相等,不相等,故输出为false.
   执行代码9,输出“i1==i3”的比较结果,比较栈区i1与i3空间的整型常量值是否相等,相等,故输出为true.
   执行代码10,JVM检查常量池中是否已存在“巢湖学院”字符串常量,若已存在,则直接让栈区s1指向常量池中的该对象,当前程序中,常量池中现在没有“巢湖学院”这个字符串常量,故在常量池中开辟一个新的空间存放此字符串常量,并让栈区s1指向该对象.
   执行代码11,JVM检查常量池中是否已存在“巢湖学院”字符串常量,因已存在,所以直接让栈区s2指向该对象.
   执行代码12,JVM在堆区创建一个新的字符串对象,并让栈区s3指向该对象.
   执行代码13,JVM在堆区创建一个新的字符串对象,并让栈区s4指向该对象.
   执行代码14,JVM在比较栈区s1和s2的引用值是否相等,即是否指向同一个对象,因为s1与s2均指向常量池的同一个“巢湖学院”字符串常量对象,故输出为true.
   执行代码15,JVM在比较栈区s1和s2所指向对象的value数组元素是是否相同,即字符串对象的字符序列是否相同,是,故输出为true.
   执行代码16,JVM在比较栈区s3和s4的引用值是否相等,即是否指向同一个对象,因为s3与s4分别指向堆区的两个不同字符串对象,故输出为false.
   执行代码17,JVM在比较栈区s3和s4所指向的对象的value数组元素是否相同,即堆区两个字符串对象的字符序列是否相同,是,故输出为true.
  4 结语
   通过本文的源码解析与程序执行过程中的内存分析,我们知道,在JAVA中实现“相等性比较”的技巧及相应原理.运用运算符“==”比较时,基本类型数据比较的是数据值[3,5],引用类型数据比较的是引用值;类可以通过重写equals方法来制定本类对象是否相等的规则.
  参考文献:
  〔1〕李小荣,疏志年,陈丽萍,程军.用软件工程指导Java程序设计[J].福建电脑,2015,31(12):66+150.
  〔2〕海子.JVM的内存区域划分[EB/OL].http://www.cnblogs.com/dolphin0520/p/3613043.html;2014 -05-29.
  〔3〕黄海东.JAVA中实现“相等”比较的深入分析[J].湖北第二师范学院学报,2015,32(02):31-35.
  〔4〕钱宇虹.论Java对象的比较技巧[J].软件工程师,2010(08):50-53.
  〔5〕田春婷.Java对象的比较方式[J].电脑知识与技术,2014,10(34):8163-8164.
转载注明来源:https://www.xzbu.com/1/view-14841795.htm