云计算百科
云计算领域专业知识百科平台

《Thinking in Java》读书笔记---初始化与清理

        随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一。


一、初始化机制深度解析

1.1 构造器核心原理

1.1.1 构造器本质特性
  • 命名强制要求:必须与类名完全相同(包括大小写)

  • 无返回值声明:不同于void方法,构造器完全不声明返回类型

  • 默认构造器规则:

    class MyClass {
    // 编译器自动添加的无参构造器(仅当没有显式定义任何构造器时)
    MyClass() {}
    }

1.1.2 构造器重载机制

class Person {
String name;
int age;

// 构造器1
Person() {
this("Unknown", 18); // 构造器委托
}

// 构造器2
Person(String name) {
this(name, 18);
}

// 构造器3(主构造器)
Person(String name, int age) {
this.name = name;
this.age = age;
}
}

1.1.3 构造器执行流程
  • 分配对象内存空间(堆内存)

  • 执行父类构造器(递归到Object)

  • 按声明顺序初始化成员变量

  • 执行构造器主体代码

  • 1.2 变量初始化策略

    1.2.1 成员变量初始化方式对比
    初始化方式语法示例执行时机特点
    声明时初始化 int x = 10; 构造器之前 简洁直观
    构造器初始化 MyClass() { x = 10; } 构造器执行时 灵活控制
    初始化块 { x = 10; } 构造器之前,与声明顺序相同 可处理复杂逻辑
    静态初始化 static { sVar = 5; } 类加载时 只执行一次
    1.2.2 初始化顺序示例

    class InitializationExample {
    // 静态变量
    static int staticVar = initStatic();

    // 静态初始化块
    static {
    System.out.println("静态初始化块");
    }

    // 实例变量
    int instanceVar = initInstance();

    // 实例初始化块
    {
    System.out.println("实例初始化块");
    }

    // 构造器
    InitializationExample() {
    System.out.println("构造器");
    }

    static int initStatic() {
    System.out.println("静态变量初始化");
    return 1;
    }

    int initInstance() {
    System.out.println("实例变量初始化");
    return 2;
    }
    }

            输出顺序:静态变量初始化、静态初始化块、实例变量初始化、实例初始化块、构造器


    二、清理机制深度剖析

    2.1 finalize()方法详解

    2.1.1 方法特性

    protected void finalize() throws Throwable {
    // 清理非内存资源
    super.finalize(); // 调用父类finalizer
    }

    2.1.2 执行机制
  • 触发条件:对象被GC判定为不可达时

  • 执行线程:由Finalizer守护线程执行(优先级低)

  • 执行保证:不保证一定会执行(程序可能提前终止)

  • 2.1.3 典型使用场景
    • 清理本地方法分配的内存(JNI)

    • 作为资源释放的最后保障(应优先使用try-with-resources)

    2.2 垃圾回收机制

    2.2.1 GC算法演进
    算法类型JDK版本特点适用场景
    标记-清除 早期 内存碎片化 简单场景
    标记-整理 1.2+ 消除碎片 老年代
    复制算法 1.3+ 空间换时间 新生代
    G1 Java 7+ 分区域收集 大内存应用
    ZGC Java 11+ 低延迟 实时系统
    2.2.2 对象生命周期管理


    三、方法重载深入探讨

    3.1 重载解析规则

    3.1.1 匹配优先级
  • 精确类型匹配

  • 基本类型自动扩展(char→int→long→float→double)

  • 包装类型自动装箱

  • 可变参数匹配

  • 3.1.2 典型歧义场景

    void f(int a, long b) {}
    void f(long a, int b) {}

    f(1, 1); // 编译错误!模糊调用

    3.2 可变参数机制

    3.2.1 底层实现

    // 源代码
    void printAll(String… args) {
    for (String s : args) System.out.println(s);
    }

    // 编译后等价于
    void printAll(String[] args) {…}

    3.2.2 使用规范
    • 必须作为最后一个参数

    • 一个方法只能有一个可变参数

    • 调用时可传入:

      • 多个单独参数:printAll("a", "b")

      • 数组:printAll(new String[]{"a", "b"})

      • 无参数:printAll()


    四、this关键字全面解析

    4.1 核心作用场景

    4.1.1 解决命名冲突

    class MyClass {
    int value;

    void setValue(int value) {
    this.value = value; // 明确区分成员变量和参数
    }
    }

    4.1.2 构造器链式调用

    class Person {
    String name;
    int age;

    Person() {
    this("Unknown"); // 调用另一个构造器
    }

    Person(String name) {
    this(name, 18);
    }

    Person(String name, int age) {
    this.name = name;
    this.age = age;
    }
    }

    4.2 内存模型视角

    MyClass obj = new MyClass();
    obj.method();

    实际执行过程:

  • 编译器将obj.method()转换为MyClass.method(obj)

  • this参数在调用时隐式传递(类似Python的self)


  • 五、static初始化细节

    5.1 类加载初始化流程

  • 加载.class文件

  • 验证字节码

  • 准备阶段(为static变量分配空间并设默认值)

  • 解析符号引用

  • 初始化(执行static块和static变量赋值)

  • 5.2 静态存储区特性

    特性说明
    生命周期 从类加载到JVM关闭
    线程安全 类加载阶段由JVM保证线程安全
    内存位置 JDK7前在永久代,JDK8+在元空间
    回收条件 类加载器被回收时

    六、枚举类型初始化

    6.1 枚举编译原理

    // 源代码
    enum Color { RED, GREEN, BLUE }

    // 编译器生成类似
    final class Color extends Enum<Color> {
    public static final Color RED = new Color();
    public static final Color GREEN = new Color();
    public static final Color BLUE = new Color();
    // …
    }

    6.2 初始化时序

  • static final枚举常量最先初始化

  • 其他static成员随后初始化

  • 不允许在static初始化块中访问枚举常量(会导致NPE)


  • 七、数组初始化大全

    7.1 数组类型系统

    类型语法特点
    基本类型数组 int[] arr = new int[5] 直接存储值
    对象数组 String[] arr = new String[3] 存储引用(初始null)
    多维数组 int[][] matrix = new int[3][4] 数组的数组

    7.2 初始化方式对比

    // 方式1:声明时初始化
    int[] arr1 = {1, 2, 3};

    // 方式2:动态初始化
    int[] arr2 = new int[3];
    arr2[0] = 1;

    // 方式3:匿名数组
    int[] arr3 = new int[]{1, 2, 3};

    // 多维数组初始化
    String[][] names = {
    {"Mr.", "Mrs."},
    {"Smith", "Jones"}
    };


    结语:通过深入理解初始化和清理机制,可以让我们编写出更健壮、更安全的Java代码,有效避免内存泄漏和资源管理问题。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 《Thinking in Java》读书笔记---初始化与清理
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!