代码块
代码块是 Java 中用大括号 {} 包围的代码区域,分为静态代码块和实例代码块。
静态代码块
基本语法
java
public class StaticBlockDemo {
static {
System.out.println("静态代码块 - 类加载时执行");
}
public StaticBlockDemo() {
System.out.println("构造方法");
}
public static void main(String[] args) {
System.out.println("--- 创建第一个对象 ---");
new StaticBlockDemo();
System.out.println("--- 创建第二个对象 ---");
new StaticBlockDemo();
}
}输出:
静态代码块 - 类加载时执行
--- 创建第一个对象 ---
构造方法
--- 创建第二个对象 ---
构造方法特点
- 只执行一次:类加载时执行,无论创建多少对象
- 用于初始化静态资源:加载配置文件、初始化数据库连接等
java
public class DatabaseConnection {
private static String url;
private static String username;
private static String password;
// 静态代码块:初始化静态资源
static {
Properties props = new Properties();
try {
props.load(new FileInputStream("db.properties"));
url = props.getProperty("db.url");
username = props.getProperty("db.username");
password = props.getProperty("db.password");
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
}实例代码块
基本语法
java
public class InstanceBlockDemo {
private String name;
// 实例代码块:每次 new 都执行
{
System.out.println("实例代码块执行");
this.name = "default";
}
public InstanceBlockDemo() {
System.out.println("构造方法");
}
public InstanceBlockDemo(String name) {
this.name = name;
System.out.println("带参构造方法");
}
public static void main(String[] args) {
System.out.println("--- 创建第一个对象 ---");
new InstanceBlockDemo();
System.out.println("--- 创建第二个对象 ---");
new InstanceBlockDemo("自定义");
}
}输出:
--- 创建第一个对象 ---
实例代码块执行
构造方法
--- 创建第二个对象 ---
实例代码块执行
带参构造方法特点
- 每次 new 都执行:创建几个对象,就执行几次
- 在构造方法之前执行:实际执行顺序是:实例代码块 → 构造方法
- 可以访问实例成员:包括
private成员
执行顺序
当一个类有静态代码块、实例代码块和构造方法时:
java
public class ExecutionOrderDemo {
// 静态代码块
static {
System.out.println("1. 静态代码块");
}
// 实例代码块
{
System.out.println("2. 实例代码块");
}
// 构造方法
public ExecutionOrderDemo() {
System.out.println("3. 构造方法");
}
public static void main(String[] args) {
System.out.println("=== 创建第一个对象 ===");
new ExecutionOrderDemo();
System.out.println("=== 创建第二个对象 ===");
new ExecutionOrderDemo();
}
}输出:
1. 静态代码块
=== 创建第一个对象 ===
2. 实例代码块
3. 构造方法
=== 创建第二个对象 ===
2. 实例代码块
3. 构造方法父子类执行顺序
当涉及继承时,顺序更复杂:
java
class Parent {
static {
System.out.println("父类静态代码块");
}
{
System.out.println("父类实例代码块");
}
public Parent() {
System.out.println("父类构造方法");
}
}
class Child extends Parent {
static {
System.out.println("子类静态代码块");
}
{
System.out.println("子类实例代码块");
}
public Child() {
System.out.println("子类构造方法");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("=== 创建子类对象 ===");
new Child();
}
}输出:
=== 创建子类对象 ===
父类静态代码块
子类静态代码块
父类实例代码块
父类构造方法
子类实例代码块
子类构造方法完整顺序:
1. 父类静态代码块
2. 子类静态代码块
3. 父类实例代码块
4. 父类构造方法
5. 子类实例代码块
6. 子类构造方法实际应用
1. 初始化配置
java
public class AppConfig {
private static Properties properties;
static {
properties = new Properties();
try {
properties.load(AppConfig.class.getClassLoader()
.getResourceAsStream("config.properties"));
} catch (IOException e) {
throw new RuntimeException("加载配置文件失败", e);
}
}
public static String get(String key) {
return properties.getProperty(key);
}
}2. 注册监听器
java
public class EventBus {
private static final List<EventListener> listeners = new ArrayList<>();
static {
// 类加载时注册默认监听器
listeners.add(new DefaultListener());
listeners.add(new LoggingListener());
}
public static void register(EventListener listener) {
listeners.add(listener);
}
}3. 初始化日志环境
java
public class LoggerFactory {
private static boolean initialized = false;
static {
// 初始化日志框架配置
System.setProperty("java.util.logging.config.file", "logging.properties");
initialized = true;
}
public static Logger getLogger(Class<?> clazz) {
return Logger.getLogger(clazz.getName());
}
}注意事项
1. 静态代码块只执行一次
java
public class Test {
static {
System.out.println("静态代码块");
}
public static void main(String[] args) {
Test t1 = new Test();
Test t2 = new Test();
Test t3 = new Test();
// 静态代码块只输出一次
}
}2. 静态代码块在类加载时执行
类加载发生在:
- 创建对象时
- 调用静态方法时
- 子类加载时(会先加载父类)
3. 静态代码块抛异常会导致类加载失败
java
public class BadClass {
static {
// 如果这里抛异常,整个类都无法使用
throw new Error("初始化失败");
}
}代码块 vs 构造方法
| 对比项 | 静态代码块 | 实例代码块 | 构造方法 |
|---|---|---|---|
| 执行时机 | 类加载时 | 每次 new | 每次 new |
| 执行次数 | 一次 | 每次 | 每次 |
| 能访问什么 | 静态成员 | 所有成员 | 所有成员 |
| this/super | ❌ | ✅ | ✅ |
总结
类加载 → 静态代码块
↓
new 对象 → 实例代码块 → 构造方法- 静态代码块:类加载时执行一次,用于初始化静态资源
- 实例代码块:每次 new 都执行,在构造方法之前
- 两者都可以用于初始化,但各有适用场景
