这篇文章给大家分享的是有关Java中Class和Object是什么意思的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
刚开始学的时候,老师对我们说的第一句话就是在Java的世界里一切都是对象。那么这个对象是什么呢?就是在java.lang包下面的Object对象。Object是一个具体的类,它的设计主要是为了扩展。在JDK中对于Object的描述如下:
它的意思是Object在类层级中是root,是每个类的父类。所有对象,包括数组以及类里面的方法。
但是这里面没有提及到接口。而且我们在IDE里面查询对象以及接口的层级结构也不一样:
我们可以看到在java.util.Timer的类表示.
Timer.class
Ctrl + h
查看它的类结构体系如下:
java.util.concurrent.Future
的类继承体系。
如果一个没有直接父类接口,接口声明了一个public abstract
方法m,JVM将会为接口标隐含定义了Object类中的方法签名完全相同的方法。除非在接口明确的定义了在接口中定义了同样方法签名,同样返回值以及throws同样的异常。
但是要注意以下两点:
如果在接口中定义了与Object定义相同的方法,并且声明为final。那么就会出现编译异常。
如果在接口中定义了与Object定义签名相同的方法。但是它不符合Object的重写规范那。就是返回值类型不同,或者抛出不兼容的异常,或者不是abstract的方法。也会出现编译异常。
下面我们就来看一看Object里面的方法。Object作为通用的类,作为通用的类不能够满足于各种各样的业务场景,所以对于它所有的非final方法(equals、hashcode、toString、clone和finalize)都有明确的通用约定,因为它们的设计成是要被覆盖的。任何一个类,它在覆盖这些方法的时候,都有责任遵守这些通用约定,其他依赖于这些约定的类(例如HashMap和HashSet)就无法结合该类一起正常工作了。
获取当前对象的类类型,使用这个对象可以执行反射操作。
返回当前对象的hash code值。当这个对象需要使用到hash表的时候需要重写这个方法。同时也需要重写equals方法。
表明其它对象是否写当前对象相等。默认是判断两个对象的引用地址是否相等。而在Effective Java中推荐覆盖equals方法的时候总要覆盖hashCode方法。而需要覆盖equals方法的时候需要遵守它的通用规定。下面就约定的内容:
自反性(reflexive):对于任何非null的引用值x,x.equals(x)必须返回true.
对称性(symmetric):对于任何非null的引用值x,y,当且仅当y.equals(x)返回true时x.equals(y)必须返回true。
传递性(transitive):对于任何非null的引用值x,y,z。如果x.equals(y)返回true.并且y.equals(z)也返回true,那么x.equals(z)也必须返回true.
一致性(consistent):对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致地false。
对于任何非null的引用值x,x.equals(null)必须返回false
创建并且返回这个对象的copy。精确的表达”copy”依赖于该对象的类。一般情况下,对于对象x:
表达式:x.clone() != x,将会为true
表达式:x.clone().getClass() == x.getClass(),将会为true
表达式:x.clone().equals(x),将会为true.
默认情况下满足这种情况,但这个并不是绝对的。
按照约定:一般通过调用super.clone获取到返回对象。如果一个类以及它的所有超类就会出现:x.clone().getClass() == x.getClass().
而且Object类并没有实现Cloneable接口。因此如果一个类并没有实现Cloneable接口,而且它的实例还调用clone方法就会出现CloneNotSupportedException.
虽然java.lang.Object提供了toString方法的一个实现,但它返回的是类的名称以及一个”@”符号,接着是散列码的无符号十六进制表示法。例如:Object@163b91,这种表示方法对于用户是非常不友好的。所以toString的约定是:建议所有的子类都覆盖这个方法。
唤醒被当前线程监控正在等待的一个线程。如果有这个对象中许多线程正在等待,就会从它们中选择一个来唤醒。这个选择是根据各个不同的系统来任意决定的,也就是说多个线程在waiting是随机选择一个线程来唤醒。
这个方法仅仅能够被是这个对象的monitor调用。一个线程可以通过以下3种方式来成为这个对象的monitor的拥有者。
执行这个对象的同步实例方法。
执行这个对象的同步代码块。
对于Class对象,执行一个同步静态方法。
并且在同一时间只能有一个线程做为一个对象minitor的拥有者。
唤醒被当前线程监控正在等待所有线程。如果是一个线程被这个对象monitor的话,可以调用wait方法。
这个方法也仅难能被这个对象的monitor的拥有者调用。具体可以看一下notity方法中介绍一个线程如何才能够成功一个monitor的拥有者。
这三个方法的功能都是一样的,都是让线程进入等待状态。只是等待的超时时间的设置方式不同。调用这三个方法都是暂停当前线程,直到另外一个线程调用notify方法或者notifyall方法或者其它线程中断了当前线程,或者过了超时时间。
当没有引用指向这个对象的时候,调用这个对象的垃圾回收。子类可以重写finalize方法用来处理系统资源或者执行其它清除操作。
一般情况下当JVM确定这个对象没有被其它对象引用的时候,就会调用finalize方法。一般的纯Java编写的Class不需要重新覆盖这个方法,因为Object已经实现了一个默认的,除非我们要实现特殊的功能(这 里面涉及到很多东西,比如对象空间树等内容)。
不过用Java以外的代码编写的Class(比如JNI,C++的new方法分配的内存),垃圾回收器并不能对这些部分进行正确的回收,这时就需要我们覆盖默认的方法来实现对这部分内存的正确释放和回收(比如C++需要delete)。
总之,finalize相当于析构函数,他是垃圾回收器回收一个对象的时候第一个要调用的方法。不过由于Java的垃圾回收机制能自动为我们做这些事情,所以我们在一般情况下是不需要自己来手工释放的。
先有Class还是先有Object?
Java的对象模型中:
所有的类都是Class类的实例,Object是类,那么Object也是Class类的一个实例。
所有的类都最终继承自Object类,Class是类,那么Class也继承自Object。
感谢各位的阅读!关于“Java中Class和Object是什么意思”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。