使用各种类时怎么能不知道它们的源头Object

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()方法。
    String类
比较对象 比较方法
地址 == 或者 未重写的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的基础知识,之后还会更新一些类似的初学时候不是很重视的东西

  • 第一次看源码,感觉认真分析每一个方法还是能学到很多东西,看源码也是理解这个方法最好的方式,应该也能提高阅读代码的能力吧

猜你喜欢

转载自blog.csdn.net/weixin_44689154/article/details/105921682