final 与 static 的区别?
一、含义和作用
- final:
- 表示最终的、不可改变的。
- 用于修饰变量时,该变量成为常量,其值不能被修改。
- 用于修饰方法时,该方法不能被重写。
- 用于修饰类时,该类不能被继承。
- static:
- 表示静态的,与类相关而不是与类的实例相关。
- 用于修饰变量时,该变量为类变量,所有的实例共享这个变量。
- 用于修饰方法时,该方法为类方法,可以直接通过类名调用,而不需要创建类的实例。
二、存储位置和生命周期
- final修饰的变量:
- 如果是基本数据类型,其值存储在栈中或常量池中,具体取决于变量的声明位置和初始化方式。一旦初始化,其值在整个程序执行过程中保持不变。
- 如果是引用类型,其引用存储在栈中,指向的对象存储在堆中。但该引用不能再指向其他对象。
- static修饰的变量:
- 存储在方法区中,与类的生命周期相同,即从类被加载到内存中开始,到类被卸载为止。
三、使用场景
-
final:
- 当你希望一个变量的值在初始化后不能被改变,或者一个方法不能被重写,或者一个类不能被继承时,可以使用final。
- 例如,定义常量、防止方法被意外重写以确保特定的行为、或者设计不可扩展的类。
- 例如,定义数学常量PI可以使用
final double PI = 3.14159;
。
- 当你希望一个变量的值在初始化后不能被改变,或者一个方法不能被重写,或者一个类不能被继承时,可以使用final。
-
static:
- 当你希望一个变量或方法与类本身相关而不是与特定的实例相关时,可以使用static。
- 例如,工具类中的方法通常是静态的,因为它们不需要创建类的实例就可以使用。
- 例如,Math类中的方法都是静态的,如Math.sqrt()用于计算平方根,不需要创建Math类的实例就可以直接调用。
- 当你希望一个变量或方法与类本身相关而不是与特定的实例相关时,可以使用static。
总结
可变性 | 继承与重写 | 访问方式 | 内存分配 | |
---|---|---|---|---|
final | 定义不可变的变量 | 不能被继承和重写 | 变量、方法和类可以通过对象实例或类名访问(取决于它们的访问修饰符) | 分配在堆(对象实例)或栈(局部变量)上 |
static | 与可变性无关,它定义的是类的共享成员 | 不能被重写,但可以被子类隐藏 | 通过类名访问,不需要创建对象实例 | 存储在方法区中,只有一份 |