区分一个Java程序员是初级还是中级最好的方法就是问他Object类中的方法都知道哪些。这个问题我曾经在面试中问过很多人,发现真正能回答上来的并不多。有人反问我Object是什么,有人说除了toString其他不清楚……下面来看看Object中都有哪些方法。
一、toString
从API中可以看到默认toString方法的返回的是class name和16进制的hash code的组合。
return getClass().getName() + "@" + Integer.toHexString(hashCode());
二、hashCode和equals
hashCode的协议:
- hashCode提供了对HashMap、HashTable的支持;
- 对于同一个对象执行hashCode多次,应该返回同样的结果;
- 对于两个相等的对象,他们的hashCode也应该一致;
- 对于两个不相等的对象,他们的hashCode可以相等,但最好不相等,这样可以增强HashMap的性能。
下面是equals和hashCode的例子:
public class MyObject {
private long id;
private String name;
private String desc;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyObject myObject = (MyObject) o;
if (id != myObject.id) return false;
if (name != null ? !name.equals(myObject.name) : myObject.name != null) return false;
return !(desc != null ? !desc.equals(myObject.desc) : myObject.desc != null);
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (desc != null ? desc.hashCode() : 0);
return result;
}
}
三、wait、notify和notifyAll
wait和notify是Java中基本的对线程进行操作的API,如下例我创建了一个只有一个值长度的Queue,一个Producer向Queue中写入新值,一个Consumer从Queue中取出值。当Producer向Queue中写入新值后通知Consumer可以取值;当Consumer取值后通知Producer可以写值。
public class WaitNotifyExample {
private class Queue {
private Integer value;
public synchronized boolean hasValue() {
return value != null;
}
public synchronized void setValue(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
}
private class Producer implements Runnable {
private final Queue q;
Producer(Queue q) {
this.q = q;
}
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (q) {
q.setValue(1);
q.notify();
}
}
}
private class Consumer implements Runnable {
private final Queue q;
Consumer(Queue q) {
this.q = q;
}
@Override
public void run() {
synchronized (q) {
while (!q.hasValue()) {
try {
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + q.getValue());
}
}
}
public static void main(String[] args) {
WaitNotifyExample example = new WaitNotifyExample();
Queue q = example.new Queue();
new Thread(example.new Producer(q), "Producer").start();
new Thread(example.new Consumer(q), "Consumer").start();
}
}
其中:
- 若删除synchronized后执行会抛出IllegalMonitorStateException,这是因为当使用wait和notify、notifyAll的时候必须拥有对象的monitor锁,否则会抛出异常。
- wait方法也可以传入参数指定timeout时间。
四、getClass
这是一个native的方法,返回本对象实例对应的class的对象。
五、clone
跟getClass一样也是一个native的方法,返回本对象的一个复制品。
注意:若要支持本方法,必须实现Cloneable接口。
六、finalize
这是另一个native的方法。当GC回收本对象的时候会被GC调用。
注意:由于该方法的执行时间是无法控制的,因此一般不建议实现该方法。如果需要资源清理请使用自定义方法。
网友评论