前言Java是一门面向对象的语言。Java中的一切都可以看作是一个对象,Java中所有的对象都默认继承自Object类。本文基于JDK1.8,一共可以看到12个方法,其中registerNatives()是原生修改的,一个本地方法,具体用C(C++)实现在一个DLL中,然后通过JNI调用。getClasspublicfinalnativeClassgetClass();getClass也是一个native方法,这个方法的作用是返回一个对象的运行时类,它的返回值是Class类型,Classc=obj.getClass();通过对象c,我们可以得到该对象的所有成员方法,每个成员方法都是一个Method对象;我们还可以获取对象的所有成员变量,每个成员变量都是一个Field对象;同样,我们也可以得到对象的构造函数,构造一个函数就是一个Constructor对象。这种方法经常用在反射中。hashCodepublicnativeinthashCode();hashCode方法返回一个哈希值。默认情况下,返回值是从对象的地址转换而来的。对同一个对象调用hashCode返回值是相等的。两个对象的equals相等,那么hashCode一定相等。两个对象的equals不相等,所以hashCode不一定相等。equalspublicbooleanequals(Objectobj){return(this==obj);}equals的实现非常简单。它的作用是比较两个对象是否相等,比较的依据是两者的内存地址。此外,equals还遵循以下原则:1.自反性:x.equals(x);//true2.对称性:x.equals(y)==y.equals(x);//true3、传递性:if(x.equals(y)&&y.equals(z))x.equals(z);//true;4、一致性,只要对象没有被修改过,多次调用equals()方法的结果不变:x.equals(y)==x.equals(y);//true5,非空性,对任何不为null的对象x调用x.equals(null)的结果为false:x.equals(空);//假;为什么要重写hashcode和equals?因为这两个方法是和对象比较相关的,所以如果程序中要做对象比较,大概率是要重写这两个方法。因为equals默认的比较逻辑是比较对象的地址,所以两个对象的内存地址肯定是不同的,所以无论如何,通过eqals对两个对象进行比较肯定返回false。但是在实际编程中,我们经常会遇到去重,或者把对象放在有序的集合中,或者把对象存储在不重复的集合中。这时候如果不重写equals和hashCode是不能满足要求的。例如,系统中同时存在两个对象,对象A和对象B,其名称和ID号完全相同。此时系统内存中有两个对象,但是它们的内容是一致的,很明显是一个人同时生成了两条重复的消息。如果使用默认的equals方法进行比较,两个对象永远不会相等,也永远不会被比较为相同的重复信息。因此必须重写equals和hashCode方法才能达到上述要求。cloneprotectednativeObjectclone()throwsCloneNotSupportedException;clone()是Object的受保护方法,不公开。如果一个类没有显式重写clone(),其他类就不能直接调用该类实例的clone()方法。另外,Clone的注释也提到了一些重点:被克隆的对象必须实现Cloneable接口,重写clone方法,否则会报CloneNotSupportedException异常clone()方法不是Cloneable接口的方法,而是Object的方法受保护的方法。Cloneable接口只是规定,如果一个类没有实现Cloneable接口,调用了clone()方法,就会抛出CloneNotSupportedException。浅拷贝:复制对象的引用类型和原对象引用同一个对象。深拷贝:拷贝对象和原对象的引用类型引用不同的对象。稍后我们将讨论浅拷贝和深拷贝。toStringpublicStringtoString(){returngetClass().getName()+"@"+Integer.toHexString(hashCode());}返回对象的字符串表示,很重要的方法getClass().getName();获取字节码文件对应的全路径名,如java.lang.Object;Integer.toHexString(hashCode());将哈希值转换为十六进制格式的字符串。等待并通知publicfinalvoidwait()throwsInterruptedException{wait(0);>999999){thrownewIllegalArgumentException("nanosecondtimeoutvalueoutofrange");}if(nanos>0){timeout++;}wait(timeout);}wait的作用是让当前线程进入等待状态,同时wait()也会让当前线程释放它持有的锁。直到其他线程调用该对象的notify()方法或notifyAll()方法,当前线程才被唤醒,进入就绪状态。wait(longtimeout)(以毫秒为单位)保持当前线程处于等待(阻塞)状态,直到其他线程调用该对象的notify()方法或notifyAll()方法,或者超过指定的时间量,当前线程线程被唤醒进入就绪状态。wait(longtimeout,intnanos)与wait(longtimeout)功能相同,唯一不同的是可以提供更高的精度。总超时(以纳秒为单位)计算为1000000*timeout+纳秒。顺便说一句,wait(0,0)与wait(0)具有相同的效果。publicfinalnativevoidnotify();publicfinalnativevoidnotifyAll();首先是notify,notify的作用是随机唤醒等待队列中的一个线程,notifyAll是唤醒等待队列中的所有线程。注意:notify和wait方法的使用说明。意思是两者必须用synchronized修饰的同步方法或同步代码。Thread.sleep()和Object.wait()有什么区别?首先,两者都可以挂起当前线程,释放CPU控制权。主要区别在于Object.wait()在释放CPU的同时释放了对象锁的控制权。并且Thread.sleep()不会释放锁。也就是说,睡觉就是耍流氓,占厕所不拉屎。完整代码包java.lang;publicclassObject{/***一个本地方法,具体用C(C++)在DLL中实现,然后通过JNI调用*/privatestaticnativevoidregisterNatives();/***这个方法在对象初始化时自动调用*/static{registerNatives();}/***返回这个Object的运行时类*/publicfinalnativeClass>getClass();/***hashCode的总约定为:*1。在java应用程序执行期间,对同一对象的hashCode()方法的多次调用必须一致地返回相同的整数,前提是用于等于对象的信息未被修改。*从应用程序的一次执行到同一应用程序的另一次执行,整数不需要保持一致。*2.如果根据equals(object)方法两个对象相等,则对这两个对象中的每一个调用hashCode方法必须产生相同的整数结果。*3.如果根据equals(java.lang.Object)方法两个对象不相等,则不需要对两个对象中的任何一个调用hashCode()方法来生成不同的整数结果。*但是,程序员应该意识到,为不相等的对象生成不同的整数结果可以提高哈希表的性能。*/publicnativeinthashCode();/***这里比较对象的内存地址*/publicbooleanequals(Objectobj){return(this==obj);}/***本地clone方法,用于对象拷贝*/protectednativeObjectclone()throwsCloneNotSupportedException;/***返回对象的字符串表示,很重要的一个方法*getClass().getName();获取字节码文件对应的全路径名如java.lang.Object*Integer.toHexString(hashCode());将哈希值转换为十六进制格式的字符串。*/publicStringtoString(){returngetClass().getName()+"@"+Integer.toHexString(hashCode());}/***不可改写,用于唤醒正在等待对象(调用wait方法)处于等待状态(waiting或time_wait)的线程,该方法只能在同步方法或同步块中调用*/publicfinalnativevoidnotify();/***不可改写,用于唤醒所有等待对象(调用wait方法)是处于等待状态(waiting或time_waiting)的线程,该方法只能在同步方法或同步块中调用*/publicfinalnativevoidnotifyAll();/***不可改写,用于线程调用,导致当前线程进入等待状态(time_waiting),超时单位为毫秒。该方法只能在同步方法或同步块中调用。超过设定时间后,线程会重新进入可运行状态*/publicfinalnativevoidwait(longtimeout)throwsInterruptedException;publicfinalvoidwait(longtimeout,intnanos)throwsInterruptedException{if(timeout<0){thrownewIllegalArgumentException("timeoutvalueisnegative");}if(nanos<0||nanos>999999){thrownewIllegalArgumentException("nanosecondtimeoutvalueoutofrange");}if(nanos>0){timeout++;}wait(timeout);}/***在其他线程调用notify()方法或此对象的notifyAll()方法。换句话说,此方法的行为就好像它只是执行了一个wait(0)调用。*当前线程必须拥有这个对象监视器。*线程释放这个监视器的所有权并等待直到其他线程通过调用notify方法或notifyAll方法通知等待这个对象监视器的线程唤醒,*然后线程将等待直到重新获得监视器的所有权继续执行。*/publicfinalvoidwait()throwsInterruptedException{wait(0);}/***这个方法在对象被回收的时候使用,这个是JVM支持的,Object的finalize方法默认什么都不做,如果子类需要在对象被回收时要进行一些逻辑处理,可以重写finalize方法。*/protectedvoidfinalize()throwsThrowable{}}PS:这里有技术交流群(按钮群:1158819530),方便大家一起交流,不断学习,共同进步。如果需要,您可以添加它。
