echo

任生命穿梭 时间的角落

0%

Object

java.lang.Object

类Object是类层次结构的根。 每个类都有Object作为超类。 所有对象,包括数组,实现这个类的方法。

类层次结构

image-20200414205022670

构造方法

public Object(){}

方法

registerNatives

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

Java 中有两种方法:Java 方法和本地方法。Java 方法是由 Java 语言编写,编译成字节码,存储在 class 文件中。本地方法是由其他语言(比如 C 、C++ 、汇编)编写的,编译成和处理器相关的机器代码。本地方法保存在动态链接库中,格式是各个平台专有的。Java 方法是平台无关的,但本地方法不是。运行中的 Java 程序调用本地方法是,虚拟机装载包含这个本地方法的动态库。本地方法是联系 Java 程序和底层主机操作系统的连接方法。

本地方法的实现是由其他语言编写并保存在动态链接库中,因此在 Java 类中不需要方法实现。registerNatives() 本质上就是一个本地方法,但这又是一个区别于一般本地方法的本地方法,从本地方法名可以猜测出该方法是用来注册本地方法的。上述代码的功能就是先定义了registerNatives()方法,然后当该类被加载的时候,调用该方法完成对该类中本地方法的注册。

凡是包含registerNatives()本地方法的类,同时也包含了其他本地方法。所以,显然,当包含registerNatives()方法的类被加载的时候,注册的方法就是该类所包含的除了registerNatives()方法以外的所有本地方法

一个Java程序要想调用一个本地方法,需要执行两个步骤:第一,通过System.loadLibrary()将包含本地方法实现的动态文件加载进内存;第二,当Java程序需要调用本地方法时,虚拟机在加载的动态文件中定位并链接该本地方法,从而得以执行本地方法。registerNatives()方法的作用就是取代第二步,让程序主动将本地方法链接到调用方,当Java程序需要调用本地方法时就可以直接调用,而不需要虚拟机再去定位并链接。

getClass

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

返回运行时类的Object 。 返回Class对象被 static synchronized 所表示的类方法修饰。
实际结果的类型是Class<? extends |X|>,其中|X| 是getClass被调用时静态类型的擦除。 例如,下列代码不需要强制转换。

1
2
Number n = 0; 
Class<? extends Number> c = n.getClass();

hashcode

1
public native int hashCode();

返回该对象的哈希码值。 为其他哈希表提供支持,例如 java.util.HashMap 。
一般 hashCode 满足以下规则:

  • 在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对同一个对象的多次调用,hashCode方法都必须始终返回同一个值。在一个应用程序与另一个应用程序的执行过程中,执行hashCode方法所返回的值可以不一致。

  • 如果两个对象由 equals() 判断为 true ,那么他们的哈希码值必须相等。

  • 如果两个对象由 equals() 判断为 false ,那么他们的哈希码值可以相等。应该为不同的对象生成不同的哈希码来提高哈希表的性能。哈希码值一般是将对象地址转成一个整数来得到。

equals

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

判断某个其他对象是否 “等于” 这个对象。默认比较的是两个对象的地址,当且仅当 this 和 obj 同时指向同一个对象时返回 true。

按照约定,equals要满足以下规则。

  • 自反性: x.equals(x) 一定是true
  • 对null: x.equals(null) 一定是false
  • 对称性: x.equals(y) 和 y.equals(x)结果一致
  • 传递性: a 和 b equals , b 和 c equals,那么 a 和 c也一定equals。
  • 一致性: 在某个运行时期间,2个对象的状态的改变不会影响equals的决策结果,那么,在这个运行时期间,无论调用多少次equals,都返回相同的结果。

通常 equals 方法被重写时,必须重写 hashcode 方法。如果重写了 equals 方法,没有重写 hashcode 方法,判断两个值相等的对象时,当 equals 方法判断为 true(对象的值相等则为 true)时,由于两个值相等的对象地址不一样,所以生成的 hashcode 也不一样。违反了 hashcode 的规则:equals 为 true 两个对象的哈希码值必须相等。

clone

1
protected native Object clone() throws CloneNotSupportedException;

创建并返回此对象的副本。按照惯例,返回的对象应该通过调用super.clone获得。

clone的方法Object执行特定的克隆操作。 首先,如果此对象的类不实现接口Cloneable ,则抛出CloneNotSupportedException 。 请注意,所有数组都被认为是实现接口Cloneable ,并且数组类型T[]clone方法的返回类型是T[] ,其中T是任何引用或原始类型。 否则,该方法将创建该对象的类的新实例,并将其所有字段初始化为完全符合该对象的相应字段的内容,就像通过赋值一样。 这些字段的内容本身不被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深度拷贝”操作。

Object类本身并不实现接口Cloneable ,因此在类别为Object的对象上调用clone方法将导致运行时抛出异常

toString

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

返回一个代表对象的字符串。这个字符串中含有对象的相关信息,便于阅读。建议所有的子类重写这个方法。

Object 类的 toString 方法返回对象的类名 + ‘@’ + 对象的哈希码值得十六进制数。

notify

1
public final native void notify();

唤醒任意一个正在等待该对象的监视器锁(对象的内置锁)的线程。一个线程通过调用 wait 方法来等待对象的监视器锁。被唤醒的线程只有在当前线程放弃了对象的锁之后才能被执行。被唤醒的线程与其他线程平等竞争对象的锁。该方法只能由作为该对象的监视器的所有者线程调用。

线程有三种方式成为对象监视器锁的所有者:

  1. 通过执行对象的同步方法。

  2. 通过执行对象的同步语句(锁住此对象)。

  3. 执行类的同步静态方法。

notifyAll

1
public final native void notifyAll();

唤醒所有一个正在等待该对象的监视器锁的线程。一个线程通过调用 wait 方法来等待对象的监视器锁。

wait

1
public final native void wait(long timeout) throws InterruptedException;

使当前线程阻塞直到另一个线程调用此对象的 notify 方法或 notifyAll 方法或指定的时间已过,当前线程变为就绪状态。当前线程必须拥有此对象的监视器锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

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

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

wait(timeout);
}

与只有一个参数的 wait 方法类似,更加精细地控制等待被唤醒的时间直到放弃。

1
2
3
public final void wait() throws InterruptedException {
wait(0);
}

使当前线程阻塞直到另一个线程调用此对象的 notify 方法或 notifyAll 方法。

finalize

1
protected void finalize() throws Throwable { }

当垃圾收集器确定不再有该对象的引用时调用。finalize 方法通常的目的是在对象不可撤销丢弃之前执行清除动作。甚至finalize 方法可以让此对象再次可用于其他线程而避免被垃圾收集器清除。finalize 方法只能调用一次。

参考:

https://blog.csdn.net/Saintyyu/article/details/90452826