`

[Java]重新编写Object类中的方法(zt)

 
阅读更多
Object类是所有类的超类,也就是说,Java中的每一个类都是由Object扩展而来的.因而每当你创建一个对象,它都将拥有Object类中的全部方法.让我们先来看看java.lang.Object的中的主要方法有哪些:
public class Object{
//公共构造函数
public Object();
//公共实例方法
public boolean equals(Object obj);
public native int hashCode();
public final native Class getClass();
public String toString();
public final native void notify();
public final native void notifyAll();
public final void wait() throws InterruptedException;
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException;
//保护实例方法
protected native Object clone();
protected void finalize() throws Throwable; }
方法equals测试的是两个对象是否相等,方法clone进行对象拷贝,方法getClass返回和当前对象相关的Class对象,方法notify,notifyall,wait都是用来对给定对象进行线程同步的.
然而Object类所提供的只是一些基本的方法,我们在编写自己的类时经常需要覆盖这些方法,一方面是加强功能,另一方面也是为了适应当前的情况.这就引出了本文的主题——
如何编写自己的equals方法
首先要明确一个问题,Object类中的equals方法是怎样判断两个对象是否相等的呢?让我们来看看它的源代码:
public boolean equals(Object obj)
{
return (this == obj);
}

不难看出,它仅仅判断了两个对象的引用是否相等,这在很多情况下并没有太大的实际意义.比如,我们需要一个比较两个字符串是否相等,在String类中就覆盖了这个方法.标准的java类库中有超过150个equals方法的实现.然而java语言规范要求equals方法具有以下性质:
自反性:对于任何非空引用x, x.equals(x)返回true.
对称性:对于任何非空引用x和y, 当且仅当y.equals(x)返回true时,x.equals(y)返回true.
传递性:对于任何引用x,y和z,如果x.equals(y)返回true并且y.equals(z)也返回true,那么x.equals(z)应该返回true.
一致性:如果x和y引用的对象没有改变,那么x.equals(y)的重复调用应该返回同一结果.
对于任何非空引用x, x.equals(null)应该返回false.
这5条规则显示良好的逻辑性,想要写好自己的equals方法,必须满足它们.那么如何才能做到这些规则呢?
假设当前equals方法传进来的参数名为otherObject,
测试this是否与otherObject相等.
测试otherObject是否为null,如果是,一定要返回false.
测试this通otherObject是否同属于一个类.这是为了满足规则2.
把otherObject强制转换为另一个变量(这里称为other):Classname other = (Classname) otherObject.然后比较所有的字段.使用 == 比较基本类型字段,使用equals方法比较对象字段.如果所有的字段都匹配返回true,否则返回false.
下面举一个简单的例子:
class TestEqual{
int number;
String s;
public boolean equals(Object otherObject){
//首先看看这两个对象引用是否相等
if (this == otherObject)
return true;
//这是为了满足规则5
if(otherObject == null)
return false;
//如果两个对象所属类型不同,它们不可能相等
if(getClass() != otherObject.getClass())
return false;
TestEqual other = (TestEqual)otherObject;
//比较所有字段
return s.equals(otherObject.s) & number == otherObject.number;
}
}
这个例子虽然很简单,但却清晰地反映出了以上所说的要点.
还有一个需要注意的地方是,在子类中,首先要调用超类的equals方法,如果这项测试无法通过,那么两个对象不可能相等.也就是:
if(!super.equals(otherObject)) return false;

到这里相信大家已经对编写自己的equals方法有了一定的认识,只要在平时写程序的时候多注意一下,写好它并不难.
再来看看本文的第二大主题:

如何编写自己的clone方法
类似equals方法,我们先来讨论一下Object的clone方法效果是怎样的.不过在此之前,有个问题要提一下,所有使用clone方法的类,不论是继承Object.clone()还是覆盖它,都必须实现一个名为cloneable的接口.如果你打开java类库查一下,会发现这个接口里什么也没有,它仅仅是表明某个类具有被clone的能力.
用一个例子来研究一下Object.clone()的复制效果:
public class TestClone1 implements Cloneable{
int count;
TestClone1 next;
public TestClone1(int count) {
this.count=count;
if(count>0)
next=new TestClone1(count-1);
}
void add(){
count++;
if(next!=null)
next.count++;
}
public String toString(){
String s=String.valueOf(count)+" ";
if(next!=null)
s+=next.toString();
return s;
}
public Object clone(){
Object o=null;
//如果没有实现cloneable,将会抛出CloneNotSupported异常
try{
o=super.clone();
}
catch(CloneNotSupportedException e){
System.err.println("cannot clone");
}
return o;
}
public static void main(String[] args){
TestClone1 t=new TestClone1(1);
System.out.println("t="+t);
TestClone1 t1=(TestClone1)t.clone();
System.out.println("t1="+t1);
t.add();
System.out.println("after addedt t="+t+"t1="+t1)
}
}

在这个例子中创建t相当于两个相连的TestClone1实例,而在调用了t的add方法之后,意想不到的结果出现了:
t=1 0
t1=1 0
after added
t t=2 1
t1=1 1
t1也发生了改变,这点也许有些出乎你的意料.实际上Object.clone()进行的复制有着"bitwise"原则,也就是逐位复制.对于一个对象中定义的对象,它只是简单的复制这个对象的引用.这也就是常说的浅层拷贝(shallow copy),明白了这一点,想要执行深层拷贝(deep copy)也就不难了.
只需要在TestClone1 t1=(TestClone1)t.clone();后面加上t1.next=(TestClone1)t.next.clone();就能得到:
t=1 0
t1=1 0
after added
t t=2 1
t1=1 0
这个正确的结果.
接下来要介绍的是,如何控制clone能力.从前面可以知道,clone()是protected的,你必须覆盖并实现cloneable接口并处理必要的异常才能使用它.这样,你在设计自己的类时,有以下几种风格来控制clone能力:
不理会clone(),也就是在你的类中不涉及任何有关clone()的内容,如果有人想实现clone功能,必须写一个子类并完成刚才所说的要求.这适合于Object.clone()可以胜任复制你的类中全部字段的情况.
支持clone().你在你的类中实现cloneable接口并且覆盖clone方法以及捕获相应的异常.
有条件的支持clone().这种情况有些特殊,也就是你的类中保存着一些可能不能被复制的对象的引用(这里是指它们没有实现cloneable).这时候你只是在clone()中复制所有这些对象,如果遇到异常,抛出所有这些异常给使用你的类的人.举个例子,假设你在写一个类似于ArrayList的类,你不知道别人会在把什么样的对象保存在你的ArrayList里,所以你也不知道他们是否能够被复制.
不实现cloneable接口但覆盖clone方法为protected.这样你虽然让你的类不能被复制,但却提供了正确的clone方法,这样如果有人想复制你的类,写一个子类实现cloneable接口就行了.
不实现cloneable接口并覆盖clone方法直接抛出异常来防止你的类被复制.不过这并不是根本的解决方法,只能对付那些直接调用你的clone方法或是在子类中调用super.clone()的人.
使用final修饰你的类来防止你的类被复制.如果你的超类中有覆盖clone方法的,再重新覆盖clone方法并直接抛出异常.这也是最彻底的办法.
希望通过本文的介绍,能够使大家对Object类有个大概的了解,编写好自己的equals和clone方法,以适应不同的需要.
分享到:
评论

相关推荐

    Java SE程序 覆盖Object中的方法

    Java SE程序 覆盖Object中的方法Java SE程序 覆盖Object中的方法Java SE程序 覆盖Object中的方法Java SE程序 覆盖Object中的方法Java SE程序 覆盖Object中的方法Java SE程序 覆盖Object中的方法Java SE程序 覆盖...

    JAVA之Object类所有方法

    java.lang.Object下的各种方法

    Java Object类认识

    Java 对Object类的认识和equals()方法和== 的对比

    1.javaObject类.zip

    1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1.javaObject类.zip1....

    java中关键字Object详解

    其次,Object类是实现Java泛型的基础,Java中的泛型是一种提供给Java程序员们使用的编程技术,它允许程序员们编写出使用一种或多种类型作为参数、返回结果或变量的类、接口以及方法,并且可以在运行时进行类型安全性...

    java-object类

    java-object类java-object类java-object类java-object类java-object类java-object类java-object类java-object类java-object类java-object类

    object中toString方法简介_动力节点Java学院整理.doc

    Object类在Java里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能有一个,JAVA为了组织这个类组织得比较...

    Java的Object类讲解案例代码 equals()、hashCode()、finalize()、clone()、wait()

    Object类是所有Java类的根类,它定义了一些常用的方法,例如equals()、hashCode()、toString()等。本案例代码将详细展示Object类的使用方法,并提供一些实际场景下的案例,以帮助开发者更好地理解和运用这些方法。 ...

    java中的Object类[文].pdf

    java中的Object类[文].pdf

    Java中的Object类、Set接口(学习小结)

    Object类是Java中所有类的基类。Java中所有的类都是直接或间接继承Object类。 Object类的引用数据类型变量可以保存Java中任意数据类型空间的首地址。 Object类中规定了一些方法,可供子类使用。 (1).String ...

    Java JSON与Object互转源代码

    高效的JSON与Object互转的工具源代码,如果JSON数据未按该工具规定的数据格式转化成对象,将转化成java.util.Map...缺点:对于集合(Collection,非Map)类数据结构,不能在集合中包含其他集合对象,但是可以包含数组。

    java之Object类方法技术分享PPT

    主要包含Object类中的getClass()、hashCode()、equals()、toString()方法的使用和作用,还包含一个3D旋转模型,还包含几个常见的面试题的解析,可用作学生每周技术分享或者上台演讲,适用于大学计算机专业相关人士。

    JAVA类源代码Object父类

    绝对正宗的Object父类JAVA源代码,加载到编译器Eclipse和Myeclipse编译器即可直接使用,还在为创建Object父类而烦恼吗,您是否正在寻找Object父类的源代码呢,如果是的话就请敢快动手吧。

    Object-CC++对象库,实现类似于Java的Object类的Object

    【Object-C】C++对象库,实现类似于Java的Object类的Object, (a C++ Object library, implementating an Object similar to Java s Object class,) 文件列表: CMakeLists.txt (1300, 2023-10-16) LibObjClangPlugin...

    java反射实现Object转json

    利用java反射机制实现Object转json.

    Java方法反射调用demo

    Java反射 调用空参方法 调用Object类型参数的方法 调用基本类型参数的方法 调用基本类型数组参数的方法 调用String数组参数的方法 调用Object数组参数的方法 调用私有方法

    详解Java中Object 类的使用.rar

    详解Java中Object 类的使用.rar

    Java Object实例代码

    Java Object实例代码 Java Object知识点分成7部分:对象、继承多态、构造器、类包内外访问权限、各种静态内部类、抽象函数、接口

    Java中的Object类详细介绍

    主要介绍了Java中的Object类详细介绍,本文讲解了Object类的作用、Object类的主要方法、Object类中不能被重写的方法、Object类的equals方法重写实例等内容,需要的朋友可以参考下

Global site tag (gtag.js) - Google Analytics