三大特性:封装、继承、多态
封装
- 数据没有任何校验方法---->private私有的---->被private修饰的内容只能在本类中使用
- 使用set、get来设置、访问私有属性
- 赋值:对象名 .set 属性名(值); 取值:对象名 .get属性名();
- 对类进行封装要求:
- 所有的属性私有化---->用private修饰
- 为私有化的属性提供公开的 get/set 方法
- 封装必要性—>保证数据的安全性,对外屏蔽功能实现的细节,让用户更关注提供的功能。
继承
-
体现的是“ A is - a B ”关系,如果成立,则成称A 继承 B---->A为子类,B为父类
-
语法:class 子类类名 extends 父类类名{ }
-
通过继承机制,子类可以直接使用父类中的属性和成员方法。---->体现了代码的复用性和扩展性
-
在程序设计时,继承是类之间本身存在的一种关系,不能泛滥使用继承
覆盖(override)—>又称为方法的重写
- 在子类中定义了和父类相同的方法。
重载—>overload | 覆盖—>override | |
---|---|---|
方法名相同,形参列表不同(顺序,个数,类型) | 方法名、形参列表、返回值和父类相同 | |
发生位置 | 本类和本类或本类和父类之间 | 父类和子类之间 |
修饰符 | 与修饰符无关 | 访问修饰符和父类相同或者比父类更宽 |
-
如果子类覆盖了父类中方法,则优先使用子类覆盖后的方法。
-
注意:
- 如果子类中方法名、形参列表和父类的相同,但是返回值不同,编译报错
- 当父类为private时,子类可以再声明一个同名方法,因为private父类对子类不可见
- 如果子类中方法的方法名和父类相同,但是形参列表不同,则是特殊的方法重载(无需关注返回值类型)
- 如果子类中方法名、形参列表和父类的相同,但是返回值不同,编译报错
-
Java中的类之间为单继承关系,一个类只能有一个直接父类,但是可以有多个间接父类(多级继承)
- 一个父类可以同时具有多个子类
-
子类与父类:
-
构造方法:父类的构造方法不能被子类继承
—>根据构造方法概念—>构造方法名==类名
—>子类中的信息相对父类要多,所以父类的构造方法可能无法满足子类的需求,所以需要根据自身需求 来定义构造方法
-
属性、成员方法:由访问修饰符来决定父类能否由子类继承
- private修饰的属性和成员方法不能被继承
- default修饰的属性和成员方法同包子类可以继承
- protected修饰的属性和成员方法同包子类+非同包子类可以继承
- public修饰的属性和成员方法都可以继承
-
修饰符—>修饰属性、成员方法和构造方法
- private—>私有的
- default—>默认的—>访问权限是隐含的,不能再写一次
- protected—>受保护的
- public—>公开的
本类 | 同包(子类+非子类) | 非同包(子类) | 其他(非同包的非子类) | |
---|---|---|---|---|
private | 可以访问 | NO | NO | NO |
default | 可以访问 | 可以访问 | NO | NO |
protected | 可以访问 | 可以访问 | 可以访问 | NO |
public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
- class类 前只有两个访问权限:public和default(不写即default)
super
-
super. :应用在子类的构造方法或是成员方法中,代表访问当前父类对象的属性或是成员方法
- super.属性名:访问父类的属性
- super.成员方法名(实参):访问父类的成员方法
-
super()
- 创建子类对象时,JVM会自动创建一个父类对象,且调用的无参构造方法
- 只能应用在子类的构造方法第一行有效语句,代表指示JVM创建子类对象默认创建父类的哪一个构造方法完成父类对象的创建。
- super():代表创建父类对象采用无参数的构造方法
- super(实参):代表创建父类对象采用有参数的构造方法
- 如果子类构造方法的第一行没有super()/super(实参)的应用,则JVM会在子类构造方法的第一行默认添加一个super()
- this()和super()冲突,不能同时存在
- 如果子类构造方法第一行被this()占用,则JVM会去this()指向的构造方法去查找super()
-
JVM默认添加的内容:
- 一个类中没有定义任何的构造方法,JVM默认添加一个公开的无参的构造方法
- 一个子类的构造方法第一行没有this() / this(实参) / super() / super(实参) ,JVM默认添加super()
- 在本类的方法中访问本类的属性名或成员方法,则JVM默认添加this. —>若成员变量和局部变量命名冲突,不再默认添加this .
- 如果一个类、属性、方法没有写访问修饰符,默认为default访问权限
- 成员变量、数组,JVM会根据数据类型分配对应的默认值。
-
带有继承父关系的创建对象过程:创建子类对象,JVM默认创建一个父类对象
- 分配空间(子类+所有父类空间):属性赋予默认值
- 先完成父类对象的创建:(递归的完成父类对象的创建)
- 初始化父类属性
- 执行父类的构造方法(子类构造方法的第一行super() / super(实参)决定)
- 再完成子类对象的创建:
- 初始化子类的属性
- 执行子类的构造方法(取决于new后面的构造方法)
-
创建子类对象会导致所有的父类对象创建---->直接父类或者间接父类
-
创建父类对象不会导致子类对象的创建
this | super | |
---|---|---|
. | 应用在本类的成员方法或者构造方法中,代表当前对象的属性或成员方法 this.通常可以省略,但是当成员变量和局部变量命名冲突时,this.可用来区分 | 应用在子类成员方法或者构造方法中,代表调用父类对象的属性或者成员方法 |
() | 应用在本类的构造方法中第一行有效语句,代表调用本类其他构造方法 | 应用在子类的构造方法中第一行有效语句,代表指示JVM创建子类对象时对象先默认创建父类对象时利用父类哪一个构造方法完成父类对象的创建 |
如果子类构造方法中没有this() / super()应用则JVM默认添加一个super() |
多态
- 父类型的引用指向子类型的对象---->父类型引用 = 子类型对象
- 以父类型的引用调用属性或方法,只能调用父类中定义的属性或方法。---->编译校验
- 运行时,JVM会自动检测子类是否覆盖父类中的方法,如果覆盖,执行子类。反之,执行父类。
引用之间的转换
-
将父类型的引用赋值给子类型的引用,通过强制类型转换—>大类型给小类型—>向下转型
-
Animal a = new Dog();
Dog d = (Dog) a;
- 通过强制类型转换将父类型引用强转为子类型的引用,编译一定通过,但是运行可能因为实际存储对象类型和要转换的类型不一致导致运行失败—>java.lang.ClassCastException(类型转换异常)
- 引用中实际存储对象类型不会随着强制类型转换而发生变化
-
-
子类型的引用赋值给父类型的引用,直接赋值,无需强转—>小类型给大类型—>体现多态—>向上转型
-
没有继承关系的两个引用不允许相互转换,强转也不通过—>编译就报错
instanceof
-
引用名 instanceof 类名—>判断引用中存储的实际对象类型是否兼容于后面类型 ( 判断引用中存储的对象是不是后面的一种,是—>true,不是—>false )
-
多态可以屏蔽不同子类之间的差异性,对子类统一进行管理和操作。也是程序更加灵活通用
- 应用在数组上:本类型对象 + 所有子类型的对象都可以作为元素进行存储
- 应用在形式参数上:本类型 + 所有的子类型的对象都可以作为实际参数进行传递
- 应用在返回值上:本类型 + 所有的子类型对象都可以作为返回值返回