一、封装
1. 访问权限修饰符基础定义
private 代表私有权限,被它修饰的属性、方法仅能在当前类内部访问,外部任何类都无法直接访问操作。
public 代表公共权限,被它修饰的内容可以在项目任意位置、任意类中直接访问。
2. 封装的两大实现标准要求
第一点:类中的所有成员属性全部使用 private 修饰,实现属性私有化,隔绝外部直接读写。
第二点:为每一个私有属性对外提供公开的 get 获取方法与 set 赋值方法。
(1)get 读取方法标准写法
public 数据类型 get属性名(){
return this.属性名;
}
注意事项:方法返回值的数据类型,必须和对应私有属性的数据类型完全一致;方法命名规则为 get 拼接属性名,属性首字母大写。
(2)set 赋值方法标准写法
public void set属性名(数据类型 临时变量名){
this.属性名 = 临时变量名;
}
注意事项:方法形参的数据类型,必须和对应私有属性的数据类型保持一致;方法命名规则为 set 拼接属性名,属性首字母大写。
3. 封装完成后的使用方式
读取私有属性存储的数据:调用该属性对应的 get 方法。
修改私有属性存储的数据:调用该属性对应的 set 方法。
二、继承
1. 继承核心概念与基础语法
继承用来描述类和类之间的 is-a 从属关系,举例:小狗是一种动物、钢笔是一种文具、学生是一种人。
若A类是一种B类,就代表A类继承B类。
语法格式:class 子类名 extends 父类名{}
子类:也叫派生类,是继承父类资源的类;
父类:也叫基类,是被子类继承、存放通用内容的类。
继承本质是一种代码复用机制,子类可以直接使用父类中允许访问的属性和方法。
开发规范:不能强行使用继承,只有类之间天然存在is-a从属关系时,才适合使用extends关键字。
继承带来的开发优势:大幅提升代码复用性,同时增强程序的可扩展性。
2. 方法重写 override(开发与面试重点)
(1)概念:仅存在于父子继承关系中,在子类内部定义和父类同名、同参数列表的方法。
(2)重写必须满足的硬性要求
第一,子类重写方法的方法名、形参列表、返回值类型,必须和父类原方法完全一致;
第二,子类重写方法的访问修饰符权限,和父类相同或者比父类更宽泛,不能更严格。
(3)运行逻辑:使用子类类型引用调用方法时,会优先执行子类重写完成后的方法。
(4)易错区分说明
如果子类方法名、形参列表和父类全部一致,仅返回值类型不同,代码编译直接报错,不构成重写。
如果子类方法名、返回值类型和父类一致,仅形参列表存在差异,不属于重写,是方法重载。
思考题:分别简述方法重写 override 和方法重载 overload 的核心特点。
(5)应用场景:当父类继承过来的通用方法,无法满足子类自身独有的业务逻辑时,子类就可以重写该方法,实现专属功能。
3. 父类与子类信息定位
父类中存放的是所有子类都具备的、通用抽象的属性与行为;
子类中存放的是自身独有的、特殊具体的属性与行为。
4. Java语言继承独有特点
Java中类与类之间只支持单直接继承,一个子类只能拥有一个直接父类;
但支持多级间接继承,一个类可以拥有多层祖辈父类。
单继承设计简化了Java语法体系,降低程序逻辑复杂度。
5. 子类能够继承的内容划分
(1)构造方法不能被子类继承
第一,构造方法名称必须和当前类名完全相同,子类和父类类名不一样,天然不满足构造方法命名规则,因此无法继承。
第二,子类通常会新增独有的属性,初始化逻辑比父类更复杂,父类构造方法无法完成子类初始化需求,子类需要自定义专属构造方法。
(2)属性、普通成员方法能否继承,由访问修饰符决定(面试高频考点)
Java一共包含四类访问修饰符,分别是private、默认无修饰、protected、public。
四类修饰符均可用于修饰成员属性、成员方法、构造方法;
只有public和默认无修饰两种修饰符,可以用来修饰外部类。
各类修饰符的访问范围与继承规则:
private私有修饰:仅当前类内部可访问,完全不能被子类继承。
default默认无修饰:当前类、同包下所有类可访问,只有同包内的子类能够继承。
protected受保护修饰:当前类、同包类、所有包下的子类均可访问,任意包中的子类都能继承。
public公共修饰:项目中所有类均可访问,全部子类都能继承。
6. 存在继承关系时,对象完整创建流程(理解记忆)
第一步,分配堆内存空间,同时为子类、所有层级父类的全部属性赋予默认初始值。
第二步,递归完成所有父类对象的创建工作:先初始化父类属性(属性第二次赋值),再执行父类构造方法(属性第三次赋值)。
第三步,完成子类对象自身创建:先初始化子类独有属性(属性第二次赋值),再执行子类构造方法(属性第三次赋值)。
7. super关键字的两大使用场景(面试+开发重点)
(1)第一种用法:super() / super(实参)
使用位置:只能写在子类构造方法内部,作用是告知JVM创建子类对象时,优先调用指定的父类构造方法,完成父类对象创建。
super():调用父类无参数构造方法。
super(实参):调用父类带有对应参数的构造方法。
强制注意规则:
第一,super()、super(实参) 必须写在构造方法内部第一行有效代码位置。
第二,子类构造方法第一行没有手动写this()或super()相关代码,JVM会自动默认添加super()。
第三,同一个构造方法中,this()系列语句和super()系列语句不能同时出现。
第四,若子类构造方法首行写了this()相关语句,JVM会去this指向的构造方法第一行寻找super语句,不会在当前构造方法查找。
(2)第二种用法:super.
使用位置:子类的构造方法、普通成员方法内部都可以使用,代表调用当前对象所属父类的成员。
super.属性名:调用父类中定义的成员属性。
super.成员方法名(实参):调用父类中定义的普通成员方法。
面试简答题:简述this关键字和super关键字的区别。
8. JVM默认自动补充的四类隐藏代码总结
第一,在类的普通成员方法中,访问本类自身的属性、成员方法时,JVM会自动补充this.前缀。
第二,一个类中没有手动编写任何构造方法,JVM会自动添加一个公开、无参数的构造方法。
第三,子类构造方法首行没有手动写this()或super()语句,JVM会自动在构造方法第一行添加super()。
第四,代码中使用java.lang包下的类时,JVM会自动补充 import java.lang.对应类名; 导入语句。
三、多态
1. 多态核心概念(理解+应用)
(1)多态核心定义:父类类型的引用变量,指向子类创建的对象。
语法格式:父类类名 引用变量名 = new 子类类名(实参);
等号左侧引用的数据类型为父类类型,也叫主观类型;
等号右侧new创建的对象为子类类型,也叫实际类型。
(2)编译阶段规则:使用父类引用调用属性、成员方法时,编译器仅识别父类中定义过的属性和方法,父类不存在的内容无法调用。
(3)运行阶段规则:程序运行时JVM会自动检测子类是否重写了父类对应方法。如果存在重写逻辑,执行子类重写后的方法;如果没有重写,直接执行父类原本的方法。
2. 引用类型之间的相互转换(开发应用重点)
(1)向上转型:子类引用直接赋值给父类引用(多态的本质实现)
子类类型属于小范围类型,父类类型属于大范围类型,小范围可以直接赋值给大范围,无需强制转换。
语法格式:父类类名 引用变量 = 子类引用变量;
示例:Dog dog = new Dog(); Animal animal = dog;
(2)向下转型:父类引用赋值给子类引用,必须强制类型转换
大范围类型转小范围类型,语法格式:子类类名 引用名 = (子类类名)父类引用变量;
示例:Animal animal = new Dog(); Dog dog = (Dog)animal;
转型运行结果分两种情况:
情况一:父类引用实际存储的对象类型,和强制转换的子类类型完全匹配,编译正常通过,运行无报错。
情况二:父类引用实际存储的对象类型,和强制转换的子类类型不匹配,编译可以通过,运行直接抛出 java.lang.ClassCastException 类型转换异常。
举例:Animal animal = new Cat(); Dog dog = (Dog)animal;
补充注意:引用变量内部存储的实际对象类型,不会因为强制转换发生任何改变。
如何规避向下转型产生的类型转换异常?
使用 instanceof 关键字做类型预判。
语法格式:引用变量名 instanceof 类名
执行逻辑:对比引用中存储的实际对象类型,和instanceof后书写的类类型是否兼容。兼容匹配返回true,不匹配返回false。
使用场景:执行父类引用强制向下转型为子类引用前,先用instanceof判断类型是否匹配。
代码示例:
Animal a = new Dog();
if(a instanceof Cat){
Cat c = (Cat)a;
System.out.println("~~~转换成功~~~");
}
(3)无继承关系的两个类,引用之间不允许互相转换,即使书写强制转换语法,编译阶段直接报错。
示例:Animal animal = new Dog(); Person person = (Person)animal; 编译报错。
3. 多态在项目中的实际开发用途
第一,数组存储:父类数组,可以存放父类自身对象、以及所有它的子类对象。
第二,方法形参:方法形参定义为父类类型,调用方法时可以传入父类对象、任意子类对象作为实参。
第三,方法返回值:方法返回值定义为父类类型,方法内部可以返回父类对象、任意子类对象。
4. 多态编程带来的开发优势
第一,屏蔽各个子类之间独有的差异化实现逻辑,使用父类统一完成全部子类的管理操作。
第二,降低代码耦合度,让整体程序代码更灵活、通用性更强。