Java 中的 Object
类是所有类的根类,它位于 java.lang
包中。所有其他类都直接或间接地继承自 Object
类。以下是关于 Object
类的一些详解:
/**
* native 方法,用于返回当前运行时对象的 Class 对象,使用了 final 关键字修饰,故不允许子类重写。
*/
public final native Class> getClass()
/**
* native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。
*/
public native int hashCode()
/**
* 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。
*/
public boolean equals(Object obj)
/**
* native 方法,用于创建并返回当前对象的一份拷贝。
*/
protected native Object clone() throws CloneNotSupportedException
/**
* 返回类的名字实例的哈希码的 16 进制的字符串。建议 Object 所有的子类都重写这个方法。
*/
public String toString()
/**
* native 方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
*/
public final native void notify()
/**
* native 方法,并且不能重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
*/
public final native void notifyAll()
/**
* native方法,并且不能重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。
*/
public final native void wait(long timeout) throws InterruptedException
/**
* 多了 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。。
*/
public final void wait(long timeout, int nanos) throws InterruptedException
/**
* 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
*/
public final void wait() throws InterruptedException
/**
* 实例被垃圾回收器回收的时候触发的操作
*/
protected void finalize() throws Throwable { }
getClass()
方法返回对象的运行时类,即对象所属的类的 Class 对象。Class 对象提供了许多反射操作,如获取类名、获取字段和方法信息等。
返回类型:
getClass()
方法返回的是 Class
类型的对象,它是 Java 反射机制中的一个重要类。用途:
getClass()
方法通常用于获取对象的运行时类型信息,包括类名、父类、接口等信息。通过 Class
对象,可以进行许多反射操作,如获取字段和方法信息、创建新的对象实例等。示例:
下面是一个简单的示例,展示如何使用 getClass() 方法获取对象的类名:Object obj = new String("Hello, World!");
Class> cls = obj.getClass();
System.out.println(cls.getName());
// 输出:java.lang.String
上述代码中,我们首先创建了一个 String 类型的对象,并将其赋给一个 Object 类型的引用变量 obj。然后,通过 getClass() 方法获取 obj 对象的运行时类型信息,即 String 类型的 Class 对象。最后,通过 getName() 方法获取该类的名称并输出。 需要注意的是,getClass()
方法返回的是对象的运行时类型,而不是编译时类型。这意味着,在多态的情况下,可能会返回不同的 Class
对象。如果需要获取编译时类型的信息,可以使用 instanceof
运算符。
hashCode()
方法返回对象的哈希码值,它用于在哈希表等数据结构中快速查找对象。默认情况下,hashCode()
方法返回的是对象的内存地址的整数表示。如果重写了 equals()
方法,通常也需要同时重写 hashCode()
方法,以保持一致性。
返回类型:
hashCode()
方法返回的是一个 int
类型的哈希码值。用途:
HashMap
、HashSet
等。它被用来快速定位对象存储的位置,以提高查找、插入和删除操作的性能。equals()
方法返回 true
,那么它们的哈希码必须相等。因此,重写 equals()
方法时通常也需要同时重写 hashCode()
方法,以保持这个约定。默认实现:
Object
类中的 hashCode()
方法的默认实现是根据对象的内存地址计算得到的,即每个对象的哈希码都是唯一的。这在大多数情况下是不可接受的,因为我们希望具有相等属性的对象具有相同的哈希码。hashCode()
方法,以便相等的对象具有相同的哈希码。通常,可以使用对象的字段来计算哈希码,确保相等的对象生成相同的哈希码。重写规则:
equals()
方法,通常也需要同时重写 hashCode()
方法。hashCode()
方法时,应该保证满足以下规则:
equals()
方法判断为相等,那么它们的哈希码必须相等。equals()
方法可能返回 false
。下面是一个示例,展示如何重写 hashCode()
方法:
public class MyClass {
private int id;
private String name;
// 构造方法、getter 和 setter 省略
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
MyClass other = (MyClass) obj;
return id == other.id && Objects.equals(name, other.name);
}
}
在上述示例中,根据类的字段 id
和 name
来计算哈希码,并在 equals()
方法中比较这些字段的值。这样,具有相同 id
和 name
字段值的对象将具有相同的哈希码。
equals()
方法用于判断两个对象是否相等。默认情况下,equals()
方法比较的是两个对象的引用是否相等,即它们是否指向同一个内存地址。可以通过重写 equals()
方法来改变对象的相等比较方式。
方法签名:
Object
类中,equals()
方法的签名为 public boolean equals(Object obj)
。默认实现:
Object
类中,equals()
方法的默认实现是使用 ==
运算符来比较两个对象的引用是否相同,即判断对象的内存地址是否一致。equals()
方法,它将和 ==
运算符具有相同的行为。这意味着只有当两个对象引用指向内存中的同一块区域时,equals()
方法才会返回 true
。重写规则:
equals()
方法。equals()
方法时,应该保证满足以下几个约定:
true
。true
,那么 y.equals(x) 也应该返回 true
。true
并且 y.equals(z) 也返回 true
,那么 x.equals(z) 也应该返回 true
。false
。示例:
下面是一个简单的示例,展示如何重写equals()
方法: public class MyClass {
private int id;
private String name;
// 构造方法、getter 和 setter 省略
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
MyClass other = (MyClass) obj;
return id == other.id && Objects.equals(name, other.name);
}
}
在上述示例中,根据类的字段 id
和 name
来判断两个对象是否相等。这样,具有相同 id
和 name
字段值的对象将被视为相等。
总之,equals()
方法用于判断两个对象是否相等,但默认情况下它比较的是对象的引用。因此,通常根据具体的业务需求来重写 equals()
方法,以便根据对象的内容来确定相等性。
clone()
方法用于创建并返回当前对象的副本。这个方法执行的是浅拷贝(shallow copy),也就是复制对象的字段值。下面是关于 clone()
方法的详解:
使用方法:
要使用clone()
方法,首先需要确保被克隆的类实现了 Cloneable
接口。该接口是一个标记接口,意味着它没有任何方法,只是用于标识能够进行克隆的类。然后,在要进行克隆的类中重写 clone()
方法,并在方法内部调用父类的 clone()
方法进行克隆。浅拷贝:
默认情况下,clone()
方法执行的是浅拷贝,即只复制对象的字段值。如果对象包含其他引用类型的字段,那么克隆后的新对象和原对象将共享这些引用类型的字段。如果需要实现深拷贝(deep copy),即复制对象及其引用类型字段的内容,可以在 clone()
方法中手动处理这些引用类型字段的克隆。返回类型:
clone()
方法的返回类型是 Object
,因此在使用时需要进行类型转换。通常,将返回的 Object
对象转换为克隆的具体类型。克隆方法的保护性质:
clone()
方法在 Object
类中被声明为受保护的,这意味着只能在当前类及其子类中访问该方法。如果一个类没有实现 Cloneable
接口或者尝试在其他类中调用该类的 clone()
方法,将会抛出 CloneNotSupportedException
异常。 需要注意的是,虽然 clone()
方法提供了一种对象的复制方式,但它并不是推荐使用的方式。因为它存在一些问题,如对于可变对象的处理、构造函数的绕过以及性能开销等。更好的方式是使用拷贝构造函数或工厂方法来创建对象的副本,以实现更精确的控制和避免潜在的问题。
toString()
方法是 Object
类中的一个方法,用于返回表示对象的字符串表示。
方法签名:
Object
类中,toString()
方法的签名为 public String toString()
。默认实现:
Object
类中,toString()
方法的默认实现返回一个包含类名和对象的哈希码的字符串,格式为 类名@哈希码
。toString()
方法。重写规则:
toString()
方法。toString()
方法时,应该返回一个包含对象信息的字符串,以便能够描述对象的状态和属性。toString()
方法的目的是为了提供可读性高、易于理解和调试的字符串表示。示例:
下面是一个示例,展示如何重写 toString()
方法:
public class MyClass {
private int id;
private String name;
// 构造方法、getter 和 setter 省略
@Override
public String toString() {
return "MyClass{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
在上述示例中,根据类的字段 id
和 name
来返回一个包含对象信息的字符串表示。通过重写 toString()
方法,我们可以得到类似于 "MyClass{id=1, name='John'}"
的字符串表示。
总之,toString()
方法用于返回对象的字符串表示,以便能够描述对象的状态和属性。默认情况下,它返回一个不太有用的字符串,因此通常需要根据具体的业务需求来重写 toString()
方法,以提供更有意义的字符串表示。
notify()
方法是 Object
类中的一个方法,用于唤醒正在等待该对象的线程;notifyAll()
方法是 Object
类中的一个方法,用于唤醒正在等待该对象的所有线程。
方法签名:
Object
类中,notify()
方法的签名为 public final void notify()
。Object
类中,notifyAll()
方法的签名为 public final void notifyAll()
。使用条件:
notify()
、notifyAll()
方法必须在同步块或同步方法中调用,并且只能由持有对象监视器(锁)的线程来调用。notify()、notifyAll()
方法将会抛出 IllegalMonitorStateException
异常。功能:
notify()/notifyAll()
方法时,它将唤醒正在等待该对象的线程中的 某一/全部 线程。被唤醒的线程将从等待状态转变为可运行状态,并且与其他线程一起竞争对象的监视器锁。notify()
,notifyAll()
方法不会立即释放对象的监视器锁,而是在当前线程执行完同步代码块或同步方法后才会释放。示例:
下面是一个示例,展示如何使用 wait()
和 notify()
、notifyAll()
方法进行线程间的通信:
public class MyClass {
public synchronized void doSomething() {
System.out.println("Thread A: Doing something...");
try {
wait(); // 线程 A 等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread A: Resumed!");
}
public synchronized void notifyThread() {
notify(); // 唤醒等待的线程
//notifyAll(); // 唤醒全部等待的线程
}
}
public class Main {
public static void main(String[] args) {
MyClass myObject = new MyClass();
Thread threadA = new Thread(() -> myObject.doSomething());
Thread threadB = new Thread(() -> myObject.notifyThread());
threadA.start(); // 启动线程 A
threadB.start(); // 启动线程 B
}
}
在上述示例中,线程 A 调用了 doSomething()
方法后进入等待状态,并通过 wait()
方法释放了对象的监视器锁。然后,线程 B 调用了 notifyThread()
方法,唤醒了线程 A,并让线程 A 重新获得对象的监视器锁并继续执行。
总之,notify()
/ notifyAll()
方法用于唤醒正在等待该对象的线程中的 某一/全部 线程,让它从等待状态转变为可运行状态。使用 notify()、
notifyAll()
方法需要注意同步块或同步方法的使用,并且调用 notify()
、
notifyAll()
方法的线程必须持有对象的监视器锁。
wait()
方法: wait()
方法是 Object
类中的一个方法,用于将当前线程置于等待状态,直到其他线程调用了该对象的 notify()
或 notifyAll()
方法来唤醒它。以下是关于 wait()
方法的详解:
方法签名:
Object
类中,wait()
方法有多个重载形式,其中最常用的签名为 public final void wait()
。使用条件:
wait()
方法必须在同步块或同步方法中调用,并且只能由持有对象监视器(锁)的线程来调用。wait()
方法将会抛出 IllegalMonitorStateException
异常。功能:
wait()
方法时,它会使当前线程进入等待状态,释放对象的监视器锁,直到其他线程调用了该对象的 notify()
或 notifyAll()
方法来唤醒它。示例:同notify()、notifyAll()方法事例
总之,wait()
方法用于将当前线程置于等待状态,直到其他线程调用了该对象的 notify()
或 notifyAll()
方法来唤醒它。使用 wait()
方法需要注意同步块或同步方法的使用,并且调用 wait()
方法的线程必须持有对象的监视器锁。
wait(long timeout)
方法:wait(long timeout)
方法是 Object
类中的一个重载方法,用于将当前线程置于等待状态,直到其他线程调用了该对象的 notify()
、notifyAll()
或指定的超时时间过去。以下是关于 wait(long timeout)
方法的详解:
方法签名:
Object
类中,wait(long timeout)
方法的签名为 public final void wait(long timeout) throws InterruptedException
。使用条件:
wait(long timeout)
方法必须在同步块或同步方法中调用,并且只能由持有对象监视器(锁)的线程来调用。wait(long timeout)
方法将会抛出 IllegalMonitorStateException
异常。功能:
wait(long timeout)
方法时,它会使当前线程进入等待状态,释放对象的监视器锁,并等待指定的时间。notify()
或 notifyAll()
方法唤醒,或者等待超时时间到达后自动恢复执行。notify()
或 notifyAll()
方法被调用,且等待时间还未到达,线程将被唤醒并继续执行。示例:
下面是一个示例,展示如何使用 wait(long timeout)
方法进行线程间的通信和超时等待:
public class MyClass {
public synchronized void doSomething() {
System.out.println("Thread A: Doing something...");
try {
wait(2000); // 线程 A 最多等待 2 秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread A: Resumed!");
}
public synchronized void notifyThread() {
notify(); // 唤醒等待的线程
}
}
public class Main {
public static void main(String[] args) {
MyClass myObject = new MyClass();
Thread threadA = new Thread(() -> myObject.doSomething());
Thread threadB = new Thread(() -> myObject.notifyThread());
threadA.start(); // 启动线程 A
threadB.start(); // 启动线程 B
}
}
在上述示例中,线程 A 调用了 doSomething()
方法后进入等待状态,并通过 wait(2000)
方法释放了对象的监视器锁,最多等待 2 秒。然后,线程 B 调用了 notifyThread()
方法,在等待时间到达前唤醒了线程 A,并让线程 A 重新获得对象的监视器锁并继续执行。
总之,wait(long timeout)
方法用于将当前线程置于等待状态,直到其他线程调用了该对象的 notify()
或 notifyAll()
方法,或者指定的超时时间到达。使用 wait(long timeout)
方法需要注意同步块或同步方法的使用,并且调用 wait(long timeout)
方法的线程必须持有对象的监视器锁。
wait(long timeout, int nanos)
方法是 Object
类中的一个重载方法,用于将当前线程置于等待状态,直到其他线程调用了该对象的 notify()
、notifyAll()
方法或指定的超时时间过去。该方法还允许设置纳秒级别的超时时间。以下是关于 wait(long timeout, int nanos)
方法的详解:
方法签名:
Object
类中,wait(long timeout, int nanos)
方法的签名为 public final void wait(long timeout, int nanos) throws InterruptedException
。使用条件:
wait(long timeout, int nanos)
方法必须在同步块或同步方法中调用,并且只能由持有对象监视器(锁)的线程来调用。wait(long timeout, int nanos)
方法将会抛出 IllegalMonitorStateException
异常。功能:
wait(long timeout, int nanos)
方法时,它会使当前线程进入等待状态,释放对象的监视器锁,并等待指定的时间(包括纳秒级别的时间)。notify()
或 notifyAll()
方法唤醒,或者等待超时时间到达后自动恢复执行。notify()
或 notifyAll()
方法被调用,且等待时间还未到达,线程将被唤醒并继续执行。示例:
下面是一个示例,展示如何使用 wait(long timeout, int nanos)
方法进行线程间的通信和纳秒级别的超时等待:
public class MyClass {
public synchronized void doSomething() {
System.out.println("Thread A: Doing something...");
try {
wait(2_000, 500_000); // 线程 A 最多等待 2 秒 500 毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread A: Resumed!");
}
public synchronized void notifyThread() {
notify(); // 唤醒等待的线程
}
}
public class Main {
public static void main(String[] args) {
MyClass myObject = new MyClass();
Thread threadA = new Thread(() -> myObject.doSomething());
Thread threadB = new Thread(() -> myObject.notifyThread());
threadA.start(); // 启动线程 A
threadB.start(); // 启动线程 B
}
}
在上述示例中,线程 A 调用了 doSomething()
方法后进入等待状态,并通过 wait(2_000, 500_000)
方法释放了对象的监视器锁,最多等待 2 秒 500 毫秒。然后,线程 B 调用了 notifyThread()
方法,在等待时间到达前唤醒了线程 A,并让线程 A 重新获得对象的监视器锁并继续执行。
总之,wait(long timeout, int nanos)
方法用于将当前线程置于等待状态,直到其他线程调用了该对象的 notify()
或 notifyAll()
方法,或者指定的超时时间到达(包括纳秒级别的时间)。使用 wait(long timeout, int nanos)
方法需要注意同步块或同步方法的使用,并且调用 wait(long timeout, int nanos)
方法的线程必须持有对象的监视器锁。
finalize()
是 Object
类中的一个方法,用于在垃圾回收器对对象进行垃圾回收之前执行清理操作。以下是关于 finalize()
方法的详解:
方法签名:
Object
类中,finalize()
方法的签名为 protected void finalize() throws Throwable
。功能:
finalize()
方法是 Java 垃圾回收机制的一部分,它用于在对象被垃圾回收之前进行一些必要的清理操作。finalize()
方法。finalize()
方法可以被子类重写,以实现特定的清理操作,例如关闭文件、释放资源等。执行时机:
finalize()
方法的执行时机是不确定的,取决于垃圾回收器的调度和系统资源的可用性。finalize()
方法的时间点是在垃圾回收器将对象标记为可回收,并在对象被实际回收之前。finalize()
方法一定会被调用。注意事项:
finalize()
方法应该小心使用,因为它的执行时间是不确定的,可能会影响应用程序的性能。try-finally
语句块中关闭文件、释放资源等,而不是依赖于 finalize()
方法。finalize()
方法已被废弃。建议使用 try-with-resources
或显式地调用资源释放方法来替代。示例:
下面是一个示例,展示了如何重写 finalize()
方法进行资源的清理操作:
public class MyClass {
private File file;
public MyClass() {
this.file = new File("example.txt");
}
@Override
protected void finalize() throws Throwable {
try {
// 清理操作,例如关闭文件
if (file != null) {
file.close();
}
} finally {
super.finalize();
}
}
}
在上述示例中,MyClass
类重写了 finalize()
方法,在方法中执行了关闭文件的操作。当对象被垃圾回收之前,垃圾回收器会调用 finalize()
方法来确保文件被关闭。
总之,finalize()
方法是 Object
类中的一个方法,用于在对象被垃圾回收之前执行清理操作。它应该小心使用,并且在实际编程中更推荐使用显式的资源释放方式替代。
更多消息资讯,请访问昂焱数据。