java中static和const和final的区别
static 关键字
static 关键字用于声明类的成员(方法或变量)为静态成员。静态成员属于类本身,而不是类的实例。换句话说,静态成员可以通过类名直接访问,而不需要实例化对象。
- 静态变量:属于类的所有对象共享,类的所有实例共享相同的内存位置。
- 静态方法:可以在没有创建对象的情况下直接调用。
- 静态块:在类加载时执行一次,用于初始化类的静态成员。
- 编译时机:
static关键字主要在编译时确定。它告诉 JVM,该成员属于类而非实例,因此不需要通过对象来访问。static修饰的变量和方法会被加载到 方法区 中的 类的结构部分。 - 内存存储位置:
static成员存储在 方法区 中的 类的静态变量区。每个类只有一个静态变量区,所有实例共享这部分内存。静态方法也存储在方法区的 方法区(Method Area) 中。
count 是静态变量,在两个 Counter 对象中共享,displayCount 是静态方法,可以通过类名直接调用。
- class Counter {
- static int count = 0; // 静态变量
-
- Counter() {
- count++; // 每次创建对象时,静态变量 count 会增加
- }
-
- static void displayCount() {
- System.out.println("Count: " + count); // 静态方法可以直接访问静态变量
- }
- }
-
- public class Main {
- public static void main(String[] args) {
- Counter c1 = new Counter();
- Counter c2 = new Counter();
- Counter.displayCount(); // 调用静态方法,输出 Count: 2
- }
- }
java运行
final 关键字
final 是一个多用途的关键字,它可以用于变量、方法和类的定义,分别具有不同的含义。
- 用于变量:声明为
final的变量是常量,一旦赋值后不可更改(不可重新赋值)。 - 用于方法:声明为
final的方法不能被子类重写。 - 用于类:声明为
final的类不能被继承。 - 编译时机:
final关键字的使用在编译时就确定了变量、方法或类的行为。例如,如果一个方法被声明为final,编译器会禁止任何子类重写该方法;如果一个类被声明为final,编译器会禁止任何子类继承该类。对于变量,final确保该变量一旦赋值后不可修改。 - 内存存储位置:
- final 变量:常量(
final变量)通常在 方法区 中的 常量池(Constant Pool) 中存储。如果是局部变量,存储在栈中。 - final 类和方法:存储在 方法区 中的 类的结构部分。
final类和方法不会被继承或重写,因此它们在运行时不需要动态解析。
- final 变量:常量(
PI 被声明为 final,因此它的值不能更改。
- // final 变量
- class Circle {
- final double PI = 3.14159; // 常量,值不可更改
-
- void calculateArea(double radius) {
- double area = PI * radius * radius; // 使用常量
- System.out.println("Area: " + area);
- }
- }
-
- public class Main {
- public static void main(String[] args) {
- Circle circle = new Circle();
- circle.calculateArea(5);
- // PI = 3.14; // 编译错误,无法修改 final 变量的值
- }
- }
java运行
const 关键字
在 Java 中,const 是一个保留关键字,但它并没有在语言中实现功能,实际上 Java 中并不使用 const 来定义常量。Java 提供了 final 来替代 const 的功能。
const在 Java 中没有实现任何功能。const关键字保留用于未来可能的用途,但目前不被使用。- 常量在 Java 中应该使用
final关键字来定义。 - 编译时机:虽然
const是 Java 中的保留关键字,但它并没有被实现。实际上,Java 没有使用const来定义常量。在 Java 中,我们通常使用final来定义常量。 - 内存存储位置:由于
const不被实际使用,它不会在内存中占用任何空间。任何常量都应该使用final来定义,并存储在 方法区的常量池 或堆栈中。
使用 const 会导致编译错误,因为 const 在 Java 中并没有实际作用。
- // const 在 Java 中并不使用
- public class Main {
- public static void main(String[] args) {
- // const int x = 10; // 编译错误,const 不被使用
- }
- }
java运行
| 特性 | static | final | const |
| 定义 | 用于类的成员(方法、变量)指定该成员为静态的 | 用于变量、方法、类,表示常量、不允许修改或重写 | 目前在 Java 中没有实现 |
| 使用场景 | 当需要共享数据或功能时使用 | 用于常量、禁止继承/重写的方法、不可修改的变量 | Java 中不使用 const |
| 作用域 | 静态成员属于类,而不是实例对象 | 变量不可修改,方法不可重写,类不可继承 | 不被使用 |
| 示例 | static int count; | final int x = 10; | 不支持 |
| 静态方法 | 静态方法可以在没有实例化对象的情况下直接调用 | 不适用 | 不适用 |
| 继承/重写 | 静态成员可以被继承,但不可以被重写 | final 方法不能被重写,final 类不能被继承 | 不适用 |
| 关键字 | 编译时机 | 内存存储位置 | 说明 |
| static | 编译时 | 方法区 中的 类的静态变量区,静态方法也存储在方法区中 | static 成员属于类而非实例,所有实例共享这部分内存 |
| final | 编译时 | 方法区的常量池 或 堆栈(针对局部变量) | final 变量会存储在常量池中,final 方法和类存储在方法区 |
| const | 编译时 | 不会被使用 | const 是保留关键字,Java 没有实际应用,通常用 final 代替 |
完整示例
- class Person {
- static String species = "Homo sapiens"; // 静态变量
- final String name; // 常量,必须在构造方法中初始化
-
- Person(String name) {
- this.name = name;
- }
-
- // final 方法,不能被子类重写
- final void showDetails() {
- System.out.println("Name: " + name + ", Species: " + species);
- }
- }
-
- class Student extends Person {
- Student(String name) {
- super(name);
- }
-
- // 编译错误,无法重写 final 方法
- // void showDetails() {
- // System.out.println("Student: " + name);
- // }
- }
-
- public class Main {
- public static void main(String[] args) {
- Person person = new Person("Alice");
- person.showDetails(); // 调用父类的 final 方法
-
- // 通过类名访问静态变量
- System.out.println("Species: " + Person.species);
-
- // 修改静态变量
- Person.species = "Homo erectus";
- System.out.println("Updated Species: " + Person.species);
-
- // name = "Bob"; // 编译错误,final 变量不可修改
- }
- }
java运行
Java 内存区的详细说明
1.方法区(Method Area)
- 存放内容:类的结构(包括类的元数据)、静态变量、常量池、方法代码等。
- 静态成员和常量:
static成员变量和final常量通常存储在方法区中。静态方法也存储在方法区。常量则会存放在类的常量池(Constant Pool)中。
2.堆(Heap)
- 存放内容:对象实例、数组、类的实例等。
final变量(如果是对象引用):如果final变量是引用类型,则它的引用会存放在栈中,但对象本身会存放在堆中。
3.栈(Stack)
- 存放内容:局部变量、方法调用信息、操作数栈等。
final局部变量:局部变量(如方法参数)如果是final,则存储在栈上。
4.程序计数器(Program Counter Register)
- 存放内容:每个线程都有一个程序计数器,指向当前执行的字节码指令。
final修饰的局部变量(参数):存储在栈上,而栈本身不直接与程序计数器相关联。
5.本地方法栈(Native Method Stack)
- 存放内容:存放 native 方法的调用信息。
</div>
原文链接:https://blog.csdn.net/yyfloveqcw/article/details/144936639

浙公网安备 33010602011771号