哈喽,刷题小伙伴们!Day4 关于异常体系的 finally 坑点是不是让你印象深刻?今天咱们攻克 Java 基础中极具实用性的考点 ——static 关键字,这题不仅考用法,还常结合类加载机制、对象实例化流程出题,是面试高频加分项,赶紧往下看!​

今日题目​

1.static 关键字的核心作用是什么?可修饰哪些元素?​

2.static 方法为什么不能调用非 static 成员(变量 / 方法)?​

3.静态代码块、构造代码块、构造方法的执行顺序是什么?​

一、基础答案​

1.static 关键字的核心作用​

  • 核心:属于类,不属于单个对象,实现 “资源共享”(静态成员被该类所有对象共用);​
  • 可修饰元素:​
  • 静态变量(类变量):类加载时初始化,存储在方法区,全局唯一;​
  • 静态方法(类方法):无需创建对象,直接通过 “类名。方法名” 调用;​
  • 静态代码块:类加载时执行,用于初始化静态变量或执行预处理操作;​
  • 静态内部类:独立于外部类对象,无需依赖外部类实例即可创建。

2.static 方法不能调用非 static 成员的原因​

  • 加载顺序:静态成员(方法 / 变量)在类加载时初始化,非 static 成员(实例变量 / 方法)在对象创建时初始化;​
  • 依赖关系:static 方法执行时,可能还未创建任何对象,而非 static 成员必须依附于具体对象存在,因此无法直接调用;​
  • 反例:非 static 方法可以调用 static 成员(因为类加载一定早于对象创建)。​

3.核心执行顺序(面试高频)​

当创建对象时,执行顺序为:​

静态代码块 → 构造代码块 → 构造方法​

  • 静态代码块:只执行一次(类加载时),多个静态代码块按定义顺序执行;​
  • 构造代码块:每次创建对象都执行,多个构造代码块按定义顺序执行;​
  • 构造方法:每次创建对象执行,根据创建对象时的参数匹配对应构造方法。​

二、深度拆解(面试加分项)​

1. 静态变量 vs 实例变量 底层区别​

特性​

静态变量(类变量)​

实例变量​

存储位置​

方法区(JDK8 后为元空间)​

堆内存(对象所属空间)​

初始化时机​

类加载时(首次使用类时)​

对象创建时(new 关键字触发)​

生命周期​

与类的生命周期一致(JVM 退出时销毁)​

与对象的生命周期一致(GC 回收时销毁)​

访问方式​

类名。变量名(推荐)、对象。变量名​

只能通过对象。变量名访问​

共享性​

该类所有对象共用​

每个对象独立拥有,互不影响​

class Student {
    static String school = "Java编程学院"; // 静态变量(所有学生共用)
    String name; // 实例变量(每个学生独立)

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

public class TestStatic {
    public static void main(String[] args) {
        Student s1 = new Student("张三");
        Student s2 = new Student("李四");
        
        System.out.println(s1.school); // 输出:Java编程学院
        System.out.println(s2.school); // 输出:Java编程学院
        
        Student.school = "Java面试训练营"; // 通过类名修改静态变量
        System.out.println(s1.school); // 输出:Java面试训练营(所有对象共享修改)
        System.out.println(s2.name); // 输出:李四(实例变量独立)
    }
}

2. 静态代码块的实战应用​

静态代码块常用于 “一次性初始化”(如加载配置文件、初始化工具类),示例:

// 工具类:加载数据库配置
class DBUtil {
    static String url;
    static String username;
    static String password;

    // 静态代码块:类加载时执行,只执行一次
    static {
        System.out.println("加载数据库配置...");
        url = "jdbc:mysql://localhost:3306/test";
        username = "root";
        password = "123456";
    }

    public static void connect() {
        System.out.println("连接数据库:" + url);
    }
}

public class TestDBUtil {
    public static void main(String[] args) {
        DBUtil.connect(); // 首次使用类,触发静态代码块执行
        DBUtil.connect(); // 再次调用,静态代码块不再执行
    }
}

输出结果:

加载数据库配置...
连接数据库:jdbc:mysql://localhost:3306/test
连接数据库:jdbc:mysql://localhost:3306/test

3. 静态内部类的核心特性​

  • 静态内部类不能访问外部类的非 static 成员(无外部类对象引用);​
  • 外部类可以访问静态内部类的所有成员(无论访问修饰符);​
  • 创建方式:外部类名.静态内部类名 实例 = new 外部类名.静态内部类名();(无需创建外部类对象);​
  • 应用场景:常用于工具类封装(如 HashMap 中的 EntrySet 静态内部类)。​

三、面试避坑提醒​

1.避免在静态方法中使用 this 或 super 关键字(this 指向当前对象,静态方法无对象关联);​2.静态变量线程不安全:多线程环境下修改静态变量,需加锁(如 synchronized)保护;​

2.静态代码块不能访问非 static 成员:类加载时实例变量还未初始化,直接访问会编译报错;​

3.不要滥用 static:静态成员生命周期长,过度使用可能导致内存泄漏(如静态集合缓存大量对象)。​

四、今日打卡​

评论区留下你的答案:以下代码的执行顺序和输出结果是什么?✅

class Person {
    // 静态代码块1
    static {
        System.out.println("静态代码块1");
    }

    // 构造代码块
    {
        System.out.println("构造代码块");
    }

    // 构造方法
    public Person() {
        System.out.println("无参构造方法");
    }

    // 静态代码块2
    static {
        System.out.println("静态代码块2");
    }
}

public class TestStaticOrder {
    public static void main(String[] args) {
        new Person();
        new Person();
    }
}

(提示:结合静态代码块、构造代码块、构造方法的执行顺序分析)​

文末预告​

Day6 预告:ArrayList 和 LinkedList 的核心区别!底层实现、性能对比、适用场景一次说透,带你吃透 Java 集合框架高频考点~明天继续刷题!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐