Object类中的常用方法
1、getClass方法
源码:
功能:
返回此Object的运行时类。
什么是运行时类?
如上图所示,类从被加载到虚拟机内存开始,到卸载出内存为止,他的生命周期一共包含7个阶段。其中加载阶段虚拟机需要做3件事。
1)通过一个类的全限定性类名来获取定义此类的二进制流文件。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口。(getClass就是获取这个对象,这是当前类的对象在运行时类的所有信息的集合)
2、hashCode方法
这是一个public的native方法,默认通过对象的内部地址(也就是物理地址)转换成一个整数,然后该整数通过hash函数的算法就得到了该对象的hashcode,子类可以对其进行重写,建议在重写对象的equals方法的时候同时重写对象hashcode方法,不然在使用集合类时有可能会出错。
3、equals方法
对于比较2个对象是否相同。默认情况下比较的是2个对象的内存地址是否相同,建议重写。
为什么需要重写equals方法?
①因为如果不重写equals方法,有可能我们认为相同的2个对象不会相同,如果有一个类Person有1个属性字符串类型的身份证号,一般情况下一个人只有一个身份证,所以只要身份证相同,就能代表是一个人,但是如果不重写equals方法,则达不到这种效果。
②当将自定义对象放到map或者set中时;如果这时两个对象的hashCode相同,就会调用equals方法进行比较,这个时候会调用Object中默认的equals方法,而默认的equals方法只是比较了两个对象的引用是否指向了同一个对象,显然大多数时候都不会指向,这样就会将重复对象存入map或者set中。这就破坏了map与set不能存储重复对象的特性,会造成内存溢出。
4、clone方法
可以实现对象的浅复制,只有实现了Cloneable接口才能调用该方法,否则为抛出CloneNotSupportedException异常。
java中什么是浅复制(拷贝)什么是深复制(拷贝)。
如果除了基本数据之外还有一层的对象,那么对于浅拷贝来说,就只能拷贝其引用。如果原对象的值发生了变化,那么这个结果不光会反映到原对象上,但是深拷贝就不一样,即使有嵌套关系依然会全部的拷贝出来。
5、toString()方法
返回当前对象的字符串表示,通常情况下都会对这个方法重写,如果不重写,则默认为当前类的全限定性类名+@+该对象的hashcode的16位表示。
6、wait方法及其重载
以下三个方法是用来线程间通信用的,作用是阻塞当前线程,等待其他线程调用notify()/notifyAll()方法将其唤醒。这些方法都是public final的,不可被重写。
注意: 此方法只能在当前线程获取到对象的锁监视器之后才能调用,否则会抛出IllegalMonitorStateException异常。 调用wait方法,线程会将锁监视器进行释放;而Thread.sleep,Thread.yield()并不会释放锁。 wait方法会一直阻塞,直到其他线程调用当前对象的notify()/notifyAll()方法将其唤醒;而wait(long)是等待给定超时时间内(单位毫秒),
如果还没有调用notify()/nofiyAll()会自动唤醒;waite(long,int)如果第二个参数大于0并且小于999999,则第一个参数+1作为超时时间;
7、notify()和notifyAll()
当前线程获得了当前对象锁,调用wait方法,将锁释放并阻塞;这时另一个线程获取到了此对象锁,并调用此对象的notify()/notifyAll()方法将之前的线程唤醒。这些方法都是public final的,不可被重写。
8、finalize()
此方法是在垃圾回收之前,JVM会调用此方法来清理资源。此方法可能会将对象重新置为可达状态,导致JVM无法进行垃圾回收。 我们知道java相对于C++很大的优势是程序员不用手动管理内存,内存由jvm管理;如果我们的引用对象在堆中没有引用指向他们时,当内存不足时,JVM会自动将这些对象进行回收释放内存,这就是我们常说的垃圾回收。但垃圾回收没有讲述的这么简单。 finalize()方法具有如下4个特点: 永远不要主动调用某个对象的finalize()方法,该方法由垃圾回收机制自己调用; finalize()何时被调用,是否被调用具有不确定性; 当JVM执行可恢复对象的finalize()可能会将此对象重新变为可达状态; 当JVM执行finalize()方法时出现异常,垃圾回收机制不会报告异常,程序继续执行。