这是Java系列的第二篇文章,其实在年初的时候我就给我自己定下了目标,要重新走一遍所有Java有关的知识,所以应该会写很多,会把我的面试经历,日常踩坑都写进去,有兴趣的大佬可以看看。
Java是一款优秀的面向对象的编程语言,既然是面向对象,那么我们必须清楚面向的对象是什么?面向的对象在哪里?
首先我们来解答一下什么是面向对象,面向对象程序设计的主要精神是将存在于日常生活中的对象概念应用在软件设计的发展模式中,着重于对象的分解与相互作用,重点是强调程序代码的可读性、可重复使用性与扩展性,让程序设计人员在设计程序时能以一种更生活化、可读性更高的设计思路来进行程序的开发和设计。
面向的对象在哪里,其实这个问题在上一段也做了解答,面向的对象就是我们真实世界的抽象。比如《Java从入门到精通》这本书,在真实世界它就是一本书,在代码里面我们该如何描述呢?这里就要抽象书这个概念,首先《Java从入门到精通》他是一本书,其次才是什么书,那么我们就可以对这本书进行一个抽象,代码如下所示。
/**
* 书的抽象
*/
public abstract class Book {
protected String name;
}
上面就是一个简单的书的抽象,其中name是所有书都得有的,所以我们可以将name其放在对象的最顶层。设计完书的抽象之后,我们再设计实实在在的对应的书。
public class JavaBook extends Book{
// todo
}
我们用JavaBook去继承抽象的Book实现了《Java从入门到精通》这本书,这样我们就完成了对一本书从实际世界到代码世界的转换,而我们面向的对象就是它。
说完了什么是面向对象,我们继续深入?既然是面向对象的程序,那么它们一定具备一些要素,面向对象的要素就是封装,继承与多态。
有一点需要补充的是,这里涉及到关于类,变量,函数,类型修饰符等概念,这些概念为Java的基本概念,是学习本文的前置条件。
接下来我们要开始介绍面向对象的第一部分封装,封装字如其名,就是对程序进行封装,让核心留在内部,外部只暴露给用户,我们希望他看到的部分,这样既遵循了设计模型中的对扩展开放,对修改关闭的原则,又可以使得内部结构处于一种非常稳定的状态存在。用户不需要关注你的内部如何实现,我只需要通过你暴露的几个简单的接口就能完成整个流程的操作.
再举一个通俗的例子,我们日常都需要的交通工具之一汽车,我们只需要把钥匙插入某些位置就可以完成启动,不需要知道这个汽车怎么造的,轮胎用的什么牌子,底盘又是怎么设计的,这些我们都不需要知道。
说了这么多,不如上代码看看,首先给出一个简单的封装的例子。
public class Car {
// 是否启动
private boolean isStart;
// 汽车引擎
private Engine engine;
// 其他模块
/**
* 传入true启动汽车
**/
public setStart(boolean: start) {
if (start) {
this.isStart = true;
engine.start();
// 其他的start
}
}
}
这个例子其实就比较简洁明了了,我们不需要操作其他任何东西,只需要传入start的状态,就可以完成汽车的启动,至于其中怎么启动,那是汽车内部的事情了,作为消费者我们不需要关注这些,这就是我们所说的封装,其实封装的思想在很多框架都得到了应用,比如SpringBoot,MyBatis等。
此处我们需要普及一下关于四种修饰符的范围。
修饰符 说明 private 所声明的方法或属性只能被此类的成员使用 protected 所声明的方法或属性可以被基类或其派生类的成员所使用 public 表示所声明的方法或属性可以被所有类的成员所使用 default 同包权限(默认,缺省的) 定义存取权限时,必须在声明成员变量,方法或类之前加入关键字。
继承从程序设计语言的角度来看,就是一种承接基类的实例变量及方法的概念,更严谨的定义是,类之间具有层级关系,基类(Base Class)就是定义好的通用类,而从基类继续而来的派生类(Derived Class)接收了基类的类成员,并在派生类的基础上发展出不同的类成员。
此处我不得不有用在第一张提到的书本的例子来进行讲述,首先我们先上类图。
上图很形象的将Book和JavaBook的关系表示了出来,JavaBook继承了基类所提供的Book的属性(只要是非private都可以)。
public class Book {
public read() {
// 所有书籍都涉及的公共逻辑
}
}
public class JavaBook extends Book {
public read() {
super.read();
// JavaBook专属逻辑
}
}
就这样我们一个简单的继承也描述了,是不是very easy!接下来就是多态,多态这块我们也将以Book这个例子来进行说明。
多态(Polymorphism)从字义来解释是多种(poly)变形(morph)的意思。在面向对象程序设计的概念中,多态主要是指同一个方法名称却有多种不同的功能。多态是一种较为复杂、不容易理解却又非常重要的概念,它的主要功能是帮助我们在编写程序时声明并定义同名的方法却能实现不同的功能,也就是一种“同名异式”的概念。在Java语言中有两种多态:静态多态与动态多态,在后续的内容中我将介绍他们。
静态多态(Static Polymorphism)是一种在编译期间(Compile Time)就决定的多态,例如重载是指我们可以设计相同名称的方法,但允许这个方法有不同的参数类型、参数个数或参数顺序,在Java程序编译期间,编译器就可以区分这些方法之间的不同,从而正确决定要调用哪一个方法。
重载可以应用于普通类的方法中,常见的System.out.println()方法就让我们感受到重载带来的好处,因为System.out.println()方法可以根据传给它参数的数据类型或个数输出指定的执行结果。当然在Java中重载还有更加常见的用法,就是构造函数,为了满足多种不同场景的构建,我们往往会采用构造函数重载入的方式来完成兼容场景。
下面我将例举一个简单的静态多态类的例子来进行说明。
public class Book {
public read() {}
public read(Integer pageNum) {}
public read(Integer pageNum, Integer lineNum){}
}
上面就是一个简答的多态的例子,我们要读书就调用read方法,但是又不能每次都是从头开始,所以此时我们就需要能读取指定页或者指定行的方法,于是我们又重载了一个read(Integer pageNum)和read(Integer pageNum, Integer lineNum)这样我们就可以实现读取我们想要的内容。
动态多态(Dynamic Polymorphism)是一种在执行期间(Runtime)才确定的多态,允许我们继承一个基类来声明并定义同名的方法。
简单来说就是就是我们继承中所举的例子。
public class Book {
public read() {
// 所有书籍都涉及的公共逻辑
}
}
public class JavaBook extends Book {
public read() {
// 重写Read方法
}
}
public class People {
public static void main(String[] args) {
Book book = new Book();
book.read();
book = new JavaBook();
book.read();
}
}
通过子类的方式实现对read的刷新,这就是一个简单的动态多态
这里其实涉及到Java中一个比较重要的知识点,重载和重写(@Overload和@Override)。
重写
其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,所以在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。
重载
在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。
通俗来说重载是在一个类里面进行,重写涉及到父子类的操作,重写不改变方法的修饰符,返回值,参数等,而重载是可以改变传入的参数的。
憋了一周,这篇关于面向对象简述的文章终于给我憋出来了,到此面向对象这块基本也就讲完了,下面该到集合框架了,这块的话就够我写一整子了。
最后补充一句,也许我写的不够好,不够全面,上述便是我对于Java的复习和整理,如果有所疏漏,请指出,会及时更正,感谢。