Java中对象生命周期与初始化块的深入解析
立即解锁
发布时间: 2025-08-17 02:35:34 阅读量: 9 订阅数: 35 


Java编程基础与SCJP认证指南
### Java 中对象生命周期与初始化块的深入解析
#### 1. 异常处理与对象初始化
在 Java 编程中,对象初始化过程常伴随着异常处理。例如,在以下代码中:
```java
private int initMaxGuests() {
// (6)
if (occupancyPerRoom > 4)
throw new RoomOccupancyTooHighException();
return noOfRooms * occupancyPerRoom;
}
```
此代码定义了一个 `initMaxGuests` 方法,若 `occupancyPerRoom` 大于 4,就会抛出 `RoomOccupancyTooHighException` 异常。该异常在 `ExceptionsInInitializers` 类里被捕获并处理:
```java
public class ExceptionsInInitializers {
public static void main(String[] args) {
try { new Hotel(); }
catch (RoomOccupancyTooHighException exception) {
exception.printStackTrace();
}
}
}
```
运行程序时,若出现异常,会输出异常信息和堆栈跟踪。
#### 2. 静态初始化块
Java 允许在类中定义静态初始化块,主要用于初始化静态字段。其语法是关键字 `static` 后接一个可包含任意代码的局部块。例如:
```java
class StaticInitializers {
final static int ROWS = 12, COLUMNS = 10;
static long[][] matrix = new long[ROWS][COLUMNS];
static {
for (int i = 0; i < matrix.length; i++)
for (int j = 0; j < matrix[i].length; j++)
matrix[i][j] = 2*i + j;
}
}
```
当 `StaticInitializers` 类首次加载时,会先初始化静态字段,接着创建 `matrix` 数组,最后执行静态初始化块中的代码。
静态初始化块有如下特点:
- 不在任何方法内,一个类可包含多个静态初始化块。
- 不是类的成员,不能有返回语句,也不能直接调用。
- 类初始化时,静态字段声明里的初始化表达式和静态初始化块按类中指定顺序执行。
- 静态初始化块中不能出现 `this` 和 `super` 关键字,因为它定义的是静态上下文。
静态初始化块在进行前向引用时,要遵循“先声明后使用”规则。例如:
```java
public class StaticForwardReferences {
static {
sf1 = 10;
int b = sf1 = 20;
int c = StaticForwardReferences.sf1;
}
static int sf1 = sf2 = 30;
static int sf2;
int if1 = 5;
static {
int d = 2 * sf1;
int e = sf1 = 50;
}
public static void main(String[] args) {
System.out.println("sf1: " + StaticForwardReferences.sf1);
System.out.println("sf2: " + StaticForwardReferences.sf2);
}
}
```
在这个例子中,`sf1` 的赋值操作是合法的,但在声明前读取其值则不被允许。
静态初始化块的异常处理和静态初始化表达式类似,未捕获的检查异常不能抛出,必须在块内捕获并处理。例如:
```java
class BankrupcyException extends RuntimeException {}
class TooManyHotelsException extends Exception {}
class Hotel {
private static boolean bankrupt = true;
private static int noOfHotels = 11;
private static Hotel[] hotelPool;
static {
try {
if (noOfHotels > 10)
throw new TooManyHotelsException();
} catch (TooManyHotelsException e) {
noOfHotels = 10;
System.out.println("No. of hotels adjusted to " + noOfHotels);
}
hotelPool = new Hotel[noOfHotels];
}
static {
if (bankrupt)
throw new BankrupcyException();
}
}
public class ExceptionInStaticInitBlocks {
public static void main(String[] args) {
new Hotel();
}
}
```
在这个例子中,第一个静态初始化块捕获并处理了 `TooManyHotelsException` 异常,第二个静态初始化块抛出了 `BankrupcyException` 异常,该异常由默认异常处理器处理,导致程序终止。
#### 3. 实例初始化块
Java 提供了实例初始化块,用于在对象创建时初始化字段,其作用和构造函数类似。语法和局部块相同,每次创建类的实例时都会执行。例如:
```java
class InstanceInitializers {
long[] squares = new long[10];
{
for (int i = 0; i < squares.length; i++)
squares[i] = i*i;
}
}
```
每次创建 `InstanceInitializers` 类的实例时,会先创建 `squares` 数组,再执行实例初始化块中的代码。
实例初始化块也有一些规则:
- 不在任何方法内,一个类可包含多个实例初始化块,实例字段声明里的初始化表达式和实例初始化块按类中指定顺序执行。
- 实例初始化块不能对违反“先声明后使用”规则的字段进行前向引用。
- 可使用 `this` 和 `super` 关键字引用当前对象,不能有返回语句。
- 可用于提取通用初始化代码,在匿名类中很有用,因为匿名类不能声明构造函数,可使用实例初始化块初始化字段。
实例初始化块的异常处理和静态初始化块类似,但执行实例初始化块可能产生未捕获的检查异常,前提是该异常在类的每个构造函数的 `throws` 子句中声明。匿名类的实例初始化块更自由,可抛出任何异常。例如:
```java
class RoomOccupancyTooHighException extends Exception {}
class BankrupcyException extends RuntimeException {}
class Hotel {
private boolean bankrupt = true;
private int noOfRooms = 215;
private int occupancyPerRoom = 5;
private int maxNoOfGuests;
{
try {
if (occupancyPerRoom > 4)
throw new RoomOccupancyTooHighException();
} catch (RoomOccupancyTooHighException exception) {
System.out.println("ROOM OCCUPANCY TOO HIGH: " + occupancyPerRoom);
occupancyPerRoom = 4;
}
maxNoOfGuests = noOfRooms * occupancyPerRoom;
}
{
if (bankrupt)
throw new BankrupcyException();
}
}
public class ExceptionsInInstBlocks {
public static void main(String[] args) {
new Hotel();
}
}
```
在这个例子中,第一个实例初始化块捕获并处理了 `RoomOccupancyTooHighException` 异常,第二个实例初始化块抛出了 `BankrupcyException` 异常,由运行时系统处理。
#### 4. 构建对象初始状态
对象初始化是使用 `new` 运算符创建对象时构建其初始状态的过程。步骤如下:
1. 先将字段初始化为默认值。
2. 调用构造函数,可能会导致构造函数的局部链式调用。
3. 局部链式调用中最后一个构造函数调用前,会进行以下操作:
- 隐式或显式调用超类构造函
0
0
复制全文
相关推荐










