![7efaac3553a60cf0cc3d58d9dc2fa1bb.png](https://i-blog.csdnimg.cn/blog_migrate/1b08b133ec6fd4f8668cca653e4e6f6d.jpeg)
楠哥最近出了一本书《Java零基础实战》,这本书中整合了我多年的一线研发经验,包括我对一些技术点的理解,可能与其他书籍讲解的角度略有不同,但一定可以帮助你更好地应用这些技能点。
![7523adcd634e49920348a98f4f1746bb.png](https://i-blog.csdnimg.cn/blog_migrate/640c011bf1e1115b68a950906b9a7aed.jpeg)
本书的最大特点就是实用,全书包括近 300 段代码示例,5 个项目实战案例,让每个核心知识点落地,不再只是理论上的叙述,让读者真正掌握其实际应用。今天截取书中的一部分内容,供大家试读,如果你觉得不错就下单吧,详见文末。
第5章 面向对象进阶
在前面的章节中我们学习了面向对象思想的基本概念,对面向对象的三大特征(封装、继承和多态)都做了详细的阐述,相信大家对这些概念已经有了一定的理解和掌握。面向对象更重要的是理解其编程思想,具备把程序模块化成对象的能力,思想的建立需要不断地思考,勤加练习,本章我们继续学习面向对象的高级部分。
5.1 Object类
5.1.1 认识Object类
Java是通过类来构建代码结构的,类分为两种:一种是Java提供的,无需开发者自定义,可直接调用;另外一种是由开发者根据不同的业务需求自定义的类。所以我们写的Java程序,其实就是由Java提供的类和自定义的类组成的,打开Eclipse,在JRESystem Library中存放的就是Java提供的类,开发者自定义的类存放在src目录下,如图5-1和图5-2所示。
![dca2f901c2859a46f559ff46e1e41ab9.png](https://i-blog.csdnimg.cn/blog_migrate/b50c2188a6ac14bcad209ed28937996d.jpeg)
图5-1
![b35e8d6a2e5976daeae85cfef5b444c6.png](https://i-blog.csdnimg.cn/blog_migrate/a0cc15a4b4dca45c8c8bf61a469fa462.jpeg)
图5-2
JRE SystemLibrary中的类全部是编译之后的字节码文件,即class格式的文件,我们可以看到源码,但是不能修改,如图5-3所示。
![d172c620fab258599f24d8f235115673.png](https://i-blog.csdnimg.cn/blog_migrate/94e69e774b7f07bda89b292078a7b707.jpeg)
图5-3
Object就是Java提供的一个类,位于java.lang包中,该类是所有类的直接父类或间接父类。无论是Java提供的类,还是开发者自定义的类,都是Object的直接子类或间接子类。或者说Java中的每一个类都是Object的后代,Object是所有类的祖先。一个类在定义时如果不通过extends指定其直接父类,系统就会自动为该类继承Object类,Object类的源码如代码5-1所示。
代码5-1:public class Object {private static native void registerNatives(); static { registerNatives(); } public final native Class> getClass(); public native int hashCode(); public boolean equals(Object obj) { return (this == obj); } protected native Object clone() throws CloneNotSupportedException; public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException { if (timeout < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos > 0) { timeout++; } wait(timeout); } public final void wait() throws InterruptedException { wait(0); } protected void finalize() throws Throwable { }}
可以看到Object类中提供了很多用public和protected修饰的方法,子类是可以直接继承这些方法的,即Java中的任何一个类,都可以调用Object类中的public和protected方法,当然private是不能调用的,如图5-4所示。
![0759a3f4159de859b422933841e7f6f9.png](https://i-blog.csdnimg.cn/blog_migrate/e77ae7302ef34f36b26c913c71eafa6a.jpeg)
图5-4
5.1.2 重写Object类的方法
上一节我们介绍了Object是所有类的父类,每一个类都可以直接继承Object类的非私有方法,实例化对象可以直接调用这些方法。但是通常情况下不会直接调用这些方法,而是需要对它们进行重写,因为父类中统一的方法并不能适用于所有的子类。就像老爹房子的装修风格是老爹喜欢的,儿子们审美各有不同,老爹的房子并不能满足他们的需求,所以儿子们会把房子的旧装修覆盖掉,重新装修以适应他们的需求。这种方式是多态的一种体现,父类信息通过不同的子类呈现出不同的形态,接下来我们就一起看看Object类经常被子类所重写的那些方法,如表5-1所示。
![5fccbfe2cd9892bd7f8785e2c9b311d8.png](https://i-blog.csdnimg.cn/blog_migrate/70651ed2071f44301b81c50d841b44ea.jpeg)
先来看看这3个方法的具体实现,toString()方法的实现如图5-5所示。
![71475d0bb4d6b7ae48696a744d6e4848.png](https://i-blog.csdnimg.cn/blog_migrate/d119b71cb1320a6843336c56ae1c7556.jpeg)
图5-5
原生的toString()方法会返回对象的类名以及散列值,直接打印对象默认调用toString()方法,如代码5-2所示。
代码5-2:public class Test { public static void main(String[] args) { People people = new People(); people.setId(1); people.setName("张三"); people.setAge(22); people.setGender('男'); System.out.println(people); }}
程序的运行结果如图5-6所示。
![22198d15b57172b09fb537ff829efb5e.png](https://i-blog.csdnimg.cn/blog_migrate/7f4cf1fb72641d1ff178d4094d1d97a8.jpeg)
图5-6
但是在实际开发中返回这样的信息意义不大,我们更希望看到的是对象的属性值,而非它的内存地址,所以我们需要对toString()方法进行重写,如代码5-3所示。
代码5-3:public class People { …… @Override public String toString() { return "People [id=" + id +