Object的所有方法
1、常用方法
equals(Object)
默认实现
public boolean equals(Object obj) {
return (this == obj);
}
此方法用来表示两个对象是否相等,Java类实现equals方法可以自定义对象相等的比较规则。
getClass()
Java native实现的方法,返回当前对象的运行时类的对象。
public final native Class<?> getClass();
hashCode()
返回对象的哈希代码值。支持此方法是为了保护哈希表(如 提供的 java.util.HashMap哈希表)。
每当在 Java 应用程序执行期间对同一对象多次调用该方法时,该方法必须始终返回相同的整数, hashCode 前提是不修改用于比较对象的信息 equals 。 从应用程序的一次执行到同一应用程序的另一次执行,此整数不必保持一致。 如果根据该方法两个对象相等,hashCode必相等,两个对象根据方法不equals相等,hashCode也不等 hashCode的规则可以提升Hash表的性能,减少哈希冲突。
toString()
默认实现是
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
如果子类不重写toString方法,则返回全类名+@+16进制的hashCode
2、线程相关方法
notify()/notifyAll()
wait(long,int)/wait(long)/wait()/wait0()
在Java中,每个对象都有两个池,锁(monitor)池和等待池
锁池
锁池:假设线程A已经拥有了某个对象的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
等待池
等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.
notify 和 notifyAll 的区别
wait()
public final void wait() throws InterruptedException,IllegalMonitorStateException
该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放锁。在从 wait()返回前,线程与其他线程竞争重新获得锁。如果调用 wait()时,没有持有适当的锁,则抛出 IllegalMonitorStateException,它是 RuntimeException 的一个子类,因此,不需要 try-catch。
notify()
public final native void notify() throws IllegalMonitorStateException
该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁,的如果调用 notify()时没有持有适当的锁,也会抛出 IllegalMonitorStateException。
该方法用来通知那些可能等待该对象的对象锁的其他线程。如果有多个线程等待,则线程规划器任意挑选出其中一个 wait()状态的线程来发出通知,并使它等待获取该对象的对象锁(notify 后,当前线程不会马上释放该对象锁,wait 所在的线程并不能马上获取该对象锁,要等到程序退出 synchronized 代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁),但不惊动其他同样在等待被该对象notify的线程们。当第一个获得了该对象锁的 wait 线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用 notify 语句,则即便该对象已经空闲,其他 wait 状态等待的线程由于没有得到该对象的通知,会继续阻塞在 wait 状态,直到这个对象发出一个 notify 或 notifyAll。这里需要注意:它们等待的是被 notify 或 notifyAll,而不是锁。这与下面的 notifyAll()方法执行后的情况不同。
notifyAll()
public final native void notifyAll() throws IllegalMonitorStateException
该方法与 notify ()方法的工作方式相同,重要的一点差异是:
notifyAll 使所有原来在该对象上 wait 的线程统统退出 wait 的状态(即全部被唤醒,不再等待 notify 或 notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll 线程退出调用了 notifyAll 的 synchronized 代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出 synchronized 代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。
3、生成对象方法
Object()
构造方法
clone()
Person p = new Person(23, "zhang"); Person p1 = (Person) p.clone();
4、垃圾回收相关方法
finalize()
在Java9中标记为弃用,真正移除还有很长的路。
此方法的作用: finalize()方法中一般用于释放非Java 资源(如打开的文件资源、数据库连接等),或是调用非Java方法(native方法)时分配的内存(比如C语言的malloc()系列函数)。
存在的问题:
① 由于finalize()方法的调用时机具有不确定性,从一个对象变得不可到达开始,到finalize()方法被执行,所花费的时间这段时间是任意长的。我们并不能依赖finalize()方法能及时的回收占用的资源,可能出现的情况是在我们耗尽资源之前,gc却仍未触发,因而通常的做法是提供显示的close()方法供客户端手动调用。
② 重写finalize()方法意味着延长了回收对象时需要进行更多的操作,从而延长了对象回收的时间。
③ 若方法异常或者产生死锁影响GC
Java9之后建议
建议使用AutoCloseable或者Cleaner进行处理,
为了防止可能造成的多线程的延迟处理,许多对象回收前的处理都是单独通过一个线程完成的,这样能够保证执行性能的提高。
package test.com;
public class Member implements Runnable{
public Member(){
System.out.println("【构造】Born");
}
public void doSomething(){
System.out.println("doing");
}
@Override
public void run() { // 执行清除的时候,执行的是此操作
System.out.println("【回收】Death");
}
}
package test.com;
import test.com.Member;
import java.lang.ref.Cleaner;
public class MemberCleaning implements AutoCloseable{ // 实现清除
private static final Cleaner cleaner = Cleaner.create(); // 创建清除处理
private Member member;
private Cleaner.Cleanable cleanable;
public MemberCleaning(Member member) {
this.member = member;
this.cleanable = this.cleaner.register(this,this.member); // 注册使用的对象
}
@Override
public void close() throws Exception {
this.cleanable.clean(); // 启动多线程
}
}
package test.com;
public class Main {
public static void main(String[] args) throws Exception{
Member m;
try (MemberCleaning mc = new MemberCleaning(m=new Member())){
// 中间可以执行一些相关的代码
m.doSomething();
}catch (Exception e){
}
}
}