面向对象编程(OOP)
面向对象对象编程,首先我们一些概念要有了解
对象:一切事物都可以是对象,更准确的说,对象是一个实体,用一组可识别的特征和行为来标识,可以说对象不同的地方就是具有不同的特征与行为。
类:是具有相同属性和功能的对象抽象集合
类是抽象集合,一个大类,代表了众多的对象(这些对象具有相同的属性与功能),并不是指具体的对象
实例就是创建具体对象的过程
想要创建实例就要调用类的构造方法
构造方法又叫构造函数是对类进行初始化,构造方法与类同名,无返回值,系统会有一个默认无参的构造方法,若定义构造方法,默认构造方法会失效
通过构造方法我们就得到了一个具体的对象,就可以对对象进行编程
面向对象的三大特性
封装
在类中有许多的属性与方法,将不想暴露的属性与方法隐藏起来,对于能暴露的属性与方法公开
封装的好处
- 良好的封装能鉴赏耦合
- 类内部的实现可以自由的修改
- 类具有清晰的对外接口
访问控制符 可以控制对外、对类、对子类、对包所暴露的方法与属性
public 公共的
都可使用
protrcted 友好的
本类、同包、子类使用
默认(没有写访问控制符) 默认的
本类、同一个个包使用
private 私有的
只能本类使用
this 关键字 在类中使用,可以代表该类,后接属性与方法,代表该类的属性与方法
例如 this.name 代表该类中name属性
内部类
内部类生成文件:外部类名$内部类名.class
内部类种类
成员内部类
静态内部类
方法内部类
匿名内部类
内部类的好处
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
- 内部类的方法可以直接访问外部类的所有数据,包括私有的数据。
- 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。
内部类的使用我在另一篇博客有详细介绍:内部类(详解)
继承
子类继承父类
特点
- 通过extends关键字,实现了继承之后,让类与类之间产生了关系
- 继承的本质就是抽取共有的方法与属性,从而对一批对象进行抽象,继承是对一批类的抽象
- 父类又被称为超类,或者基类,子类又被称为派生类
- Java是面向对象语言,万事万物皆是对象,为了满足这个设计原则,所有的类都直接或者间接继承自Object类。
优点
所有的子类公共部分都放在父类,使得代码得到共享,简化了代码,避免了重复,
继承可使得修改或扩展继承而来的实现都较为容易,提高了扩展性,维护性
缺点
父类变,子类不得不变,继承是一种类与类之间强耦合的关系,牵一发动全身
继承会破坏包装
注意
- 初始化时,先初始化父类再初始化子类
- 单一继承性:在Java中是不支持多继承的,子类只能有一个父类,而父类可以有很多子类。
- 支持多层继承:继承可以一直传下去,子类有父类,父类又有父类…
- 父类成员使用private修饰,那么子类不能被继承。(private只是对本类有效)
- 一个子类继承了父类的属性和方法还可以有自己特有的属性和方法。(不光有父类的属性(可继承的)和方法(可继承的),也有自己独有的属性和方法。)
- 当子类和父类的成员变量重名的时候,子类优先。(就近原则)
- 构造方法不能够被继承(构造方法必须要与类名保持一致)。
final关键字
- final 修饰类,则该类不允许被继承。
- final 修饰方法,则该方法不允许被覆盖(重写)。
- final 修饰的属性, 初始化之后就不能改了,只能赋值一次。
- final 修饰属性,则该类的该属性不会进行隐式的初始化,所以 该final 属性的初始化属性必须有值,或在构造方法中赋值(但只能选其一,且必须选其一,因为没有默认值!)
- final 修饰变量,则该变量的值只能赋一次值,在声明变量的时候才能赋值,即变为常量。
super关键字 在类中使用,代表该类的父类
- 访问父类的属性:super.变量名
- 访问父类的方法:super.方法名()
- super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行
Object类
Object类是所有类的父类
主要方法
- toString()
默认在Object类里面定义toString()方法的时候返回的对象的哈希code码(对象地址字符串) - equals()
默认的情况下,比较的是对象的引用是否指向同一块内存地址-------对象实例化时,即给对象分配内存空间,该内存空间的地址就是内存地址。
方法的重写。当调用方法时会优先调用子类的方法。
多态
多态就是对象的多种形态,多态表示不同的对象可以执行相同的动作,但要通过他们自己的实现代码来执行
继承是多态的基础
- 子类以父类形式出现,子类不能以父类的形式出现
- 子类以父类的身份出现时共有的方法以自己的方式来实现
- 子类以父类的身份出现时,子类特有的属性和方法不可以使用
类型转换
向上类型转换(隐式/自动类型转换),是子类类型转换到父类类型
向下类型转换(强制类型转换),是父类类型转换到子类类型(有风险,可能出现数据溢出)。
如果要进行类型转换,我们最好使用instanceof运算符来判断是否是继承关系,再进行强制转换。
instanceof运算符
利用if语句和instanceof运算符来判断两个对象的类型是否一致。
instanceof 与 getClass()的区别
Instanceof进行类型检查规则是:你属于该类吗?或者你属于该类的派生类吗?
getClass获得类型信息采用==来进行检查是否相等的操作是严格的判断,不会存在继承方面的考虑;
抽象类
1. 抽象类前使用abstract关键字修饰,表示该类为抽象类,
2. 抽象类不能被实例化,只能被子类实现抽象方法,才能对子类进行实例化
3. 抽象类定义抽象方法,只有声明,不需要实现。抽象方法没有方法体以分号结束,抽象方法必须用abstract关键字来修饰
4. 类中包含抽象方法的就是抽象类。抽象类中可以包含普通的方法,也可以没有抽象方法
接口
接口由全局常量和公共的抽象方法所组成
- 接口是把隐式公共方法(只能是抽象方法)和属性(静态属性)组合起来封装特定功能的一个集合
- 类实现接口,实现接口使用implements关键字,类就可以支持接口所指定的所有属性和成员
- 接口里全是抽象方法,不允许提供出现执行方式
- 一个类可以支持多个接口
java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以补充。
extends关键字在前implements关键字在后
接口在使用过程中还经常和匿名内部类配合使用。匿名内部类就是没有没名字的内部类,多用于关注实现而不关注实现类的名称。
抽象与接口的区别
语法层面上的区别
1. 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3. 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
设计层面上的区别
1. 抽象类作为很多子类的父类,它是一种模板式设计
2. 接口是一种行为规范,它是一种辐射式设计
3. 对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更
4. 对于接口,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
类、抽象类、接口
类是对对象的抽象
抽象类是对类的抽象
接口是对行为的抽象