我们都知道:在Java中,所有的类都继承了Object这个基类,并且大家都知道,Object有几个比较通用的方法,如equals(),clone(),toString(),我们需要在使用它们的时候进行覆写,今天,我们就具体的探究下这几个方法。
void registerNatives()
这是个Native方法,在静态块中调用,其目的是将hashCode,wait,notify,notifyAll和clone方法注册到本地。
Class<?> getClass()
同样是个Native方法,获取对象的Class。
int hashCode()
一个对象在同一个进程被多次调用,但是它的哈希码仍然应该是相同的。但是,当同一个对象在不同进程中执行,则哈希码有可能不同。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()来进行对象终结对象的判断。