Object类
Object类是Java中所有类的父类,所有的类都是继承自Object或其子类。即使自己编写的类没有继承任何类,也会在编译的时候默认添加继承Object类。
package java.lang;
import jdk.internal.vm.annotation.IntrinsicCandidate;
public class Object {
@IntrinsicCandidate
public Object() {}
@IntrinsicCandidate
public final native Class<?> getClass();
@IntrinsicCandidate
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
@IntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
@IntrinsicCandidate
public final native void notify();
@IntrinsicCandidate
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
@Deprecated(since="9")
protected void finalize() throws Throwable { }
}
Object类既然是都有类的父类,那么所有类都能够使用Object类中的方法,同样的Object类的设计也是提取所有类都可能使用的方法。我们来分析一下这些方法:
public final native Class<?> getClass();
这个方法主要是用于获取类对象,在反射的时候很常用,这是一个native方法。
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
这两个方法是用于判断对象是否是同一个对象设计的。hashCode值用于标识一个特定对象,equals默认判断两个对象的地址是否相同。如果要根据对象的某些属性相同就判定是同一个对象就可以重写equals方法和hashCode方法。
protected native Object clone() throws CloneNotSupportedException;
clone方法用于复制一个对象
@IntrinsicCandidate
public final native void notify();
@IntrinsicCandidate
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
wait和notify方法与并发有关。
@Deprecated(since="9")
protected void finalize() throws Throwable { }
这是一个废弃的方法,作用是对象被回收的时候会回调这个方法。
浅拷贝和深拷贝
对象克隆就会遇到浅拷贝和深拷贝问题。
- 浅拷贝:只复制对象本身,对象中的引用还是指向原来的对象
- 深拷贝:复制对象及对象中的引用指向的对象都被复制
- clone重写需要实现Clonable接口,否则会报异常
并不是Clonable中也有一个clone方法,Clonable只是一个标记型的接口,其中没有任何方法,但是需要实现Clonable接口才能够重写Object中的clone方法,标志着这个类的对象可以复制。
接下来是一个验证浅拷贝和深拷贝的demo
class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Cat cat = new Cat();
Dog dog = new Dog();
Animal animal = new Animal(cat,dog);
Animal animal1 = (Animal) animal.clone();
System.out.println(cat);
System.out.println(dog);
System.out.println(animal1.cat);
System.out.println(animal1.dog);
}
}
class Animal implements Cloneable {
public Cat cat;
public Dog dog;
public Animal() {
}
public Animal(Cat cat, Dog dog) {
this.cat = cat;
this.dog = dog;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// Animal result = new Animal();
// result.cat = (Cat) this.cat.clone();
// result.dog = (Dog) this.dog.clone();
// return result;
return super.clone();
}
}
class Cat implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Dog implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
这里Animal类中包含两个对象,一个是Cat对象,一个是Dog对象。如果代码是现在这样,是属于浅拷贝,可以看到Animal类只是调用了父类Object类的clone方法,相当于只是复制了Animal对象自己,他所包含的cat和dog还是指向的原来的对象,打印如下:
Cat@3b07d329
Dog@41629346
Cat@3b07d329
Dog@41629346
animal和animal1中的cat和dog指向的是同一个对象。
如果将Animal中clone方法中的注释代码进行替换,则打印结果为:
Cat@3b07d329
Dog@41629346
Cat@404b9385
Dog@6d311334
这样Animal中所包含的对象也被拷贝了,是深拷贝。
还有一种深拷贝的方式是将对象序列化后再反序列化创建对象。