一、封装性
1、为什么要引入封装性
-
- 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合 :仅对外暴露少量的方法用于使用
- 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想
2、封装性的体现
-
- ① 私有化(private)类的属性xxx,同时提供公共的(public)设置(setXxx())和获取(getXxx())的方法
-
- ② 不对外暴露私有的方法,我们可以设置为private
- ③ 如果不希望类在包外被调用,可以将类设置为缺省的
- ④ 单例模式(将构造器私有化):饿汉模式与懒汉模式
3、四种权限修饰符:封装性的体现,需要权限修饰符来配合
-
- 从大到小:private < 缺省 < protected < public
- 权限修饰符可修饰的结构:① 4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类;② 只能使用缺省或者public来修饰类
- 修饰范围
总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小
二、继承性
1、为什么有继承
-
- 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可
2、继承的优点
-
- ① 减少了代码的冗余,提高了复用性
- ② 具有更好的扩展性,继承的出现让类与类之间产生了关系,提供了多态的前提
- ③ 继承的出现,更有利于功能的扩展
- 注:不能为了继承而去继承,不要仅为了获取其他类中某个功能而去继承
3、继承的格式:class A extends B{}
-
- A:子类、派生类、subclass
- B:父类、超类、基类、superclass。子类直接继承的父类,称为:直接父类;间接继承的父类称为:间接父类
4、继承的规则
-
- 一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法
- 子类不能直接访问父类中私有的(private)的成员变量和方法
-
-
父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已
- 父类私有属性,可以通过get、set方法,子类间接调用
-
父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已
-
-
- 父类私有方法,子类可以通过其他公共方法间接调用
-
5、继承性说明
-
- ① 子类和父类是相对的概念,父类又继承自己的父类,所有的类直接或间接的继承于java.lang.Object类
- ② 子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展
- ③ 一个父类可以有多个子类,但子类只能声明一个父类:Java类的单继承性
- ④ 如果一个类没有显式继承另外一个类的话,则其父类为:java.lang.Object类(根基类)
- ⑤ 任何一个类在继承java.lang.Object类之后,就获取了Object类中声明的属性和方法
- ⑥ Java中,继承是对父类的扩展,而不是父类的子集
6、子类对象实例化过程
-
-
从结果上来看:(继承性)
- 子类继承父类以后,就获取了父类中声明的属性或方法
- 创建子类的对象,在堆空间中,就会加载所有父类中声明的属性
-
从过程上来看:
- 实例化子类对象的过程中,间接或者直接的调用父类的构造器,或者父类的父类的构造器,... 直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用
- 注:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象
-
从结果上来看:(继承性)
三、多态性
1、多态的定义
-
- 可以理解为一个事物的多种形态
2、多态的体现
-
-
广义上多态体现
-
① 方法的重载和方法的重写
- 对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”
- 对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”;方法的重写可以理解为多态性
- ② 子类对象的多态性
-
① 方法的重载和方法的重写
-
狭义上多态体现
- 子类对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用),可以直接应用在抽象类和接口上
-
广义上多态体现
3、多态的使用
-
-
虚拟方法调用
- 在编译期,只能调用父类中声明的方法,但在运行期,实际执行的是子类重写父类的方法
-
虚拟方法调用
-
-
- 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。多态属于运行时行为
- 总结:编译,看左边;运行,看右边。“看左边”:看的是父类的引用(父类中不具备子类特有的方法);“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
- 不能调用子类特有的方法,编译看左边
-
-
- 省去重载方法的使用:此处可以放入任何对象
-
- 举例:
4、多态性的使用前提
-
- ① 类的继承关系
- ② 方法的重写
- 注:对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)。对象.属性=父类中的属性值,不能调用子类特有的属性,编译看左边
四、向上/向下转型
1、向上转型:向上转型实际就是多态
2、向下转型
-
-
向下转型原因
- ① 由于子类的对象赋给了父类的引用,所以在编译时,只能调用父类声明的结构:属性和方法
- ② 内存中实际上是加载了子类特有的属性和方法,只有考虑向下转型才能调用子类特有的属性和方法
-
向下转型要求
- ① 向下转型使用强制转化符:()
-
向下转型原因
-
-
- ② 为了避免强转出现 Class Cast Exception 的异常,在强转前,建议使用instance of判断
-
instanceof关键字
-
作用:
- 判断关键字左边对象是否是关键字右边类/接口的对象/实现类的对象,如果是返回true,如果不是返回false
- 在向下转型时,为了避免ClassCastException,利用instanceof关键字进行判断
-
使用:
- a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false
-
作用:
-
-
-
-
- 如果 a instanceof A返回true,若类B是类A的父类,则 a instanceof B也返回true
-
-
-
-
-
- 如果 a instanceof A返回true,若类B是类A的子类,则 a instanceof B不一定返回true
-
-
练习
- 编译时通过,运行时不通过
-
-
-
- 编译通过,运行时也通过
-
-
-
- 编译不通过
-
3、注意问题
-
- ① 使用强制类型转换符,可能出现Class Cast Exception的异常
- ② 要求x所属的类与类A必须是子类和父类的关系,否则编译错误
4、类型转换
-
- 基本数据类型
-
- 类