1.面向对象的基础概念
Java是面向对象的语言,对象就是面向对象程序设计的核心。具有以下特点:
1.对象具有属性和行为
2.对象具有变化的状态
3.对象具有唯一性
4.对象都是某个类别的实例
5.一切皆为对象,真实世界中的所有事物都可以视为对象
2.面向对象和面向过程的区别
面向过程是一种较早的编程思想,顾名思义就是站在过程的角度去思考问题,着重的是功能行为,功能的执行过程,即执行的先后顺序。这种思想最小的程序单元是函数,每个函数负责完成某一个功能,用于接收输入数据,函数对输入数据进行处理,得到输出结果。整个系统由一个个的函数组成,主函数作为程序的入口函数,主函数依次调用其他函数,普通函数之间互相调用,从而实现整个系统功能。
面向过程的问题:由于采用自顶而下的设计模式,在设计阶段就需要考虑每个模块所关联的其他子模块,而每个子模块又细分为更小的字模块,随着系统的膨胀,面向过程将无法应付,最终会导致系统的崩溃。
面向对象是一种基于面向过程的新编程思想,是指站在对象的角度思考问题,把多个功能合理放到不同对象里,强调的是具备某些功能的对象。最小的程序单元是类。面向对象更加符合常规的思维方式,稳定性好,可重用性强,易于开发大型软件产品,有不错的可维护性,实现了低耦合和高内聚。
3.面向对象的三大核心特点
3.1.继承
继承是指子类继承父类的特征和行为,但父类私有的属性和方法,子类无法直接访问(在java中,只能单继承,如果想实现多继承,只能通过内部类的方式)
如上图,食草动物和食肉动物共同属于动物一类,但是食草动物的饮食属性与食肉动物有差异,
并且食草动物大多温顺,食肉动物大多凶猛,在行为上也有差异。
所以继承关系应该是:is-a , 父类更通用,子类更具体。
3.1.1 方法重写
如果觉得子类继承父类的方法并不适用,可以在子类中重新编写继承的方法,这个操作称为方法的重写,当调用方法时会优先调用子类的方法。
重写注意点:返回值类型,方法名,参数类型及个数。这几点与父类相同才算是重写。
重载和重写的区别:方法重载是同一个类中,拥有相同方法名,但参数类型或者参数个数不同,而重写是相对继承来说,子类对继承到父类的方法的个性化修改
3.1.2 继承的初始化顺序
简单的说,父类优先,静态优先。
父类静态变量和静态初始化代码块-->子类静态变量和静态初始化代码块-->父类成员变量和初始化代码块-->父类构造方法-->子类成员变量和初始化代码块-->子类构造方法
3.1.3 final关键字
final表示“最终的”
使用final修饰类时,类无法被继承
使用final修饰方法时,方法无法被重写
使用final修饰变量或者属性时,初始化后无法被更改
3.1.4 super关键字
在对象内部使用,可以代表父类对象。
1.访问父类的属性:super.property
2.访问父类的方法:super.method()
super的应用:
在子类构造过程当中必须调用父类的构造方法,这个过程隐式地使用了super关键字,这是因为如果子类构造方法中没有显式调用父类的构造方法,则系统默认调用父类无参的构造方法,那么如果自己用super关键字在子类中调用父类的构造方法,则必须在子类构造方法的第一行。
需要注意的是:如果子类构造方法中既没有显示调用父类的构造方法,而父类没有无参的构造方法,则会编译出错
// 父类
public class Person {
private String age;
private String name;
//虽然没有显式声明父类无参构造方法,系统会默认生成,但是如果父类有带参数的构造方法,此时系统就不会生成
public Person(String age,String name){
this.name = name;
this.age = age;
}
}
//子类
public class Student extends Person{
//这里会编译报错
public Student(){
}
}
3.2.封装
封装就是把过程和数据包裹起来,对数据的访问只能通过已经定义的接口或者方法。
例如ATM收款机,会使用一个机器来保证钱的正常流动,给你一个特定的方法来存钱取钱,不会说让你随意的取钱存钱。
封装的目的在于保护信息,是一种将抽象性函数式接口的实现细节部分包装,隐藏起来的方法。主要优点如下:
1.良好的封装能够减少耦合
2.类内部的结构可以自由修改
3.可以对成员变量进行更精确的控制
4.隐藏信息,实现细节
3.2.1 Java中的内部类
内部类是指定义在一个类里面的类,包含内部类的类称为外部类。
那么内部类的作用是什么?
1.内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同包中其他类访问
2.内部类的方法可以直接访问外部类的所有数据,包括私有
3.内部类所实现的功能使用外部类同样能实现,但是内部类更方便
内部类的类型:
1.成员内部类
2.静态内部类
3.方法内部类
4.匿名内部类
public class Outter {
//成员内部类
class Inner1{
}
//静态内部类
static class Inner2{}
public void main(String[] args) {
//成员内部类
Outter.Inner1 inner1 = new Outter.Inner1();
//静态内部类
Outter.Inner2 inner2 = new Outter.Inner2();
//方法内部类
class LocalInner{}
//匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
}
});
}
}
3.3.多态
多态是指同一种行为在不同对象上的表现方式不同
例如上述中的食草动物和食肉动物都具备eat属性,但是前者eat素食,后者eat荤食,这就是同一行为在不同对象的不同表现。
在java中,还可以将多态定义为接口的不同实现
彩色打印机和黑白打印机都实现了打印机的接口,但是打印操作的结果不同,这也满足上述的结果。
多态的优点:可替换性,可扩展性,接口性,灵活性,简化性。使用多态是一种好习惯,如果某天我们对这个接口方法的实现方式变了,对这个接口又有一个新的实现类,我们的程序也需要使用最新的实现方式,此时只需将对象实现修改一下。
比如Map< String,String> map = new HashMap < String,String>();
想换成HashTable实现,可以Map< String,String> map = new HashTable < String,String>();
比如写一个方法,参数要求传递List类型,你就可以用List list = new ArrayList()中的list传递,但是你写成ArrayList list = new ArrayList()是传递不进去的。尽管方法处理时都一样。另外,方法还可以根据你传递的不同list(ArrayList或者LinkList)进行不同处理。
3.3.1 引用多态
父类的引用可以指向本类的对象;
父类的引用可以指向子类的对象;
public static void main(String[] args) {
//父类的引用可以指向子类的对象
Person person = new Student();
//父类的引用可以指向本类的对象
Person person2 = new Person();
}
注意,这里我们不能使用子类的引用指向父类,就以上面的例子来说,学生是人的一种职业, 但是无法说人是学生的一种职业,学生和人就是子类和父类的继承关系,顺序无法颠倒。当父类的引用指向子类时,该对象是一种特殊的父类,反之,子类引用指向父类是不可行的
3.3.2 方法多态
本类对象和子类对象,同样是父类的引用,当指向不同的对象时,调用的方法也是多态的。
创建本类方法,调用的方法为本类方法
创建子类方法,调用的方法为子类重写或者继承的方法
如果在子类中写了一个独有的方法(没有继承父类),那么无法通过父类引用创建子类对象调用该方法,继承或实现是多态的基础
3.3.3 引用类型转换
1.向上类型转换(隐式/自动类型转换),小类型-->大类型,例如父类引用指向子类
2.向下类型转换(强制类型转换),大类型-->小类型,有风险,可能会数据溢出
3.instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题
instanceof是Java的一个二元运算符,作用是测试它左边的对象是否是它右边类的实例,返回布尔值
一般在写程序时,如果要进行类型转换,最好先使用instanceof判断,再进行强转。