接口使用实例(自定义类型排序和深浅拷贝)
Posted 爱敲代码的三毛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口使用实例(自定义类型排序和深浅拷贝)相关的知识,希望对你有一定的参考价值。
一、Comparable 接口
1.sort 方法
我们知道数组有一个 sort 方法是用来排序的,使用也很简单可以直接调用它来排序基本类型的数组。
代码示例:
运行结果
那么如果用它来排序一个自定义类型,能不能排序呢?
代码示例:
运行结果:
这里抛出一个异常,说学生这个类型不能转换 java.lang.Comparable,那么这个Comparable到底是个啥呢?
来看一下源码
也就是说我们要把 Student 强制转换为 Comparable 再来调用Comparable 里面的 compareTo方法来进行比较。
仔细思考, 不难发现, 和普通的整数不一样, 两个整数是可以直接比较的, 大小关系明确.
而两个学生对象的大小关系怎么确定呢,现在需要我们自己来指定,
2.compareTo
我们调用 sqrt 来进行自定义类型的比较,但是它并不知道要通过什么来比较。年龄还是姓名?
所以我们要指定比较方法
让我们的 Student 类实现 Comparable 接口, 并实现其中的 compareTo 方法
代码示例:
运行结果
那么如果要用姓名比较,也要重写compareTo方法,如果以后引用类型要进行比较一定要用 compareTo方法,而且一定要实现Comparable 接口
运行结果
在 sort 方法中会自动调用 compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象.
然后比较当前对象和参数对象的大小关系(按分数来算).
如果当前对象应排在参数对象之前, 返回小于 0 的数字;
如果当前对象应排在参数对象之后, 返回大于 0 的数字;
如果当前对象和参数对象不分先后, 返回 0
3.小结
compareTo其实就是一个比较规则,如果以后自定义类型要进行比较一定要重写compareTo这个比较规则。但是如果这个比较规则已经被很多人使用,你突然想换个比较规则,如果修改比较规则必然会造成损失,所以这个方方法对类的侵入性太强了,并不是特别好
。
二、Comparator 接口
刚刚我们说 Comparable 对类的侵入性太强了,但有另外一个接口它十分灵活。就是Comparator 。
代码示例:
我们写了两个类,分别实现了 Comparator 这个接口,一个是用年龄比较,一个是用姓名比较。我们叫做比较器。
再来看原来的代码,我们的Student并没有实现任何接口,也没有重写compareTo 方法。
只是实例化了刚刚上面两个比较器,在用sort比较时,传过去了两个参数,一个是要排序的数组,一个是我们写的比较器对象。
运行结果:
Comparator 接口,如果要进行比较只需要根据自己的需要写一个比较器就好了,并不像第一个接口那样直接写死了。
三、Clonable 接口
1.Clonable 使用
Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 但是要想合法调用 clone 方法, 必须要先实现Clonable接口
1.实现Clonable接口
2.记住要处理异常
3.重写 Object 的 clone 方法
代码示例:
运行结果:
此时内存中的存储
2.浅拷贝
怎么来理解深拷贝和浅拷贝呢?
来看一下浅拷贝,我们在刚才的例子中在Student中实例化了一个Money类
运行结果
我们发现当我们修改 student 的money的值的同时,student1的值也被修改了,这并不是我们想要的拷贝效果,那么此时这就是一个浅拷贝。
此时的内存图
3.深拷贝
刚刚那个例子是浅拷贝,那么怎么实现深拷贝呢?
只需要在刚刚那个例子中修改,Student里面的clone方法即可。
先拷贝一个stydent,再把原来拷贝的对象里面的tmp也拷贝一份,让拷贝出来的新对象里面的tmp指向拷贝出来的tmp,就实现了深拷贝。
运行结果
此时内存图
完!
以上是关于接口使用实例(自定义类型排序和深浅拷贝)的主要内容,如果未能解决你的问题,请参考以下文章