多态
多态情况下的方法调用:
- 虚拟方法调用:
子类当中定义了和父类同名同参数的方法,在多态的情况下,将此时父类的那个方法称之为"虚拟方法"
父类根据赋给他的不同子类对象,动态的调用该子类的方法,这样的方法调用在编译器是无法确定的,所以也被称之为动态绑定
- 关于多态当中方法重写的或者重载的问题:
重载:在同一个类当中,出现了方法名相同参数列表不同,与返回值无关。
编译器会根据方法的不同参数列表,对方法名进行标识修饰,对于编译器而言,这些同名的方法其实已经被划分不同的标识地址,他们在编译的时候
这种被称之为"静态绑定"/"早绑定"
对于多态的这种情况,如果存在了方法重写,因为编译器在编译的时候涉及到了N个类,他无法确定你究竟是调用哪个类,或者说是不是有进行重写。
因为类不是被同时加载,所以在类加载的时候根本无法确定你到底调用的是哪个类的哪个方法,只有你在运行的时候,才内确定你的内存空间是什么
这种被称之为"动态绑定"/"晚绑定"。
多态当成成员访问特点:
- 成员变量
当父类和子类具有相同的成员变量的时候,那么在多态的情况访问的是父类的成员变量
- 成员方法
当父类和子类存在相同的成员方法的时候,在多态的情况下默认方法的是父类的成员(但是因为方法重写的问题,所有最后输出的是子类的方法)
- 静态方法
当父类和子类存在相同的成员方法的时候,在多态的情况下,因为静态不存在重写的问题,所以访问的是父类的
除了考虑子类重写成员方法的问题,全部都是以父类为主。
多态的优点:
- 提高了代码的可维护性(继承提供)
- 提高了代码的扩展性(多态提供)
1、多态可以作为形参提供,接收更广的赋值范围,避免方法的形参过度重载
2、多态还可以作为返回值提供,返回更广的数据类型,避免因为不确定的返回数据而不能明确返回值的问题
instanceof操作符
x instanceof A:检查x是否为A类的对象,返回值为boolean类型
易错点:
x必须是A的直属类,或者是父子关系类,否则编译错误
这个操作符一般使用多态的向下转型当中,避免类型不同而操作类型转换失败
对象的类型转换
Java的对象的强制类型转换也被称之为造型转换
- 从子类转换父类直接进行自动转换
- 从父类到子类必须进行强制转换
Fu f = new Zi();
Zi z = (Zi)f;
- 无继承关系的情况下,所有引用数据的相互转换都是非法
- 在转换之前,如果代码复杂,建议您使用instanceof进行类型校验
抽象类
特点:
- 用abstract关键字来修饰一个类,这个类叫做抽象类
- 用abstract来修饰一个方法,该方法叫做抽象方法。
抽象方法:只有方法的声明,没有方法的实现。以分号结束(因为一个抽象方法,本身就不是一个具体,何必去写代码)
- 含有抽象方法的类必须被声明为抽象类。
- 抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写(可以用多态,利用其具体的子类来进行实例从而达到使用抽象)
- 不能用abstract修饰变量、代码块、构造器
- 不能用abstract修饰私有方法、静态方法、final的方法、final的类。
抽象类的子类
- 子类必须重新父类的所有抽象方法
- 象类子类依旧还可以是抽象类,那么就继续用abstract修饰子类就可以了,如果不是子类不是抽象类,就必须重写父类的所有抽象方法。
模板设计模式特点(抽象的体现):
- 定义一个骨架方法(固定的代码片段)
- 定义一个强制要求填充的代码片段(抽象方法)
- 调用骨架方法,此时也会要求其他人必须填充不固定的代码(继承和多态的前提)。
接口特点:
- 接口使用interface进行定义
interface 接口名{}
- 如果一个类需要实现一个接口,则使用implements
class 类名 implements 接口名{}
- 接口无法进行实例化
(可以使用具体的实现类来进行实例:Eraser e = new ClearPencil();)
接口和子类:
- 接口可以继承接口,但是意义不大 因为继承的还是一个接口
- 具体类可以实现接口,但是不能继承接口(具体类实现接口是推荐方案,一般只会这么做)
- 抽象类可以实现接口,但是不能继承接口
接口的成员特点:
- 成员变量:
只能定义常量,必须是静态常量
默认语法为:
public final static int num = 20;
- 成员方法:
只能是抽象方法
默认修饰符:
public abstract void show();
- 构造方法:
没有构造方法
因为对于接口来说,构造方法没有任何用途,因为没有任何数据需要进行初始化.
继承
-
继承的概念:
继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
-
继承的限制
一个子类只能够继承一个父类,存在单继承局限。
在一个子类继承的时候,实际上会继承父类之中的所有操作(属性、方法),但是需要注意的是,对于所有的非私有(no private)操作属于显式继承(可以直接利用对象操作),而所有的私有操作属于隐式继承(间接完成)。
在继承关系之中,如果要实例化子类对象,会默认先调用父类构造,为父类之中的属性初始化,之后再调用子类构造,为子类之中的属性初始化,即:默认情况下,子类会找到父类之中的无参构造方法。
继承和实现区别(类和接口的区别)
- 类和类:
继承关系(extends),而且只能是单继承
- 类和接口:
实现关系(implements),可以是多实现,而且可以继承一个类的时候,仍然可以实现多个接口
- 接口和接口:
继承关系,可以是单根继承,也可是多根继承
方法重写:
当父类数据无法满足子类需求的时候,声明了和父类方法一模一样的时候,被称之为方法重写(覆盖)
方法重写的注意事项:
- 父类的私有方法不能被重写
- 子类的重写方法必须保持和父类方法一模一样的返回值、命名、参数列表
- 子类的重写方法的访问权限不能小于父类(一般保持一致即可,不用刻意写成不一样)
- 如果存在static的修饰,则不存在重写的概念,重写的前提是子类继承了父类的方法,而两个方法的加载时候都应该属于对象调用
封装
封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。封装是一种信息隐藏技术,在java中通过关键字private实现封装。什么是封装?封装把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
评论