1. final 关键字
final 可以修饰类,成员变量,成员方法,局部变量
1.1 final 修饰成员变量
final 修饰的成员变量要求必须进行初始化操作
1. 直接初始化赋值
2. 【有参】数构造方法,实例化对象过程中初始化 final 修饰成员变量
final 修饰的成员变量一旦被赋值无法二次修改
1.2 final 修饰成员方法
final 修饰成员方法不允许被子类重写,一般用于框架,业务核心代码内容修饰,不允许修改/重写代码内容
1.3 final 修饰类
final 修饰类没有子类,在开发中基本类型不允许继承重新定义/制定规则。
1.4 final 修饰局部变量
final 修饰的局部变量首次赋值允许,后期不允许二次赋值
【注意】
final 修饰引用数据类型变量,指向不可变,指向数据空间内容可变
从底层逻辑分析,final 修饰的为引用数据类型变量,当前变量存储数据不可变,变量存储内容是一个【地址】,表示地址无法修改,但是对应地址指向的数据空间内容,没有被 final 修饰,可以修改数据内容。
1.5 final 使用总结
①final 修饰类一般是架构中的底层核心代码,基本数据类型
② final 修饰成员变量一般用于常量使用,并且在开发中大量存在,例如: 订单状态,用户状态,设备状态
③ final 修饰局部变量一般用于常量数据使用,同时是为了避免【生命周期问题】。
④ final 修饰成员方法是核心业务逻辑方法
2. static【重点 难点】
2.1 类加载【重点】
程序所需资源加载过程
游戏加载:在游戏开始之前,需要加载游戏的相关资源(地图,角色,角色皮肤,角色特效,网络情况...)。在游戏开始之前完成的工作。
类加载同理:JVM 会根据当前程序运行所需,加载所有的类文件(.class 文件),程序准备阶段,并且在准备阶段过程中,会执行加载【static】修饰相关内容。
> 【核心】
三个重点:静态成员变量,静态成员方法,静态代码块
一个原则: 类加载过程中 static 修饰内容完成准备工作
【没有对象】
2.2 static 修饰静态变量
语法特征:
1. static 修饰的静态成员变量在内存的【常量池】
2. static 修饰的静态成员变量在整个代码的运行周期中有且只有一个。
3. static 修饰的静态成员变量在类文件加载阶段,需要准备就绪,已具备数据提供能力和数据存储能力。
4. static 修饰的静态成员变量别名【类变量】,语法建议直接通过类名操作
5. 【使用建议】
静态成员变量最好不要和类对象有相关性。
静态成员变量生命周期从类加载开始到程序结结束,类对象是从实例化对象开始,到 JVM GC 回收结束。可以实例化对象相当于程序开始运行,晚于静态成员变量加载GC 收回是在程序退出之前,完成内存收回工作之后,静态成员变量销毁。
2.3 static 修饰静态成员方法
语法特征:
1. 静态成员方法使用 static 修饰
2. static 修饰的静态成员方法不允许使用类内的【非静态成员】
3. static 修饰的静态成员方法可以直接使用类内的其他静态资源。
4. 静态成员方法常用于【工具类】方法封装 如:Arrays
5. 静态成员方法推荐使用类名直接调用,可以摆脱类对象的限制,执行效率较高。无需考虑对象实例化过程,以及销毁对象过程的时间和内存空间的占用浪费。
2.4 static 修饰静态代码块
1. 静态代码块在类文件加载阶段一定执行,并且只会执行一次。
2. 静态代码块可以调用类内的其他静态资源,不可以调用类内的非静态资源
3. 静态代码块一般用于程序初始化操作,预处理操作,项目运行前准备工作。\
在代码块中所有的静态 static 修饰内容平级,按照基础的从上到下顺序执行加载。并且每一个 static 修饰内容都需要执行完各自的需求。
> 静态代码块【执行/运行】
>静态成员变量 【具备数据存储和数据提供能力】
>静态成员方法 【具备执行能力】
>静态成员变量对于当前类而言有且只有一个,非静态成员变量属于每一个实例化对象,个数不限制。
static 面试题
class Father {
static {
System.out.println("Father 静态代码块");
}
static Father f = new Father();
public Father() {
System.out.println("Father 类构造方法");
}
}
class Son extends Father {
static {
System.out.println("Son 静态代码块");
}
static Father f = new Father();
public Son() {
System.out.println("子类构造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
/*
Father 静态代码块
Father 类构造方法
Son 静态代码块
Father 类构造方法
Father 类构造方法
子类构造方法
*/
}
}