目录
Java 中有一个比较特殊的类,就是 Object 类,它是所有类的父类。如果一个类没有使用 extends 关键字明确标识继承另外一个类,那么这个类就是默认继承 Object类。因此,Object 类是 Java 类层中最高层的类,是所有类的超类。换句话说, Java 中任何一个类都是它的子类。由于所有类都是 Object 衍生出来的,所以 Objetc 类中的方法适用于所有类。
public class Person { // 当没有指定父类,会默认 Object 类为其父类
}
等价于
public class Person extends Object{
}
一、Object 类的方法
序号 | 方法 & 描述 |
---|---|
1 | protected Object clone() 创建并返回一个对象的拷贝 |
2 | boolean equals(Object obj) 比较两个对象是否相等 |
3 | protected void finalize() 当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法。 |
4 | Class<?> getClass() 获取对象的运行时对象的类 |
5 | int hashCode() 获取对象的 hash 值 |
6 | void notify() 唤醒在该对象上等待的某个线程 |
7 | void notifyAll() 唤醒在该对象上等待的所有线程 |
8 | String toString() 返回对象的字符串表示形式 |
9 | void wait() 让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 |
10 | void wait(long timeout) 让当前线程处于等待(阻塞)状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数设置的timeout超时时间。 |
11 | void wait(long timeout, int nanos) 与 wait(long timeout) 方法类似,多了一个 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。 |
二、示例
2.1、clone()
创建并返回一个对象的拷贝。
clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,相对应的深拷贝则会连引用的对象也重新创建。
public class Main implements Cloneable {
// 声明变量
String name;
int age;
public static void main(String[] args) {
// 创建对象
Main obj1 = new Main();
// 初始化变量
obj1.name = "张三";
obj1.age = 28;
// 打印输出
System.out.println("obj1 姓名:"+obj1.name +" 年龄"+obj1.age ); // 张三 28
try {
// 创建 obj1 的拷贝
Main obj2 = (Main) obj1.clone();
// 使用 obj2 输出变量
System.out.print("obj2 姓名:"+obj2.name + " 年龄"+ obj2.age); // 张三
} catch (Exception e) {
System.out.println(e);
}
}
}
控制台显示
obj1 姓名:张三 年龄28
obj2 姓名:张三 年龄28
2.2、equals()
用于比较两个对象是否相等。
equals() 方法比较两个对象,是判断两个对象引用指向的是同一个对象,即比较 2 个对象的内存地址是否相等。
public class Main {
public static void main(String[] args) {
// Object 类使用 equals() 方法
// 创建两个对象
Object obj1 = new Object();
Object obj2 = new Object();
// 判断 obj1 与 obj2 是否相等
// 不同对象,内存地址不同,不相等,返回 false
System.out.println(obj1.equals(obj2)); // false
// obj1 赋值给 obj3
// String 重写了 equals() 方法
// 对象引用,内存地址相同,相等,返回 true
Object obj3 = obj1;
System.out.println(obj1.equals(obj3)); // true
}
}
2.3、finalize()
用于实例被垃圾回收器回收的时触发的操作。
当 GC (垃圾回收器) 确定不存在对该对象的有更多引用时,对象的垃圾回收器就会调用这个方法。
public class FinalizeTest {
public static void main(String[] args) {
//多造点垃圾,让垃圾回收器启动
for(int i = 0; i < 10000000; i++) {
//创建对象
Person p = new Person();
//把Person对象变成垃圾
p = null;
}
}
}
class Person{
//重写finalize()方法
//Person类型的对象被垃圾回收器回收的时候,垃圾回收器负责调用p.finalize();
protected void finalize() throws Throwable {
System.out.println("即将被销毁!");
}
}
2.4、getClass()
Object getClass() 方法用于获取对象的运行时对象的类。
import java.util.ArrayList;
import java.util.GregorianCalendar;
public class Main extends GregorianCalendar {
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());
// 创建 RunoobTest 类的对象
Main m = new Main();
System.out.println("Main 的类为: " +m.getClass());
}
}
控制台显示
obj1 的类为: class java.lang.Object
obj2 的类为: class java.lang.String
obj3 的类为: class java.util.ArrayList
Main 的类为: class com.day03.Main
2.5、hashCode()
Object hashCode() 方法用于获取对象的 hash 值。
public class Main{
public static void main(String[] args) {
// Object 使用 hashCode()
Object obj1 = new Object();
System.out.println(obj1.hashCode());
Object obj2 = new Object();
System.out.println(obj2.hashCode());
Object obj3 = new Object();
System.out.println(obj3.hashCode());
}
}
控制台显示
1023487453
1651191114
1586600255
2.6、notify() 与wait()
Object notify() 方法用于唤醒一个在此对象监视器上等待的线程。
如果所有的线程都在此对象上等待,那么只会选择一个线程,选择是任意性的,并在对实现做出决定时发生。
Object wait() 方法让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
等待线程
public class WaitThread implements Runnable{
Object lock;
public WaitThread(Object lock){
this.lock = lock;
}
public void run() {
String threadName = Thread.currentThread().getName();
synchronized (lock){
System.out.println(threadName + "开始进入同步代码块区域");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "准备离开同步代码块区域");
}
}
}
唤醒线程
public class NotifyThread implements Runnable{
Object lock;
public NotifyThread(Object lock){
this.lock = lock;
}
public void run() {
String threadName = Thread.currentThread().getName();
synchronized (lock){
System.out.println(threadName + "开始进入同步代码块区域");
lock.notify();
try {
System.out.println(threadName + "业务处理开始");
// 暂停 2s 表示业务处理
Thread.sleep(2000);
System.out.println(threadName + "业务处理结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "准备离开同步代码块区域");
//lock.notify();放在这一行唤醒,效果一样
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "退出同步代码块后续操作");
}
}
主程序
public class Main {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread waitThread = new Thread(new WaitThread(lock), "waitThread");
Thread notifyThread = new Thread(new NotifyThread(lock), "notifyThread");
waitThread.start();
Thread.sleep(1000);
notifyThread.start();
}
}
控制台显示
waitThread开始进入同步代码块区域
notifyThread开始进入同步代码块区域
notifyThread业务处理开始
notifyThread业务处理结束
notifyThread准备离开同步代码块区域
waitThread准备离开同步代码块区域
notifyThread退出同步代码块后续操作
2.7、notifyAll() 与wait()
Object notifyAll() 方法用于唤醒在该对象上等待的所有线程。
等待线程
public class WaitThread implements Runnable{
Object lock;
public WaitThread(Object lock){
this.lock = lock;
}
public void run() {
String threadName = Thread.currentThread().getName();
synchronized (lock){
System.out.println(threadName + "开始进入同步代码块区域");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "准备离开同步代码块区域");
}
}
}
唤醒线程
public class NotifyThread implements Runnable{
Object lock;
public NotifyThread(Object lock){
this.lock = lock;
}
public void run() {
String threadName = Thread.currentThread().getName();
synchronized (lock){
System.out.println(threadName + "开始进入同步代码块区域");
lock.notifyAll();
try {
System.out.println(threadName + "业务处理开始");
// 暂停 2s 表示业务处理
Thread.sleep(2000);
System.out.println(threadName + "业务处理结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "准备离开同步代码块区域");
//lock.notifyAll();放在这一行唤醒,效果一样
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "退出同步代码块后续操作");
}
}
主程序
public class Test2 {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread waitThread = new Thread(new WaitThread(lock), "waitThread");
Thread waitThread2 = new Thread(new WaitThread(lock), "waitThread2");
Thread notifyThread = new Thread(new NotifyThread(lock), "notifyThread");
waitThread.start();
waitThread2.start();
Thread.sleep(1000);
notifyThread.start();
}
}
控制台显示
waitThread开始进入同步代码块区域
waitThread2开始进入同步代码块区域
notifyThread开始进入同步代码块区域
notifyThread业务处理开始
notifyThread业务处理结束
notifyThread准备离开同步代码块区域
waitThread准备离开同步代码块区域
waitThread2准备离开同步代码块区域
notifyThread退出同步代码块后续操作
2.8、toString()
Object toString() 方法用于返回对象的字符串表示形式
public class Main {
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@3d012ddd
java.lang.Object@626b2d4a
java.lang.Object@5e91993f