概述
一、定义
(一)什么是object类
1.Object类存储在java.lang包中,使用的时候无需显示导入,编译时由编译器自动导入。是所有java类(Object类除外)的终极父类(包括标准容器类,比如数组),不过接口不继承Object类。
2.可以使用类型为Object的变量指向任意类型的对象。Object类的变量只能用作各种值的通用持有者,要对他们进行任何专门的操作,都需要知道它们的原始类型并进行类型转换。
3.包含的函数:
1)public Object();
2)protected Object clone()
3)boolean equals(Object obj)
4)protected void finalize()
5)Class< > getClass()
6)int hashCode()
7)void notify()
8)void notifyAll()
9)String toString()
10)void wait()
11)void wait(long timeout)
12)void wait(long timeout, int nanos)
二、用法
(一) 常用函数解析
1.Object():默认构造方法。
1)Java中规定:在类定义过程中,对于未定义构造函数的类,默认会有一个无参数的构造函数,作为所有类的基类,Object类自然要反映出此特性,在源码中,未给出Object类构造函数定义,但实际上,此构造函数是存在的。当然,并不是所有的类都是通过此种方式去构建,也自然的,并不是所有的类构造函数都是public。
2.Clone():创建并返回此对象的一个副本。
1)clone()方法又是一个被声明为native的方法,因此,我们知道了clone()方法并不是Java的原生方法,具体的实现是有C/C++完成的。clone英文翻译为"克隆",其目的是创建并返回此对象的一个副本。clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。
2)当代码执行的时候,将会检查调用对象的类(或者父类)是否实现了java.lang.Cloneable接口(Object类不实现Cloneable)。如果没有实现这个接口,clone()将会抛出一个检查异常()——java.lang.CloneNotSupportedException,如果实现了这个接口,clone()会创建一个新的对象,并将原来对象的内容复制到新对象,最后返回这个新对象的引用。
3)浅克隆(也叫做浅拷贝)仅仅复制了这个对象本身的成员变量,该对象如果引用了其他对象的话,也不对其复制仅仅复制其引用(当被复制的对象的引用类型变量内容发生变化时候,被复制的对象也会跟着变化)。
3.finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
1)首先,Object中定义finalize方法表明Java中每一个对象都将具有finalize这种行为,其具体调用时机在:JVM准备对此对形象所占用的内存空间进行垃圾回收前,将被调用。由此可以看出,此方法并不是由我们主动去调用的(虽然可以主动去调用,此时与其他自定义方法无异)。
4.equals()与hashCode():指示某个其他对象是否与此对象“相等”; 返回该对象的哈希码值。
1)重写equals()方法必须重写hashCode()方法。因为当仅仅重写equals()方法改变了判断对象相等条件,但是很多引用类型(例如hashMap等)判断相等是通过hashCode()方法判断key值是否相等,所以会导致意想的equals()要相等,但是hashCode()依旧是之前的逻辑导致不相等。
2)对象相等 ó equals()相等 => hashCode()相等;根据逆反定理:hashCode()不相等 => equals()不相等 ó 对象不相等
3)hashCode()相同的两个对象不一定相等,换而言之不相等的两个对象其hashCode()值可能相同。
5.getClass():返回一个对象的运行时类。
1)首先解释下"类对象"的概念:在Java中,类是对具有一组相同特征或行为的实例的抽象并进行描述,对象则是此类所描述的特征或行为的具体实例。作为概念层次的类,其本身也具有某些共同的特性,如都具有类名称、由类加载器去加载,都具有包,具有父类,属性和方法等。于是,Java中有专门定义了一个类,Class,去描述其他类所具有的这些特性,因此,从此角度去看,类本身也都是属于Class类的对象。为与经常意义上的对象相区分,在此称之为"类对象"。
6.toString:返回该对象的字符串表示。
1)在Object类中,它用于返回对象所属类名和散列码。
2)绝大多数的toString方法都遵循这个格式: 类名[域值,域值,域值......]。
7.notify()、notifyAll():唤醒在此对象监视器上等待的单个/所有线程。
1)调用后,其所在线程不会立即释放所持有的锁,直到其所在同步代码块中的代码执行完毕,此时释放锁,因此,如果其同步代码块后还有代码,其执行则依赖于JVM的线程调度。
8.wait()、wait(long timeout)、wait(long timeout, int nanos):导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法、或者已超过某个实际时间量,、或者其他某个线程中断当前线程。
1)调用后当前线程将立即阻塞,且释放其所持有的同步代码块中的锁,直到被唤醒或超时或打断后且重新获取到锁后才能继续执行。
三、总结
1.既然比较两个对象是否相等的唯一条件(也是冲要条件)是equals,那么为什么还要弄出一个hashCode(),并且进行如此约定,弄得这么麻烦?
1)其实,这主要体现在hashCode()方法的作用上,其主要用于增强哈希表的性能。
2)以集合类中,以Set为例,当新加一个对象时,需要判断现有集合中是否已经存在与此对象相等的对象,如果没有hashCode()方法,需要将Set进行一次遍历,并逐一用equals()方法判断两个对象是否相等,此种算法时间复杂度为o(n)。通过借助于hasCode方法,先计算出即将新加入对象的哈希码,然后根据哈希算法计算出此对象的位置,直接判断此位置上是否已有对象即可。(注:Set的底层用的是Map的原理实现)
2.在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一地返回同一个整数。
1)设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()方法就会生成一个不同的散列码。
2)因此,在设计hashCode方法和equals方法的时候,如果对象中的数据易变,则最好在equals方法和hashCode方法中不要依赖于该字段。
3.大多数人认为hashCode返回的就是对象的存储地址,事实上这种看法是不全面的,确实有些JVM在实现时是直接返回对象的存储地址,但是大多时候并不是这样,只能说可能存储地址有一定关联。
最后
以上就是斯文溪流为你收集整理的Java顶级父类Object的全部内容,希望文章能够帮你解决Java顶级父类Object所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复