Java 源码--Object

Object是Java的基类,它的大部分方法都是native修饰的,标记方法是Java中的本地方法,一般是用C/C++语言实现的。下面我们就来分析一下这个类。

registerNatives方法将C/C++种的方法映射到Java中的native方法,实现方法命名的解藕。此函数在类的静态代码块中,在类首次加载时执行。

1
2
3
4
private static native void registerNatives();
static {
registerNatives();
}

在JDK1.8以及之前,Object的构造方法是没有写出来的,但是编辑器默认其有一个无参构造方法。从JDK1.9之后,Object的构造方法被显示写出。@HotSpotIntrinsicCandidate注解是特定于Java虚拟机的注解。

1
2
@HotSpotIntrinsicCandidate
public Object() {}

getClass方法返回对象运行时的类,即返回的是动态类型的类。如果这个类被另一个

1
2
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();

Java不是存粹的静态类型或者动态类型,A a,A就是静态类型,若B继承于A,a = new B(),B就是动态类型。

可以通过以下例子看出getClass方法的返回。

1
2
3
4
5
6
A a = new A();
A b = new B();
B c = new B();
System.out.println(a.getClass().getName());
System.out.println(b.getClass().getName());
System.out.println(c.getClass().getName());

运行结果:

1
2
3
test.A
test.B
test.B

hashCode方法返回对象的哈希值,它的存在是为了提高HashTable、HashMap等的效率。对于同一对象,在不改变equals方法前提下,必须返回相同的哈希值。对于equals方法返回true的两个对象,哈希值必须返回相同的。对于equals方法返回false的两个对象,哈希值可以相同也可以不相同,但是我们应该尽量让他们的哈希值不相同。

1
2
HotSpotIntrinsicCandidate
public native int hashCode();

equals方法比较两个对象的相等性,此处比较的是两个对象的地址。

1
2
3
public boolean equals(Object obj) {
return (this == obj);
}

clone方法返回一个对象的复制。使用克隆方法的类必须实现Cloneable接口,否则会抛出CloneNotSupportedException异常。

1
2
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;

toString方法返回对象的字符串。如果我们自己的类没有重写toString方法,就会返回类名加类的哈希值的16进制的表示。

1
2
3
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

notify方法唤醒正在此对象上等待的一个线程,如果有多个线程在等待,则由JVM决定选择其中一个唤醒。

1
2
@HotSpotIntrinsicCandidate
public final native void notify();

notifyAll方法唤醒全部等待的线程。

1
2
@HotSpotIntrinsicCandidate
public final native void notifyAll();

wait方法使一个线程进入等待状态,直到其他线程调用notify或notifyAll方法或等待时间到达指定时间。当指定时间为0时,只能等待其他线程唤醒。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public final void wait() throws InterruptedException {
wait(0L);
}

public final native void wait(long timeoutMillis) throws InterruptedException;

public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}

if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}

if (nanos > 0) {
timeoutMillis++;
}

wait(timeoutMillis);
}

调用对象的wait()、notify()、notifyAll()方法之前必须获得对象的锁,否则会出现java.lang.IllegalMonitorStateException异常。对象执行wait()方法之后,线程释放锁进入等待状态,直到其他线程将其唤醒或该线程被中断或线程等待时间达到指定长度。当线程被唤醒之后,并不能立马获得对象的锁,而是重新竞争锁,线程必须拿到锁之后才能继续执行。另一个线程执行了notify()或notifyAll()方法之后也不会立马释放锁,要执行完synchronized语句块才会释放锁。当其他线程执行了notify()方法之后,JVM会从等待该锁的线程中选择一个唤醒,执行了notifyAll()方法之后,会唤醒全部等待该锁的线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static void main(String[] args) {
ObjectTest objectTest = new ObjectTest();
Test test = new Test();

Thread thread1 = new Thread(() -> {
synchronized (objectTest) {
try {
System.out.println("1");
objectTest.wait();
System.out.println("2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

});
thread1.start();

Thread thread3 = new Thread(() -> {
synchronized (test) {
try {
System.out.println("3");
test.wait();
System.out.println("4");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

});
thread3.start();

Thread thread2 = new Thread(() -> {
synchronized (objectTest) {
System.out.println("5");
objectTest.notify();
System.out.println("6");
}
});
thread2.start();
}

输出结果如下,并且主线程并没有停止,处于等待状态。

1
2
3
4
5
1
3
5
6
2

当垃圾回收器认为一个对象没有其他引用时,就调用finalize()方法清理对象。

1
2
@Deprecated(since="9")
protected void finalize() throws Throwable { }
-------------本文结束感谢您的阅读-------------

本文标题:Java 源码--Object

文章作者:huihui

发布时间:2018年11月26日 - 00:11

最后更新:2019年02月14日 - 19:02

原始链接:http://101.200.47.120:8011/2018/11/26/Java 源码--Object/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。