目录
- Object 类提供的方法
- 方法实例
- clone() 方法
- equals() 方法
- finalize() 方法
- getClass() 方法
- hashCode() 方法
- wait() 方法
- notify() 与 notifyAll() 方法
- toString() 方法
Java的Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
Object 类可以显式继承,也可以隐式继承,以下两种方式是一样的:
// 显式继承: | |
public class Runoob extends Object{ } | |
// 隐式继承: | |
public class Runoob { } |
Object 类提供的方法
方法 | 描述 |
Object() | 构造一个新对象 |
protected Object clone() | 创建并返回一个对象的拷贝 |
boolean equals(Object obj) | 比较两个对象是否相等 |
protected void finalize() | 当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法 |
Class<?> getClass() | 获取对象的运行时对象的类 |
int hashCode() | 获取对象的 hash 值 |
void notify() | 唤醒在该对象上等待的某个线程 |
void notifyAll() | 唤醒在该对象上等待的所有线程 |
String toString() | 返回对象的字符串表示形式 |
void wait() | 让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法 |
void wait(long timeout) | 让当前线程处于等待(阻塞)状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数设置的timeout超时时间 |
void wait(long timeout, int nanos) | 与 wait(long timeout) 方法类似,多了一个 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒 |
方法实例
clone() 方法
protected native Object clone() throws CloneNotSupportedException;
描述:
用于创建并返回一个对象的拷贝。clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存。
参数:
无
返回值:
返回一个对象的拷贝。
注意:
由于 Object 本身没有实现 Cloneable 接口,所以不重写 clone 方法并且进行调用的话会发生 CloneNotSupportedException 异常。
public class Test implements Cloneable { | |
// 声明变量 | |
String name; | |
int likes; | |
// 属性引用的对象 | |
JueJin jueJin; | |
Test() { | |
this.jueJin = new JueJin(); | |
} | |
public static void main(String args[]) { | |
// 创建对象 | |
Test obj1 = new Test(); | |
// 初始化变量 | |
obj1.name = "Runoob"; | |
obj1.likes = 111; | |
obj1.jueJin.name = "掘金"; | |
// 打印输出 | |
System.out.println("obj1 的 name = " + obj1.name); // Runoob | |
System.out.println("obj1 的 likes = " + obj1.likes); // 111 | |
System.out.println("obj1 的 jueJin 的 name = " + obj1.jueJin.name); //掘金 | |
try { | |
// 创建 obj1 的拷贝 | |
Test obj2 = (Test) obj1.clone(); | |
obj2.name = "JueJin"; | |
obj2.likes = 222; | |
obj2.jueJin.name = "稀土掘金"; | |
// 使用 obj2 输出变量 | |
System.out.println(); | |
System.out.println("obj2 的 name = " + obj2.name); // JueJin | |
System.out.println("obj2 的 likes = " + obj2.likes); // 222 | |
System.out.println("obj2 的 jueJin 的 name = " + obj2.jueJin.name); //稀土掘金 | |
System.out.println(); | |
System.out.println("浅拷贝的问题"); | |
System.out.println("obj1 的 name = " + obj1.name); // Runoob | |
System.out.println("obj1 的 likes = " + obj1.likes); // 111 | |
System.out.println("obj1 的 jueJin 的 name = " + obj1.jueJin.name); //稀土掘金 | |
} catch (Exception e) { | |
System.out.println(e); | |
} | |
} | |
} | |
class JueJin { | |
public String name; | |
} | |
// 以上程序执行结果为: | |
// obj1 的 name = Runoob | |
// obj1 的 likes = 111 | |
// obj1 的 jueJin 的 name = 掘金 | |
// obj2 的 name = JueJin | |
// obj2 的 likes = 222 | |
// obj2 的 jueJin 的 name = 稀土掘金 | |
// 浅拷贝的问题 | |
// obj1 的 name = Runoob | |
// obj1 的 likes = 111 | |
// obj1 的 jueJin 的 name = 稀土掘金 |
解析:
由于浅拷贝对对象内属性引用的对象只会拷贝引用地址,所以 obj1 与 obj2 的 jueJin 属性引用的对象指向同一内存地址,所以在 obj2 修改 jueJin 的 name 属性后,obj1 的 jueJin 的 name 属性也发生了变化。
equals() 方法
public boolean equals(Object obj)
描述:
用于比较两个对象是否相等。比较两个对象时,是通过判断两个对象引用指向的是同一个对象,即比较 2 个对象的内存地址是否相等。
参数:
obj -- 要比较的对象。
返回值:
如果两个对象相等返回 true,否则返回 false。
注意:
不同的类重写了 equals() 方法,导致equals() 方法的行为有所不同。但如果子类重写了 equals() 方法,就需要重写 hashCode() 方法,比如 String 类就重写了 equals() 方法,同时也重写了 hashCode() 方法。
public class Test implements Cloneable { | |
public static void main(String args[]) { | |
// 创建两个对象 | |
Object obj1 = new Object(); | |
Object obj2 = new Object(); | |
// 判断 obj1 与 obj2 是否相等 | |
// 不同对象,内存地址不同,不相等,返回 false | |
System.out.println(obj1.equals(obj2)); // false | |
// obj1 赋值给 obj3 | |
// 对象引用,内存地址相同,相等,返回 true | |
Object obj3 = obj1; | |
System.out.println(obj1.equals(obj3)); // true | |
} | |
} | |
// 以上程序执行结果为: | |
// false | |
// true |
finalize() 方法
protected void finalize() throws Throwable { }
描述:
用于实例被垃圾回收器回收的时触发的操作。当 GC (垃圾回收器) 确定不存在对该对象的有更多引用时,对象的垃圾回收器就会调用这个方法。
参数:
无
返回值:
无
public class Test { | |
public static void main(String args[]) { | |
JunJin junJin = new JunJin(); | |
junJin = null; | |
System.gc(); | |
} | |
} | |
class JunJin { | |
protected void finalize() throws Throwable { | |
super.finalize(); | |
System.out.println("对象被回收了"); | |
} | |
} | |
// 以上程序执行结果为: | |
// 对象被回收了 |
getClass() 方法
public final native Class<?> getClass();
描述:
用于获取对象的运行时对象的类。
参数:
无
返回值:
返回对象的类。
public class Test { | |
public static void main(String args[]) { | |
// getClass() with Object | |
Object obj1 = new Object(); | |
System.out.println("obj1 的类为: " + obj1.getClass()); | |
// getClass() with String | |
String obj2 = new String(); | |
System.out.println("obj2 的类为: " + obj2.getClass()); | |
// getClass() with ArrayList | |
ArrayList<Integer> obj3 = new ArrayList<>(); | |
System.out.println("obj3 的类为: " + obj3.getClass()); | |
} | |
} | |
// 以上程序执行结果为: | |
// obj1 的类为: class java.lang.Object | |
// obj2 的类为: class java.lang.String | |
// obj3 的类为: class java.util.ArrayList |
hashCode() 方法
public native int hashCode();
描述:
用于获取对象的 hash 值。
参数:
无
返回值:
返回对象哈希值,是一个整数,表示在哈希表中的位置。
public class Test { | |
public static void main(String args[]) { | |
// Object 使用 hashCode() | |
Object obj1 = new Object(); | |
// obj1 赋值给 obj2 | |
Object obj2 = obj1; | |
// 判断两个对象是否相等 | |
System.out.println(obj1.equals(obj2)); // true | |
// 获取 obj1 与 obj2 的哈希值 | |
System.out.println("对象相等则hashCode一定相等"); | |
System.out.println(obj1.hashCode()); // 225534817 | |
System.out.println(obj2.hashCode()); // 225534817 | |
} | |
} | |
// 以上程序执行结果为: | |
// true | |
// 对象相等则hashCode一定相等 | |
// 692404036 | |
// 692404036 |
wait() 方法
// 该方法有以下几种语法格式: | |
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 |
描述:
让当前线程进入等待状态。
参数:
- timeout -- 等待超时时间(以毫秒为单位)。如果 timeout 参数为 0,则不会超时,会一直进行等待,类似于 wait() 方法。如果阻塞的时间超过该参数时间,会唤醒线程。
- nanos -- 额外时间(以纳秒为单位,范围是 0-999999)。如果设置该时间,超时的时间还需要加上 nanos 纳秒。
返回值:
无
注意:
- 当前线程必须是此对象的监视器所有者,否则还是会发生 IllegalMonitorStateException 异常。
- 如果当前线程在等待之前或在等待时被任何线程中断,则会抛出 InterruptedException 异常。
- 如果传递的参数不合法,则会抛出 IllegalArgumentException 异常。
notify() 与 notifyAll() 方法
public final native void notify();
描述:
用于唤醒一个在此对象监视器上等待的线程。如果所有的线程都在此对象上等待,那么只会选择一个线程,选择是任意性的,并在对实现做出决定时发生。
参数:
无
返回值:
无
public final native void notifyAll();
描述:
用于唤醒在该对象上等待的所有线程。notifyAll() 方法跟 notify() 方法的区别在于 notifyAll() 方法唤醒在此对象监视器上等待的所有线程,notify() 方法是一个线程。
参数:
无
返回值:
无
public class Test { | |
// 声明一个同步列表 | |
private List synchedList; | |
/** | |
* 构造方法 | |
*/ | |
public Test() { | |
// 创建一个同步列表 | |
synchedList = Collections.synchronizedList(new LinkedList()); | |
} | |
/** | |
* 删除列表中的元素 | |
* @return 删除的元素 | |
* @throws InterruptedException | |
*/ | |
public String removeElement() throws InterruptedException { | |
synchronized (synchedList) { | |
// 列表为空就等待 | |
while (synchedList.isEmpty()) { | |
System.out.println("列表是空的..."); | |
System.out.println("线程 " + Thread.currentThread().getName() + " 将开始等待..."); | |
synchedList.wait(); | |
System.out.println("线程 " + Thread.currentThread().getName() + " 等待结束!"); | |
} | |
// 删除元素 | |
String element = (String) synchedList.remove(0); | |
// 返回删除的元素 | |
return element; | |
} | |
} | |
/** | |
* 添加元素到列表 | |
* @param element 要添加的元素 | |
*/ | |
public void addElement(String element) { | |
synchronized (synchedList) { | |
// 添加一个元素,并通知元素已存在 | |
synchedList.add(element); | |
System.out.println("添加了新元素:'" + element + "'"); | |
synchedList.notify(); | |
System.out.println("notify 已调用,唤醒 synchedList 上等待的任意一个线程!"); | |
//synchedList.notifyAll(); | |
//System.out.println("notifyAll 已调用,唤醒 synchedList 上等待的所有线程!"); | |
} | |
System.out.println("添加元素完成..."); | |
} | |
/** | |
* main 函数 | |
* @param args | |
*/ | |
public static void main(String args[]) { | |
final Test demo = new Test(); | |
Runnable runA = new Runnable() { | |
public void run() { | |
try { | |
// 删除 synchedList 中的一个元素并输出 | |
String item = demo.removeElement(); | |
System.out.println("删除了元素 " + item); | |
} catch (InterruptedException ix) { | |
System.out.println("中断的异常!"); | |
} catch (Exception x) { | |
System.out.println("Exception thrown."); | |
} | |
} | |
}; | |
Runnable runB = new Runnable() { | |
// 执行添加元素操作,并开始循环 | |
public void run() { | |
demo.addElement("Hello!"); | |
} | |
}; | |
try { | |
// 创建线程 threadA1 并开始执行 | |
Thread threadA1 = new Thread(runA, "Google"); | |
threadA1.start(); | |
// 当前执行 main 方法的线程休眠 | |
Thread.sleep(500); | |
// 创建线程 threadA2 并开始执行 | |
Thread threadA2 = new Thread(runA, "Runoob"); | |
threadA2.start(); | |
// 当前执行 main 方法的线程休眠 | |
Thread.sleep(500); | |
// 创建线程 threadB 并开始执行 | |
Thread threadB = new Thread(runB, "Taobao"); | |
threadB.start(); | |
// 当前执行 main 方法的线程休眠 | |
Thread.sleep(1000); | |
// 中断 threadA1 线程 | |
threadA1.interrupt(); | |
// 中断 threadA2 线程 | |
threadA2.interrupt(); | |
} catch (InterruptedException x) { | |
System.out.println(x); | |
} | |
} | |
} |
使用 notify() 方法唤醒线程时,可以看到 Google 线程的等待被唤醒了,但 Runoob 线程的等待最终没有被唤醒,输出如下:
列表是空的...
线程 Google 将开始等待...
列表是空的...
线程 Runoob 将开始等待...
添加了新元素:'Hello!'
notify 已调用,唤醒 synchedList 上等待的任意一个线程!
添加元素完成...
线程 Google 等待结束!
删除了元素 Hello!
中断的异常!
使用 notifyAll() 方法唤醒线程时,可以看到 Runoob 与 Google 线程的等待都被唤醒了,但 Runoob 线程唤醒后将集合中的元素删除了,所以集合再次变为空的,Google 就再次进入了等待状态,输出如下:
列表是空的...
线程 Google 将开始等待...
列表是空的...
线程 Runoob 将开始等待...
添加了新元素:'Hello!'
notifyAll 已调用,唤醒 synchedList 上等待的所有线程!
添加元素完成...
线程 Runoob 等待结束!
删除了元素 Hello!
线程 Google 等待结束!
列表是空的...
线程 Google 将开始等待...
中断的异常!
注意:
notify() 与 notifyAll() 方法只能被作为此对象监视器的所有者的线程来调用。如果当前线程不是此对象监视器的所有者的话会抛出 IllegalMonitorStateException 异常。
一次只能有一个线程拥有对象的监视器。一个线程要想成为对象监视器的所有者,可以使用以下 3 种方法:
- 执行对象的同步实例方法
- 使用 synchronized 内置锁
- 对于 Class 类型的对象,执行同步静态方法
toString() 方法
public String toString() | |
描述:
用于返回对象的字符串表示形式。
参数:
无
返回值:
返回对象的字符串表示形式。默认返回格式:对象的 class 名称 + @ + hashCode 的十六进制字符串。
public class Test { | |
public static void main(String[] args) { | |
// toString() with Object | |
Object obj1 = new Object(); | |
System.out.println(obj1.toString()); | |
Object obj2 = new Object(); | |
System.out.println(obj2.toString()); | |
Object obj3 = new Object(); | |
System.out.println(obj3.toString()); | |
} | |
} | |
// 以上程序执行结果为: | |
// java.lang.Object@29453f44 | |
// java.lang.Object@5cad8086 | |
// java.lang.Object@6e0be858 |