目录
1.什么是Object类
Object类是所有类的父类,如果一个类没有用extends指明具体继承哪个类,那么就默认继承Object类,同时也继承了Object类中的方法。
2.Object类中的常用方法
方法 | 作用 |
---|---|
getClass() | 获取对象运行时类的Class对象 |
equals() | 比较两个对象是否相等 |
hashCode() | 获取对象的hashCode值 |
toString () | 将对象转换为字符串形式表示 |
clone() | 克隆对象 |
finalize() | 对象被回收时自动调用 |
2.1 getClass()方法
2.1.1 理解
获取对象运行时类的Class对象(存在一个类是Class类)。表示运行时类(运行时的字节码文件即.class文件),用于反射。
例如有一个类User和它的子类vipUser
User user1 = new User() ;
Class c = user1.getClass() ;
//返回一个Class对象,表示运行时的类,在此处就是User类的字节码文件
System.out.println(c);
User user2 = new vipUser() ;
System.out.println(user2.getClass());
输出得到的是: 调用该方法的对象属于的类所在的包.类名。
虽然第二个看上去是用User类生成的,但本质上运行的还是vipUser类,所以运行时类为vipUser。
2.1.2 用法
使用getClass()方法可以用来判断对象的类型,例如
if(user2.getClass() == vipUser.class) {
.....
}
由于 类名.class属性 也可以得到运行时类。那么就可以通过判断当前的对象运行时类是否等于某个类 来判断对象的类型。当然还有另外一种更简单的方式来判断也能达到相同的效果:
if(user2 instanceof vipUser) {
....
}
2.1.3 native修饰
查看Object类的源码可以知道,该方法返回的是一个Class类,代表的就是运行时类。同时可以看到Object类不是抽象类,但是getClass()方法却没有具体的实现,也不属于抽象方法。
能实现这样的效果的原因就是该方法被 native 修饰。
被native修饰的方法称为本地方法,该方法的方法体由非java语言实现,主要用来调用本地的底层语言,如c或c++。所以定义被native修饰的方法时不需要提供具体的方法实现。 Object类中其他的很多方法也是被native修饰,例如hashCode()、clone()、notify()等
2.2 equals()方法
比较两个对象是否相等
2.2.1 判断相等的两种方式与区别
- 使用 == ,由于每new一个对象就会在内存中开辟一个新的空间,而 == 判断是否引用了同一个对象,也就是在内存中存放的是不是同一个位置。
- 使用 equals()方法 , 若该方法没有被重写,则和 == 没有区别。查看源码可知道Object类中 equals()方法本质上还是用 == 进行判断的。
这个时候就会有一个疑惑,拿字符串比较为例,如果用 == 判断两字符的内容是否相等是不行的,但用equals()又是可以,那是因为String类已经重写过equals()方法了。所以如果需要比较的是对象里面的值而不是地址的话,就要重写equals()方法。
比较对象 | 比较方法 |
---|---|
地址 | == 或者 未重写的equals()方法 |
具体值 | 重写equals()方法 |
2.2.2 自动重写equals()方法
开发工具一般都可以自动生成重写的equals()方法,以eclipse为例点击右键然后按照下图选择就可以了。而且使用开发工具自动生成的equals()重写方法判断条件更全面。所以一般不用自己写,直接生成就好了。
2.3 hashCode()方法
获取对象的hashCode值。目的是为了支持哈希表,若没重写该方法,则会返回该对象的地址。
2.3.1注意事项
- 同一个对象多次调用该方法返回的值一定是一样的
- 若要重写equlas()方法,也一定要重写hashCode()方法。因为这两个方法经常会一起使用。上面说的eclipse可以自动重写equlas()方法,在这同时也会自动重写hashCode()方法。
- 如果两个对象的equlas()方法比较返回true,那么hashCode()方法返回的值也一定一样
- 如果两个对象的equlas()方法比较返回false,那么hashCode()方法返回的值可以相同也可以不相同,但最好不相同(提高哈希表性能)
2.4 toString () 方法
将对象转换为字符串形式表示。使用该方法一般用于输出对象时返回更容易读的信息,便于查看结果,常用于测试。当直接输出对象时,也会自动执行toString()方法。
System.out.println(user1.toString()) ;
System.out.println(user1); //两个输出结果一样
查看源码,可以看到Object类中的toString()方法直接返回的是 运行时类+十六进制字符串型的哈希code。但是这样写还是不能很清晰地查看这个对象中有什么,所以一般需要重写这个方法。同样开发工具也可以自动重写。
2.5 clone() 方法
该方法用于克隆对象。克隆得到的是开辟了新空间的一个新对象,只是里面的属性值和原来的一样。
2.5.1 重写clone() 方法
查看源码可知,clone() 方法被 protected修饰,所以在我们自己写的类中不能直接调用,所以必须要重写该方法才能使用。
重写要点:
- 在需要使用clone()方法的类中将该方法从protected类型重写成public类型,在函数体中只需要返回super.clone()即可
- 重写clone()方法的类要实现Cloneable接口。查看这个接口的源码发现里面什么东西都没有,这个接口只是作为一个标志,有了这个标志才允许克隆。
2.5.2 clone() 方法的分类
- 浅克隆:从Object继承的clone()方法。只克隆对象本身,如果属性中含有对象属性,那么不克隆引用的这个对象属性。简单说就是,克隆出来的新对象是开辟了新空间产生的,但其中的对象属性还是原来的那一个。只克隆了一层。
- 深克隆:把对象中引用的所有对象都克隆出新的,没有共用的空间。要实现只能自己来实现。
2.6 finalize()方法
对象被回收时自动调用。不需要手动调用,由垃圾回收器自动调用。所以这个方法基本不用管,如果想要监测什么时候回收对象,那么可以重写该方法,加上提示语句然后执行super.finalize(),但是很难观察到什么时候调用了这个方法。
2.6.1 垃圾回收机制:
- JVM中存在一个守护线程gc(垃圾回收器),自动启动。
- 每个对象都存在一个int类型的变量作为引用计数器,每当有一个引用指向该对象计数器就加一,不再引用就减一。当计数器的值为0时,gc会认为该对象是垃圾,gc会在合适的时机(由算法控制)对该对象自动回收释放空间。当被回收时自动调用finalize()方法。
- 虽然gc不用手动控制就能执行,但如果想要在某个地方执行gc,就可以用System.gc()来建议(可能回收也可能不回收)JVM执行gc
3.总结
-
只总结了几个常用的,还有一些比如notify等还不是很了解就等之后加在后面
-
第一次学Java的时候很多类似Object这样的东西都是只知道但没有深入去学习,导致很多常用的方法见到也不知道是什么意思。 最近开始重写复习Java的基础知识,之后还会更新一些类似的初学时候不是很重视的东西
-
第一次看源码,感觉认真分析每一个方法还是能学到很多东西,看源码也是理解这个方法最好的方式,应该也能提高阅读代码的能力吧