第5章 初始化与清理 - 《Java编程思想》读书笔记

第5章 初始化与清理

5.4 this关键字

  • 可以用this返回当前对象的引用,实现在一条语句里,对同一个对象进行多次操作
public class Leaf{
    int i = 0;
    Leaf increment(){
        i++;
        return this;
    }
    void print(){
        System.out.println("i = " + i);
    }
    public static void main(String[] args){
        Leaf x = new Leaf();
        x.increment().increment().print();
    }
}
  • 也可以通过this将当前对象传递给外部的工具方法
class Peeler{
    static Apple peel(Apple apple){
        //...remove peel
        return apple;
    }
}
class Apple{
    Apple getPeeled(){
        return Peeler.pell(this);
    }
}

5.4.1 在构造器中调用构造器

  • 可以为this添加参数列表来调用构造器
  • 只能调用一个构造器,并且需要放在构造器的最前面

5.5 清理:终结处理和垃圾回收

  • Java允许在类中定义finalize()方法
  • 工作原理:一旦垃圾回收器准备好释放对象所占用的存储空间,将首先调用finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存
  • 与C++中的析构函数不同,Java中:
    1. 对象可能不被垃圾回收
    2. 垃圾回收并不等于析构

5.5.1 finalize()的用途何在

  • 垃圾回收只与内存有关
  • 在分配内存时采用了C语言中的做法,如本地方法等

5.5.4 垃圾回收器如何工作

  • 对任何活的对象,一定能追溯到其存活在堆栈或静态存储区之中的引用

    • 这样就能解决交互自引用的对象组(对象之间循环引用)的问题
  • 停止-复制:先暂停程序的运行,然后将所有存活的对象从当前堆复制到另一个堆,并且保持紧凑排列

  • 标记-清扫:遍历所有引用,对找到的活的对象设标记,标记完成后,清理未标记对象

    • 在没有新垃圾产生时,会自适应地转换到这种模式
  • 即时(JIT)编译器:把程序全部或部分翻译成本地机器码

  • 惰性评估:即时编译器只在必要的时候才编译代码,Java HotSpot就采用了类似方法

5.7 构造器初始化

5.7.1 初始化顺序

  • 变量定义的先后顺序决定了初始化的顺序、
  • 变量会在任何方法(包括构造器)被调用之前得到初始化

5.7.2 静态数据的初始化

  • 静态初始化只有必要时刻才会进行,如创建对象或第一次访问静态数据

  • 对象的创建过程:

    1. 当首次创建对象时,或者静态方法、静态域首次被访问时,Java解释器查找类路径,定位.class文件

    2. 创建一个Class对象,执行有关静态初始化的动作

    3. 当用new创建对象时,首先在堆上分配存储空间

    4. 存储空间清零,完成数据初始化

    5. 执行所有出现于字段定义处的初始化动作

    6. 执行构造器

5.8 数组初始化

5.8.1 可变参数列表

  • Java SE5之前,可以用Object数组作为参数,实现可变参数列表

  • Java SE5中,使用Object... args作为可变参数

    • 调用方法时,不需要显式地编写数组语法,编译器会自动填充数组
    • 所以,获取的仍旧是一个数组
    • 当参数已经是一个数组时,方法会直接当做可变参数列表来接受
    • 可变参数也可以是0个参数
  • 如果重载方法时,所有方法都是可变列表,则参数不能为空,因为无法判断调用哪个方法

5.9 枚举类型

public enum Spiciness{
    NOT, MILD, MEDIUM, HOT, FLAMING
}
  • 因为枚举类型的实例是常亮,因此习惯用大写字母表示
  • 使用方法如下:
public SimpleEnumUse{
    public static void main(String[] args){
        Spiciness howHot = Spiciness.MEDIUM;
        System.out.println(howHot)
        for(Spiciness s : Spiciness.values())
            System.out.println(s + " " + s.ordinal());
        /*
        NOT 0
        MILD 1
        ...
        FLAMING 4
        */
    }
}
  • 创建enum时,会自动创建toString()方法,显示实例名字
  • static values()方法可以按照enum常量的声明顺序,产生由常量值构成的数组
  • ordinal()方法可以表示某个特定enum常量的声明顺序
  • enum还能再switch...case...中方便地使用
posted @ 2021-03-01 18:47  一天到晚睡觉的鱼  阅读(61)  评论(0)    收藏  举报