final关键字的作用
final可以修饰变量,可以修饰类也可以修饰方法
修饰变量
修饰变量主要是为了防止变量值改变
- 修饰基本数据类型变量:变量的值将不再可变
- 修改引用类型的变量:变量的指向的地址不再可变(也就是不能再次初始化),但是需要注意,变量指向的地址虽然不能变,但是该地址上的数据是可以修改的,不代表该变量的值不能改变
import java.util.ArrayList;
public class FinalExample {
public static void main(String[] args) {
// 1. final基本类型(值不可变)
final int num = 10;
// num = 20; // 报错:不能修改final基本类型
// 2. final引用类型(引用不可变,对象内容可变)
final ArrayList<String> list = new ArrayList<>();
list.add("A"); // 允许修改内容
list.add("B");
// list = new ArrayList<>(); // 报错:不能修改final引用
System.out.println("数字:" + num);
System.out.println("列表:" + list);
}
}
修饰方法:
表明方法被锁定,没有任何类继承后能修改其含义
也就代表了子类不能重写该方法,同时JVM可能内联final方法的调用,提升效率
典型例子
- 关键算法(如加密算法)
修饰类
表明该类不可以被继承,类中的所有的成员方法都是final方法,成员变量不受影响
能防止子类篡改行为(攻击者通过继承破坏系统)
典型例子
- 工具类
- 不可变类(JDK包装类)
static关键字
static修饰变量
static关键字的主要作用就是为了创建类级别的共享变量
- 修饰基本数据类型:该变量被所有实例共享,内存中只有一份拷贝
- 修饰引用类型的变量:所有实例共享一个引用,指向同一个对象
public class StaticExample {
// static基本类型变量
static int count = 0;
// static引用类型变量
static ArrayList<String> sharedList = new ArrayList<>();
public static void main(String[] args) {
StaticExample obj1 = new StaticExample();
StaticExample obj2 = new StaticExample();
obj1.count = 5;
System.out.println(obj2.count); // 输出5,因为所有实例共享
obj1.sharedList.add("A");
System.out.println(obj2.sharedList); // 输出[A],共享同一个对象
}
}
static修饰方法
表明该方法是类方法,不需要创建任何的实例
- 可以直接通过类名调用,无需依赖任何实例
- 只能访问类的static成员,不能访问实例成员
典型例子
工具类方法(Math.max())
static修饰代码块
在类加载时,用于初始化static变量
- 只会执行一次
- 按照在类中编写的顺序执行
static {
// 初始化配置等操作
System.out.println("静态代码块执行");
}
static修饰内部类
创建不依赖于外部类实例的嵌套类
- 可以直接实例化,无需先实例化外部类
- 不能访问外部类非static成员
典型例子
工具类中的辅助类
补充:如果有static变量但是没有static修饰代码块来给static变量赋值可以吗
static变量有三种初始化方式,代码块只是其中一种:
- 声明时直接赋值
static int count = 0;
static List<String> names = new ArrayList<>();
- static代码块赋值
static int count;
static {
count = initializeCount(); // 可以调用方法进行复杂初始化
}
- 通过静态方法来初始化(static修饰的方法)
static int count;
static {
count = initializeCount(); // 可以调用方法进行复杂初始化
}