我们都知道:在Java中,所有的类都继承了Object这个基类,并且大家都知道,Object有几个比较通用的方法,如equals(),clone(),toString(),我们需要在使用它们的时候进行覆写,今天,我们就具体的探究下这几个方法。
void registerNatives()
这是个Native方法,在静态块中调用,其目的是将hashCode,wait,notify,notifyAll和clone方法注册到本地。
Class<?> getClass()
同样是个Native方法,获取对象的Class。
int hashCode()
Native方法,生成哈希码,其中注意三点
-
一个对象在同一个进程被多次调用,但是它的哈希码仍然应该是相同的。但是,当同一个对象在不同进程中执行,则哈希码有可能不同。JavaDoc原文如下
Whenever it is invoked on the same object more than once during an execution of a Java application, the {@code hashCode} method must consistently return the same integer, provided no information used in {@code equals} comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
-
如果两个对象通过equals()比较返回true,那么它们的哈希码应该相同。
-
如果两个对象通过equals()比较返回false,那么它们的哈希码应该不同。
boolean equals(Object obj)
这恐怕使我们最常用的方法之一了,我们在实际应用中,也经常遇到什么时候用equals(),什么时候用==的问题。一般来说,基本数据类型用==,因为这样可以直接比较它们的值,但是复合数据类型如果我们用==的话,那么实际上我们比较的就是它们的引用了,除非它们指向的是同一个对象,否则它们不可能相等,因此我们比较符合数据类型一般用equals(),并且我们应该覆写equals(),这是因为Object的equals()方法默认的也是用==进行判定:
public boolean equals(Object obj) { return (this == obj); }
我们再来看看我们经常用的String是如何覆写equals()方法的:
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false;}
在这里还有一个很有趣的问题,请看下面的例子
String s1 = "String"; String s2 = "String"; System.out.println("The result is " + s1.equals(s2));
你会发现返回值为True,这个就和我们上面讲的不一样了,按照我们上面的讲解,这时候应该返回false才对。其实是这样的,因为JVM中会维护一个字符串池,如果池中已经有包含此对象的字符串的时候,那么它就会返回池中的字符串(当然如果你new一个新的String对象的话就另当别论。)所以这个时候返回的是true。
###Object clone() Native方法,我们一般用它来复制一个对象,并且用clone()可以实现深复制(将所有需要复制的对象都复制了一遍,而不单单是用引用指向原来的对象。)示例如下:
public class Animal implements Cloneable { private int height; private int age; public Animal(int height, int age){ this.height = height; this.age = age; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Animal{" + "height=" + height + ", age=" + age + '}'; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}public class People implements Cloneable { private int height; private int age; private Animal a; public People(int height, int age,Animal a){ this.height = height; this.age = age; this.a = a; } @Override public Object clone() throws CloneNotSupportedException { People p = (People) super.clone(); p.a = (Animal) a.clone(); return p; } @Override public String toString() { return "People{" + "height=" + height + ", age=" + age + ", a=" + a + '}'; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void setAnimalAge(int a) { this.a.setAge(5); }}
接下来我们这样调用:
Animal a1 = new Animal(100,3); People p1 = new People(173,24,a1); People p2 = (People) p1.clone(); p2.setAge(26); p2.setHeight(181); p2.setAnimalAge(6); System.out.println(p1.toString()); System.out.println(p2.toString());
这样我们就完成深复制了。
String toString()
最常用的方法,我们一般用它获取对象成员变量的值。Object的默认实现:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());}
void notify(),void notifyAll()
Native方法,多线程时应用,通知其他线程等待结束。
void wait(long),void wait(long,int),void wait()
Native方法,通知线程等待。
void finalize()
垃圾回收。当JVM判断一个对象可以被垃圾回收时,那么JVM会调用finalize()方法,但是记住,它只能调用一次(所以如果你想这个对象不被垃圾清除的话,你就要在这里面做点事情了),但是一般你不能依赖在这里做垃圾回收的工作,在《Java编程思想》中说明了有关finalize()的一个用法,那就是通过finalize()来进行对象终结对象的判断。