Object类
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
public class Object
Object类是类层次结构的根。每个类都有Object作为超类。所有的对象,包括数组,都实现了这个类的方法。
一、方法
1、构造函数
public Object()
2、public final Class<?> getClass()
返回一个此Object的运行时类(runtime class)对象。通过返回得到的Class类对象,是被代表类的静态同步方法锁定的对象。
实际得到的结果类型是Class<? extends |X|>,|X|是getClass()被调用处的表达式的被擦除的静态类型。例如,在下面这个代码段中不需要强制转换:
Number n = 0;
Class<? extends Number> c = n.getClass();
3、public int hashCode()
返回对象的hashcode值。这个方法支持散列表,例如HashMap提供的散列表。
hashcode的一般规约:
- 在一个Java应用程序的执行过程中,无论同一个Object的hashcode()方法被调用了多少次,只要在equals比较中需要用到的信息没有被修改,hashcode()方法必须始终返回相同的整数。当然在不同的执行过程中,该整数无需保持一致。
- 如果两个对象根据equals方法的判别是相等的,那么对每个对象的hashcode()方法的调用都会得到相同的整数。
- 根据equals方法判别不相等的两个对象,并不要求两个对象的hashcode()方法必须返回不同的整数。但是,程序员应该注意,为不相等的对象生成不同的整数结果可能会提高散列表的性能。
事实上,Object中定义的hashcode()方法的确为不同的对象返回不同的整数值。这是通过将对象的内部地址转换为整数来实现的,但这种转换技术并不是Java语言要求的。
4、public boolean equals(Object obj)
指示其它对象是否与这个对象“相等”。
equals方法在非空对象的引用上实现了等价关系:
- 它是自反的,对任何非空引用x,x.equals(x)应该返回true;
- 它是对称的,对任何非空引用x和y,当y.equals(x)返回true时,x.equals(y)也应当返回true。
- 它是可传递的,对于任何非空引用x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)也应该返回true
- 它是一致的,对于任何非空引用x,y,如果对象中用于equals比较的信息没有被修改,那么x.equals(y)应该始终返回true或者false。
- 对于任何非空引用x,x.equals(null)应该返回false
Object类的equals方法,在对象上实现了最具鉴别可能性的等价关系。也就是说,对任意的非空引用x,y,当且仅当x和y指向同一对象时,即x==y,该方法会返回true。
请注意,每当重写这个方法时,通常都需要重写hashcode()方法。以便维护hashcode()方法的一般规约——它指出相等的对象,必须有相等的hashcode。
5、protected Object clone() throws CloneNotSupportedException
返回一个当前实例对象的拷贝。
这个“拷贝”的精准定义,取决于对象的类型。一般情况下都意味着对任何对象x:
表达式 x.clone() !=x 为true;
表达式x.clone().getClass() ==x.getClass()为true;
但是,这些都不是绝对的要求。通常的情况是:
x.clone().equals(x)返回true,这个也不是绝对的要求~
按照约定,应该通过调用super.clone来获得所返回的对象。如果一个类和它所有的超类(除了except)都遵守这个约定,会有如下情况:
x.clone().getClass() == x.getClass();
按照惯例,这个方法所返回的对象应该独立于当前对象。为了实现这种独立性,在这个由super.clone返回的对象返回之前,可能有必要修改它的一个或者多个属性。通常这意味着要拷贝任何包含被克隆对象的深层次结构的可变对象,并且用指向拷贝对象的引用代替指向这些对象的引用。
如果一个类只包含原始属性或者指向不可变对象的引用,那么通常情况下不需要修改由super.clone所返回的对象中的属性
Object类的clone()方法执行特定的克隆操作。首先,如果一个对象的类没有实现Cloneable接口,则会引发CloneNotSupportedException异常。注意,所有的数组都被认为实现了Cloneable接口,并且一个T[]类型数组的clone()方法的返回的对象的类型也是T[],T是任意引用类型或者初始数据类型。否则,这个方法将会创建此对象所属类的新的实例,并使用此对象的属性的相关内容去初始化新的实例的所有属性,就像赋值一样;这些属性的内容本身并不克隆。因此,这个方法执行的是当前对象的一个浅拷贝,而不是深拷贝。
类Object本身并不实现Cloneable接口,因此在类为Object的对象上调用clone方法将导致在运行时抛出异常。
6、public String toString()
返回当前对象的字符串表现形式。
返回的字符串应该是一个简洁但内容丰富的表述,有利于阅读。建议所有的子类重写此方法。
Object类的toString()方法返回的字符串包含:实例对象所属类的类名、符号“@”和实例对象的hashcode的无符号十六进制数字。换句话说,此方法返回一个等于如下值的字符串:
getClass().getName()+'@'+Integer.toHexString(hashcode());
7、public final void notify()
唤醒一个正在等待当前对象的监视器的单线程。
如果有多个线程正在等待,选择其中一个唤醒。这种选择是随意的,并且由实现决定。
被唤醒的线程将不会立即执行,直到当前线程放弃这个对象的锁。
被唤醒的线程将以通常的方式与任何其他可能主动竞争这个对象的同步的线程竞争,即在争夺这个对象的锁的竞争中,被唤醒的线程并不享有特权,也没有劣势。
本方法只应被拥有该对象的监视器的线程调用。一个线程可以通过三种方式成为一个对象的监视器的拥有者:
- 通过执行那个对象的同步实例方法
- 通过执行一个作用在相关对象上的同步语句的主体;
- 对于Class类型的对象,通过执行这个类的同步静态方法。
一个对象的监视器只能同时被一个线程占用。
如果当前线程不拥有对象的监视器,引发异常:IllegalMonitorStateException
8、public final void notifyAll()
唤醒所有正在等待该对象的监视器的线程。
一个线程如果调用了一个对象的wait方法,则它是在等待这个对象的监视器。
被唤醒的线程将不会立即执行,直到当前线程放弃这个对象的锁。
被唤醒的线程将以通常的方式与任何其他可能主动竞争这个对象的同步的线程竞争,即在争夺这个对象的锁的竞争中,被唤醒的线程并不享有特权,也没有劣势。
如上~
9、public final void wait( long timeout ) throws InterruptedException
使当前线程等待,直到另一个线程调用了此对象的notify()方法、notifyAll()方法,或者走过了指定的时间量。
当前线程必须拥有这个对象的监视器。
本方法使得当前线程(T)把自身置于该对象的等待集中,并放弃所有对该对象的同步声明。为了达到线程调度的目的,线程T被禁用,并且处于休眠状态,知道发生一下四种情况之一:
- 其它线程调用此对象的notify()方法,并且线程T碰巧被选择为要唤醒的线程;
- 其它线程调用该对象的notifyAll()方法;
- 其他线程中断了线程T
- 走过了指定的时间量。如果timeout是0,线程T一直等待直到被通知唤醒。
10、public final void wait(long timeout, int nanos) throws InterruptedException
功能同上,能更好地控制等待时间,单位为纳秒:1000000*timeout+nanos
11、public final void wait() throws InterruptedException
功能如上,只能被通知唤醒。相当于wait(0)。
12、protected void finalize() throws Throwable
在垃圾回收时,若确定没有该对象的引用,由垃圾回收器调用。
子类可以重写该方法以处理系统资源或进行其它清理。
通常的情况是,当Java虚拟机确定任何未死的线程不再有任何方法访问该对象时,该方法会被调用。除非该方法作为一个即将被终结的类或者对象在进行终结时所采取的操作的结果。
finalize()方法中可以执行任何操作,包括让当前对象再次可用于其它线程
不过,finalize()方法的通常目的是在对象不可撤销地丢弃之前执行清理操作。
类Object的finalize方法不执行特殊操作;它只是正常返回。 Object的子类可以重写该方法。
Java编程语言不能保证哪个线程将调用给定对象的finalize()方法。但是可以确保调用finalize()的线程在调用fianlize()时,不会保留任何用户可见的同步锁。
如果finalize方法执行时引发未捕获的异常,则该异常会被忽略,并且对象的终结过程会中止!
任何给定对象的finalize()方法只会被JVM调用一次。