public final native Class<?> getClass()java
public native int hashCode()app
public boolean equals(Object obj)ide
protected native Object clone() throws CloneNotSupportedExceptionoop
public String toString()性能
public final native void notify()测试
public final native void notifyAll()this
public final native void wait(long timeout) throws InterruptedException线程
public final void wait(long timeout, int nanos) throws InterruptedExceptioncode
public final void wait() throws InterruptedExceptionorm
protected void finalize() throws Throwable
getClass方法是一个final方法,不容许子类重写,而且也是一个native方法。
返回当前运行时对象的Class对象,注意这里是运行时,好比如下代码中n是一个Number类型的实例,可是java中数值默认是Integer类型,因此getClass方法返回的是java.lang.Integer:
Number n = 0; Class<? extends Number> c = n.getClass(); // class java.lang.Integer
hashCode方法也是一个native方法。
该方法返回对象的哈希码,主要使用在哈希表中,好比JDK中的HashMap。
哈希码的通用约定以下:
在java程序执行过程当中,在一个对象没有被改变的前提下,不管这个对象被调用多少次,hashCode方法都会返回相同的整数值。对象的哈希码没有必要在不一样的程序中保持相同的值。
若是2个对象使用equals方法进行比较而且相同的话,那么这2个对象的hashCode方法的值也必须相等。 若是根据equals方法,获得两个对象不相等,那么这2个对象的hashCode值不须要必须不相同。可是,不相等的对象的hashCode值不一样的话能够提升哈希表的性能。
一般状况下,不一样的对象产生的哈希码是不一样的。默认状况下,对象的哈希码是经过将该对象的内部地址转换成一个整数来实现的。
若是2个对象的equals方法相等,那么他们的hashCode值也必须相等,反之,若是2个对象hashCode值相等,可是equals不相等,这样会影响性能,因此仍是建议2个方法都一块儿重写。
比较两个对象是否相等。Object类的默认实现,即比较2个对象的内存地址是否相等:
public boolean equals(Object obj) { return (this == obj); }
建立并返回当前对象的一份拷贝。通常状况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 也为true。
Object类的clone方法是一个protected的native方法。
因为Object自己没有实现Cloneable接口,因此不重写clone方法而且进行调用的话会发生CloneNotSupportedException异常。
Object对象的默认实现,即输出类的名字@实例的哈希码的16进制:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
toString方法的结果应该是一个简明但易于读懂的字符串。建议Object全部的子类都重写这个方法。
**notify方法是一个native方法,而且也是final的,不容许子类重写。 **
notify方法只能被做为此对象监视器的全部者的线程来调用。一个线程要想成为对象监视器的全部者,可使用如下3种方法:
执行对象的同步实例方法 使用synchronized内置锁 对于Class类型的对象,执行同步静态方法 一次只能有一个线程拥有对象的监视器。
若是当前线程不是此对象监视器的全部者的话会抛出IllegalMonitorStateException异常
注意点:
由于notify只能在拥有对象监视器的全部者线程中调用,不然会抛出IllegalMonitorStateException异常
跟notify同样,惟一的区别就是会唤醒在此对象监视器上等待的全部线程,而不是一个线程。
一样,若是当前线程不是对象监视器的全部者,那么调用notifyAll一样会发生IllegalMonitorStateException异常。
wait(long timeout)方法一样是一个native方法,而且也是final的,不容许子类重写。
wait方法会让当前线程等待直到另一个线程调用对象的notify或notifyAll方法,或者超过参数设置的timeout超时时间。
跟notify和notifyAll方法同样,当前线程必须是此对象的监视器全部者,不然仍是会发生IllegalMonitorStateException异常。
wait方法会让当前线程(咱们先叫作线程T)将其自身放置在对象的等待集中,而且放弃该对象上的全部同步要求。出于线程调度目的,线程T是不可用并处于休眠状态,直到发生如下四件事中的任意一件:
其余某个线程调用此对象的notify方法,而且线程T碰巧被任选为被唤醒的线程
其余某个线程调用此对象的notifyAll方法
其余某个线程调用Thread.interrupt方法中断线程T
时间到了参数设置的超时时间。若是timeout参数为0,则不会超时,会一直进行等待
因此能够理解wait方法至关于放弃了当前线程对对象监视器的全部者(也就是说释放了对象的锁)
以后,线程T会被等待集中被移除,而且从新进行线程调度。而后,该线程以常规方式与其余线程竞争,以得到在该对象上同步的权利;一旦得到对该对象的控制权,该对象上的全部其同步声明都将被恢复到之前的状态,这就是调用wait方法时的状况。而后,线程T从wait方法的调用中返回。因此,从wait方法返回时,该对象和线程T的同步状态与调用wait方法时的状况彻底相同。
在没有被通知、中断或超时的状况下,线程还能够唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种状况在实践中不多发生,可是应用程序必须经过如下方式防止其发生,即对应该致使该线程被提醒的条件进行测试,若是不知足该条件,则继续等待。换句话说,等待应老是发生在循环中,以下面的示例:
synchronized (obj) { while (<condition does not hold>) obj.wait(timeout); ... // Perform action appropriate to condition }``` 若是当前线程在等待以前或在等待时被任何线程中断,则会抛出InterruptedException异常。在按上述形式恢复此对象的锁定状态时才会抛出此异常。 ### wait(long timeout, int nanos) throws InterruptedException方法 跟wait(long timeout)方法相似,多了一个nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 因此超时的时间还须要加上nanos毫秒。 须要注意的是 wait(0, 0)和wait(0)效果是同样的,即一直等待。 ### wait() throws InterruptedException方法 跟以前的2个wait方法同样,只不过该方法一直等待,没有超时时间这个概念。 如下这段代码直接调用wait方法会发生IllegalMonitorStateException异常,这是由于调用wait方法须要当前线程是对象监视器的全部者:
Factory factory = new Factory(); factory.wait();
通常状况下,wait方法和notify方法会一块儿使用的,wait方法阻塞当前线程,notify方法唤醒当前线程,一个使用wait和notify方法的生产者消费者例子代码以下:
public class WaitNotifyTest {
public static void main(String[] args) { Factory factory = new Factory(); new Thread(new Producer(factory, 5)).start(); new Thread(new Producer(factory, 5)).start(); new Thread(new Producer(factory, 20)).start(); new Thread(new Producer(factory, 30)).start(); new Thread(new Consumer(factory, 10)).start(); new Thread(new Consumer(factory, 20)).start(); new Thread(new Consumer(factory, 5)).start(); new Thread(new Consumer(factory, 5)).start(); new Thread(new Consumer(factory, 20)).start(); }
}
class Factory {
public static final Integer MAX_NUM = 50; private int currentNum = 0; public void consume(int num) throws InterruptedException { synchronized (this) { while(currentNum - num < 0) { this.wait(); } currentNum -= num; System.out.println("consume " + num + ", left: " + currentNum); this.notifyAll(); } } public void produce(int num) throws InterruptedException { synchronized (this) { while(currentNum + num > MAX_NUM) { this.wait(); } currentNum += num; System.out.println("produce " + num + ", left: " + currentNum); this.notifyAll(); } }
}
class Producer implements Runnable { private Factory factory; private int num; public Producer(Factory factory, int num) { this.factory = factory; this.num = num; } @Override public void run() { try { factory.produce(num); } catch (InterruptedException e) { e.printStackTrace(); } } }
class Consumer implements Runnable { private Factory factory; private int num; public Consumer(Factory factory, int num) { this.factory = factory; this.num = num; } @Override public void run() { try { factory.consume(num); } catch (InterruptedException e) { e.printStackTrace(); } } }
注意的是Factory类的produce和consume方法都将Factory实例锁住了,锁住以后线程就成为了对象监视器的全部者,而后才能调用wait和notify方法。 输出:
produce 5, left: 5 produce 20, left: 25 produce 5, left: 30 consume 10, left: 20 produce 30, left: 50 consume 20, left: 30 consume 5, left: 25 consume 5, left: 20 consume 20, left: 0
### finalize方法 finalize方法是一个protected方法,Object类的默认实现是不进行任何操做。 该方法的做用是实例被垃圾回收器回收的时候触发的操做,就比如 “死前的最后一波挣扎”。 直接写个弱引用例子:
Car car = new Car(9999, "black"); WeakReference<Car> carWeakReference = new WeakReference<Car>(car);
int i = 0; while(true) { if(carWeakReference.get() != null) { i++; System.out.println("Object is alive for "+i+" loops - "+carWeakReference); } else { System.out.println("Object has been collected."); break; } }
class Car { private double price; private String colour;
public Car(double price, String colour){ this.price = price; this.colour = colour; } // get set method @Override protected void finalize() throws Throwable { System.out.println("i will be destroyed"); }
}
输出:
.... Object is alive for 26417 loops - java.lang.ref.WeakReference@7c2f1622 Object is alive for 26418 loops - java.lang.ref.WeakReference@7c2f1622 Object is alive for 26419 loops - java.lang.ref.WeakReference@7c2f1622 Object is alive for 26420 loops - java.lang.ref.WeakReference@7c2f1622 Object is alive for 26421 loops - java.lang.ref.WeakReference@7c2f1622 Object is alive for 26422 loops - java.lang.ref.WeakReference@7c2f1622 Object has been collected. i will be destroyed