首页 > 范文大全 > 正文

论Java对象的比较技巧

开篇:润墨网以专业的文秘视角,为您筛选了一篇论Java对象的比较技巧范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!

摘要:java对象比较是初学者不易掌握的。本文对与对象的比较密切相关的几个重要概念,如“类与对象的关系”“类与对象在内存中的存储”“对象和对象的引用”“对象引用的比较和对象内容的比较”等进行了深刻的剖析,随后给出了解决自定义对象比较的两种方法,即:运用Comparator接口实现比较算法,和运用Comparable接口实现可比较的对象,并对这两种方法进行对比,指出应用的场景。

关键词:Java对象的比较;对象的引用;自定义对象的比较;Comparator接口;Comparable接口

在Java语言开发过程中,常常需要对对象进行比较。例如,在IF等结构语句中需要根据对象比较所得出的结果来进行相关处理。但是Java对象毕竟跟普通的变量不同,要比较两个对象是否相同,跟比较两个变量的值是否相同有很大的差异。笔者在本文中,对Java对象的比较问题做出深刻的理解和分析,澄清初学者容易混淆的几个重要概念,给出进行Java对象比较的方法和代码。

1 跟对象比较相关的重要概念

1.1 类与对象的关系

在面向对象的编程语言中,类是程序的基本单元,它有一个类名并包括属性说明和服务说明两个主要部分。类与对象的关系就如同设计图纸与产品的关系。例如:自行车设计图,虽然设计图纸只有一张,但是根据图纸我们可以生产出一批自行车产品。设计图纸为所有同类型自行车提供了统一的抽象描述,就如同类是具有相同属性和方法的一组对象的抽象描述;自行车的生产过程就如同类的实例化过程,当我们定义好了类,实例化结果就是对象,有了类这一模版,我们可以通过实例化创建多个对象,而这些对象的共同特征可以归并到同一个类中去。 所以,类的实例化结果就是对象,而对一类对象的抽象就是类。

1.2 类与对象在内存中的存储

当程序员定义一个类时,只要不含静态成员变量和方法,Java虚拟机(JVM)不会在内存中给其分配存储空间,只有创建对象后,才会在内存中为对象分配存储空间。当我们用同一个类创建不同的对象时,JVM会在内存中为不同的对象分配不同的存储空间。也就是说,不同的对象会对应不同的内存地址。虽然同一个类可以创建多个对象,其内容可能相同(成员变量、成员方法等等都相同),但是每个对象在内存中的地址是不同的。

1.3 对象和对象的引用[1]

对象的引用在英文中是reference, 对象和对象的引用是容易混淆却又必须掌握的基础知识。先看下面的程序片断:

Student y;

y = new Student();

第一行语句声明了一个变量y,但是我们还没有在内存中创建对象,此时变量y 只是有可能成为一个Student对象的引用,它当前的值为 null。第二行语句使用 new操作符在内存中创建了一个对象,我们可以把新创建的对象想象成一个氢气球,引用变量y是紧紧抓住这只气球的绳子,如图1所示:

我们也可以创建一个新的对象,但是并没有把它赋给一个引用变量,如下所示:

new Student();

这样的对象就好像飞掉的氢气球,在我们的程序中永远无法访问。

请注意,我们可以将以上两行语句合二为一,即声明一个引用变量y,并创建一个Student对象赋给 y , 这样y就成为Student对象的引用,如下所示:

Student y = new Student();

初始化引用变量的另一种方法,是将已有的对象引用传递给它,请看下面的程序片断:

Student x = new Student(); Student y;y = x;

第一行语句实例化一个Student对象;第二行语句仅申明一个引用变量y,并没有创建第二个Student对象;第三行语句把引用x 传递给y, 此时,x并没有失去对Student对象的引用,所以结果是,有两根“绳子”抓住了同一只气球,如图2所示。

因此我们可以看到,同一个对象可以有多个引用变量引用它,但是一个引用变量一次只能引用一个对象,所以当引用变量引用另一个对象时,意味着它要失去对原来对象的引用。继续分析下面的程序片断会得到怎样的结果呢?

Student x = new Student(); Student y;y = x;Student z = new Student();

y = z; //y失去对对象#1的引用,转而引用对象#2

x = z; //x失去对对象#1的引用,转而引用对象#2

结果,当一个对象失去了所有的引用,就如同飞掉的氢气球,这个对象在我们的程序中永远无法访问,如图5所示,它所占用的内存永久性的浪费了。在 C++语言中遇到这种情况,程序员必须小心处理内存回收问题,而在 Java语言中,垃圾回收器(garbage collector)将自动为我们回收丢失对象的内存。

1.4 对象引用的比较和对象内容的比较

“==”运算符与equals()方法可用于对象比较,但是比较的实质大相径庭。其中,“==”是将对象的引用进行比较,实质是比较两个引用变量是否引用同一个对象;而equals()方法则是比较两个对象的实际内容是否相同。请看下面的程序片断:

由于变量n1和变量n2 分别引用了不同的Integer对象,所以n1==n2的结果为false;而这两个Integer对象的内容都是47,所以n1.equals(n2)的结果为true。同理,由于变量s1和变量s2 分别引用了不同的String对象,如图6,所以s1==s2的结果为false;而这两个String对象的内容都是“Hello”,所以s1.equals(s2)的结果为true.

为什么在字符串常量这种情况下 s3==s4 结果为true而不是false呢?这是因为JVM为同一个字符串常量只创建一个对象而不是两个,所以s3 和s4实际上引用了同一个字符串对象,这就不难理解s3==s4 结果为true了。

在Java中很多类都定义了equals()方法比较对象内容,其返回值为boolean类型,这些类包括:String、Double、Float、Long、Integer、Short、Byte、Boolean、BigDecimal、BigInteger等等。 因为equals()方法首先做“==”比较,所以当两个变量引用的是同一个对象时很快得到返回值true,只有当两个变量引用的是不同对象时才进行内容的比较

2 自定义对象的比较

假设我们创建了自己的类以后,如何进行对象的比较呢? 例如: Employee 是我们创建的类,封装了雇员的基本信息,包括姓名和年龄两个属性,如程序清单1所示:

现在需要将公司的所有雇员按年龄进行排序。这是根据对象的某属性进行排序。针对这种应用有两种处理方法:一种是使用parator接口,另一种是使用parable接口。

2.1 运用Comparator接口实现比较算法

第一种方法是保持Employee 类不变化,在这之外编写一个比较算法,这需要使用Comparator接口。

Comparator接口定义了一个compare()方法, 其原型如下:

/*@return o1小于、等于或大于o2,分别返回负整数、零或正整数。*/

int compare(Object o1, Object o2);

为了解决雇员的年龄比较问题,我们需要构造一个年龄比较器类,如程序清单2所示:

年龄比较器类AgeComparator实现了Comparator接口,即提供了compare()方法的具体实现。在这个方法中,将两个雇员对象的年龄进行比较,针对o1小于、等于或大于o2,分别返回负整数、零和正整数。

随后将Comparator传递给Collections.sort或Arrays.sort 方法就可以对对象的集合进行整体排序。如程序清单3所示。employees数组初始化时5个雇员的顺序为40,20,34,18,25( 以年龄为准), 整体排序后变成 18,20,25,34和40 了。

2.2 运用Comparable接口实现可比较的类

第二种方法需要对Employee 类进行改造,使之成为一个可比较的(Comparable)类,这需要Employee类实现Comparable接口。

Comparable接口定义了一个compareTo ()方法, 其原型如下:

/* @return 该对象小于、等于或大于指定对象o,分别返回负整数、零或正整数。*/

int compareTo(Object o);

改造后的Employee类如程序清单4:

请注意,其中的CompareTo()方法比较该对象和指定对象的顺序,如果该对象小于、等于或者大于指定对象,则分别返回负整数、零和正整数

Comparable接口强行对实现它的每个类的对象进行整体排序,实现此接口的对象列表(和数组)可以通过Collections.sort或Arrays.sort进行自动排序。如程序清单5:

2.3 Comparator和Comparable的区别

一个类实现了Comparable接口则表明这个类的对象之间是可以相互比较的,这个类的对象组成的集合就可以直接使用sort方法排序。Comparator可以看成算法的实现,将算法和数据分离。如果类的设计师没有考虑比较问题而没有实现Comparable 接口,则可以通过Comparator来实现排序而不必改变对象本身。

3 结语

Java对象的比较是初学者不易掌握的。本文对“类与对象的关系”,“类与对象在内存中的存储”,“对象和对象的引用”,“对象引用的比较和对象内容的比较”等几个重要概念进行了深刻的剖析,随后给出了解决自定义对象比较的两种方法,即:运用Comparator接口实现比较算法,和运用Comparable接口实现可比较的对象,并对这两种方法进行对比,指出应用的场景。

参考文献

[1] Jacquie Barker.Beginning Java Objects From Concept to Code[M]. Birmingham,UK.Published by Wrox Press Ltd. 2000