Java中static与final关键字详解(简单易懂)

 更新时间:2026年01月30日 08:41:45   作者:莫问前路漫漫  
在Java中static和final是两个非常重要的关键字,它们各自具有独特的作用,当组合使用时,还可以产生额外的效果,这篇文章主要介绍了Java中static与final关键字的相关资料,需要的朋友可以参考下

一、static(静态关键字)

1. 核心概念

static修饰的成员(变量、方法、代码块、内部类)属于类本身,而不是类的某个实例(对象)。

  • 比喻:班级的公共饮水机(static),属于整个班级,所有同学(对象)都能使用,且只有 1 份;而每个同学的水杯(非 static),属于各自的实例,有多个副本。
  • 内存角度:static 成员在类加载时就被初始化,存放在方法区(而非堆内存),生命周期与类一致,直到 JVM 卸载该类。

2. 常见用法及示例

(1)static 变量(类变量)

  • 所有实例共享同一个 static 变量,修改一个实例的 static 变量,其他实例的该变量也会同步变化。
  • 访问方式:类名.变量名(推荐)或对象名.变量名(不推荐,易混淆)。
  • 命名规范:通常配合final使用(常量),全大写,下划线分隔;普通 static 变量小写开头。
public class Student {
    // 非static变量(实例变量):每个学生有独立的姓名
    private String name;
    // static变量(类变量):所有学生共享同一个班级名称,只有1份
    public static String className = "高一(1)班";

    public Student(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        Student s1 = new Student("张三");
        Student s2 = new Student("李四");

        // 访问static变量:推荐用类名访问
        System.out.println(Student.className); // 输出:高一(1)班
        // 修改static变量
        Student.className = "高一(2)班";
        // 所有实例的static变量都被修改
        System.out.println(s1.className); // 输出:高一(2)班
        System.out.println(s2.className); // 输出:高一(2)班
    }
}

(2)static 方法(类方法)

  • 属于类,无需创建对象即可调用(类名.方法名)。
  • 核心限制:不能直接访问非 static 成员(因为 static 方法没有this引用,无法指向具体实例),但可以访问 static 成员。
  • 典型场景:工具类方法(如Math.random()Arrays.sort())、工具性操作(如对象创建的静态工厂方法)。
public class Calculator {
    // static方法:无需创建Calculator对象即可调用
    public static int add(int a, int b) {
        // 可以访问static成员,不能访问非static成员
        return a + b;
    }

    // 非static方法:必须创建对象才能调用
    public int subtract(int a, int b) {
        return a - b;
    }

    public static void main(String[] args) {
        // 调用static方法:直接用类名
        int sum = Calculator.add(10, 20);
        System.out.println(sum); // 输出:30

        // 调用非static方法:必须创建对象
        Calculator cal = new Calculator();
        int diff = cal.subtract(20, 10);
        System.out.println(diff); // 输出:10
    }
}

(3)static 代码块

  • 类加载时执行,且只执行一次(无论创建多少个实例)。
  • 用于初始化 static 变量(如加载配置、初始化静态资源)。
public class Config {
    public static String DB_URL;

    // static代码块:类加载时执行,初始化静态变量
    static {
        System.out.println("static代码块执行");
        DB_URL = "jdbc:mysql://localhost:3306/test";
    }

    public static void main(String[] args) {
        // 首次访问类,触发类加载,执行static代码块
        System.out.println(Config.DB_URL); // 输出:static代码块执行 + jdbc:mysql://localhost:3306/test
        // 再次创建实例,static代码块不会重复执行
        Config c1 = new Config();
        Config c2 = new Config();
    }
}

(4)static 内部类

  • 属于外部类本身,无需依赖外部类的实例即可创建。
  • 不能访问外部类的非 static 成员(只能访问 static 成员)。
public class OuterClass {
    private static String staticField = "静态字段";
    private String nonStaticField = "非静态字段";

    // static内部类
    public static class StaticInnerClass {
        public void print() {
            // 可以访问外部类的static成员
            System.out.println(staticField);
            // 错误:不能访问外部类的非static成员
            // System.out.println(nonStaticField);
        }
    }

    public static void main(String[] args) {
        // 创建static内部类:无需外部类实例
        OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
        inner.print(); // 输出:静态字段
    }
}

二、final(最终关键字)

1. 核心概念

final表示 “最终的、不可改变的”,修饰不同成员时,含义略有差异,但核心都是 “不可修改”。

  • 比喻:刻在石碑上的文字(final 变量)无法修改;密封的箱子(final 方法)无法被打开重写;绝版的书籍(final 类)无法再版(继承)。

2. 常见用法及示例

(1)final 变量(常量)

  • 一旦赋值,不可修改(引用类型变量:引用不可变,但对象内容可变)。
  • 初始化要求:
    • 局部 final 变量:声明时或使用前赋值即可;
    • 成员 final 变量:必须在声明时、构造方法、初始化块中赋值(三者选其一),且只能赋值一次。
  • 命名规范:final 常量(通常配合 static)全大写,下划线分隔(如PIMAX_VALUE)。
public class FinalDemo {
    // 1. 成员final变量:声明时直接赋值(推荐)
    private final String NAME = "张三";
    // 2. 成员final变量:构造方法中赋值
    private final int AGE;
    // 3. static final常量(类级常量,最常用)
    public static final double PI = 3.1415926;

    public FinalDemo(int age) {
        this.AGE = age; // 构造方法中初始化final变量
    }

    public static void main(String[] args) {
        FinalDemo demo = new FinalDemo(18);
        // 错误:final变量不可修改
        // demo.NAME = "李四";
        // demo.AGE = 20;

        // 引用类型final变量:引用不可变,但对象内容可变
        final StringBuilder sb = new StringBuilder("hello");
        sb.append(" world"); // 合法:修改对象内容
        System.out.println(sb); // 输出:hello world
        // 错误:引用不可变
        // sb = new StringBuilder("new");

        // static final常量:类名访问,不可修改
        System.out.println(FinalDemo.PI); // 输出:3.1415926
    }
}

(2)final 方法

  • 不能被子类重写(override),保证方法的逻辑稳定(如父类的核心业务逻辑不允许子类修改)。
public class Parent {
    // final方法:子类不能重写
    public final void sayHello() {
        System.out.println("Hello from Parent");
    }
}

public class Child extends Parent {
    // 错误:无法重写final方法
    // @Override
    // public void sayHello() {
    //     System.out.println("Hello from Child");
    // }

    public static void main(String[] args) {
        Child child = new Child();
        child.sayHello(); // 输出:Hello from Parent
    }
}

(3)final 类

  • 不能被继承(extend),保证类的完整性(如 Java 核心类StringMathInteger都是 final 类,避免被篡改)。
// final类:不能被继承
public final class FinalClass {
    public void print() {
        System.out.println("这是final类的方法");
    }
}

// 错误:无法继承final类
// public class SubClass extends FinalClass {
// }

三、static final 组合使用(最常用)

static final修饰的变量是类级常量,具备两大特性:

  • static:属于类,内存中只有 1 份,类加载时初始化;
  • final:一旦赋值,不可修改。
  • 典型场景:定义系统常量(如Math.PIInteger.MAX_VALUE)。
public class Constants {
    // 数据库连接常量
    public static final String DB_URL = "jdbc:mysql://localhost:3306/test";
    public static final String DB_USER = "root";
    public static final String DB_PWD = "123456";

    // 工具类:私有化构造方法,避免创建实例
    private Constants() {}
}

总结

  • static 核心:属于类而非实例,类加载时初始化,所有实例共享,可通过类名直接访问;常用于工具方法、共享变量、静态初始化。
  • final 核心:“不可变”,修饰变量则值 / 引用不可改,修饰方法则不可重写,修饰类则不可继承;常用于定义常量、保护核心逻辑 / 类结构。
  • static final:类级常量,内存唯一且不可修改,是 Java 中定义常量的标准方式。

到此这篇关于Java中static与final关键字的文章就介绍到这了,更多相关Java static与final关键字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • RocketMQ普通消息实战演练详解

    RocketMQ普通消息实战演练详解

    这篇文章主要为大家介绍了RocketMQ普通消息实战演练详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • SpringBoot中最常用的5个内置对象使用方法

    SpringBoot中最常用的5个内置对象使用方法

    这篇文章主要给大家介绍了关于SpringBoot中最常用的5个内置对象使用的相关资料,在学习springboot的过程中,发现了springboot非常多的优点和特性,需要的朋友可以参考下
    2023-08-08
  • springboot+vue实现阿里云oss上传的示例代码

    springboot+vue实现阿里云oss上传的示例代码

    文件上传是常用的功能,本文主要介绍了springboot+vue实现阿里云oss上传的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • MyBatis如何使用selectKey返回主键的值

    MyBatis如何使用selectKey返回主键的值

    这篇文章主要介绍了MyBatis如何使用selectKey返回主键的值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java实现二分搜索树的示例代码

    Java实现二分搜索树的示例代码

    二分搜索树是一颗二叉树,二分搜索树每个节点的左子树的值都小于该节点的值,每个节点右子树的值都大于该节点的值。本文将利用Java实现二分搜索树,需要的可以参考一下
    2022-03-03
  • MyEclipse设置Console输出到文件的实现方法

    MyEclipse设置Console输出到文件的实现方法

    下面小编就为大家带来一篇MyEclipse设置Console输出到文件的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • 利用Java更改PDF页面大小的操作指南

    利用Java更改PDF页面大小的操作指南

    在日常的软件开发中,我们经常会遇到处理 PDF 文档的需求,其中,调整 PDF 文件的页面大小是一个常见且重要的操作,本文将深入探讨在 Java 环境下如何高效、准确地调整 PDF 页面尺寸,需要的朋友可以参考下
    2025-08-08
  • 调用java.lang.Runtime.exec的正确姿势分享

    调用java.lang.Runtime.exec的正确姿势分享

    这篇文章主要介绍了调用java.lang.Runtime.exec的正确姿势,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 基于Spring Boot的Logback日志轮转配置详解

    基于Spring Boot的Logback日志轮转配置详解

    本篇文章主要介绍了基于Spring Boot的Logback日志轮转配置详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • jstl之map,list访问遍历以及el表达式map取值的实现

    jstl之map,list访问遍历以及el表达式map取值的实现

    下面小编就为大家带来一篇jstl之map,list访问遍历以及el表达式map取值的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论