Chapter 5 Initialize and Cleanup

Chapter 5 Initialize and Cleanup

不安全的编程方式已逐渐成为编程代价高昂的主因之一,初始化(initialize)和清理(cleanup)正是
涉及编程安全的两个关键问题。未初始化的元素会引起各种问题,用完元素一直不清理则会引起资源用尽
的问题。

5.1 Use Constructors to ensure intialization

每个类都应该有一个初始化方法initilize(),提醒调用者在使用之前先调用该方法进行初始化,但这依赖于调用者的主动调用。

在Java中,通过构造器,确保用户有能力操作对象之前自动调用完毕构造器,保证了初始化。

为了确保构造方法不重名,且能够被编译器识别调用,采用c++语言的解决方法:构造器与类具有有相同的名称。

new 操作在创建对象,为对象分配空间时,将调用相应的构造器,
“初始化”和“创建”捆绑在一起,两者不能分离。

Java通过定义与类同名的构造函数,在new对象时自动调用,以确保对象的初始化。

5.2 Method Overloading

人类语言具有很强的"冗余"性,同样的动词会因为动词对象的不同而表达不同的动作。
Java中也一样,参数和方法名构成了方法标签,同样的方法名不同的参数可以视为不同的方法。

基本类型作为参数列表时,传入的参数首先选择完全符合的方法,若找不到则进行类型提升,只有主动进行类型转换才能降低。

5.3 Default Constructor

若类没有显示定义构造器,则编译器会自动创建一个无参默认构造器;若定义了构造器,编译器就不会创建了。

5.4 This

编译器把所操作对象的引用作为第一个参数this传给类的方法,所以在方法内部能够通过this调用其他属性或方法,
并且this可以省略,编译器会首先认为变量或方法是类的。

this也能用来表示构造器,但只能处于构造器的第一行。

总结:

  1. 在对象方法内部使用代表对象的引用。
  2. 在构造器中表示对象的另一个构造方法(不能循环引用)。

static方法就是没有this的方法,可以在没有创建对象的前提下调用方法,类似于全局函数。

5.5 finalize

finalize()会在对象被GC回收的时候执行,不能作为清理对象的方法。

因为:

  • Java中对象可能不被垃圾回收(内存充足的话)
  • 垃圾回收不等于"折构"
  • 垃圾回收应该只与内存有关

finalize主要用来提供给本地方法(Java调用其他语言)使用来回收内存。

Java中对象的清理一般是不可预料的,由GC来

5.6 GC

Java使用GC(垃圾回收器)来进行内存(主要是堆)的释放。

Java的GC一边回收内存,一边使堆中的对象紧凑排列,已获得更高的分配内存的速度。

GC的任务:

  • 快速地回收内存
  • 重排对象,提高分配内存的速度
  • 减少GC操作的消耗

引用计数法

每个对象都含有一个引用计数器,当被引用时,计数+1;当离开作用域或被置为null时,计数减1。
垃圾回收器会在整个程序生命周期中,对含有全部对象的列表进行遍历,当发现对象引用计数为0就释放空间。

  • 简单,但速度慢。
  • 定位循环引用的情况消耗大。
  • 用来说明垃圾回收,没有被应用于任何一种虚拟机中。

引用网络

思想:还处于工作中的对象的引用构成了"活"的对象引用链,遍历全部引用构成了"活"的对象的网络。
没有处于在网络中的对象就应该被回收,这就解决了循环引用的问题。

停止-复制

将堆分成两块,GC时先暂停程序的运行,从一个活的对象开始,遍历整个堆栈或静态存储区的引用作为应该存活的对象网络。然后将这些对象复制到另一个堆上,重新排列保持紧凑,修正所有对象的引用(映射为新地址)。余下的对象就是垃圾。

  • 基于引用网络,解决了循环引用问题。
  • 复制时会重新排列对象,使得分配内存的效率提高。
  • 维护两个堆的消耗增加,且就算没有垃圾,也会进行复制的操作。

标记-清扫

GC时先暂停程序的运行,从一个活的对象开始,遍历整个堆栈或静态存储区的引用,并标记每个对象。
遍历标记完成后,清理没有被标记的对象。

  • 基于引用网络,解决了循环引用问题。
  • 没有复制操作。
  • 标记清扫后剩下的堆空间是不连续的,需要重新整理。

分代回收

停止-复制方法导致了大量内存复制,特别是大对象的复制降低了程序的效率。
在Java中,对象生命周期处于不均匀的状态,一部分对象存活时间很短,一部分对象将一直存活,这就引入了分代的思想。
分代回收将内存分为不同的代,不同的代GC的频率不同。每次停止-复制时,存活下来的对象的代数将+1,代数越大的对象越被认为是持久对象,进行复制的频率将会降低。而代数低的对象将会被更快的清理,释放空间。

5.7 成员初始化

Java 尽力保证所有变量在使用前都能得到其恰当的初始化。

  • 对于局部变量,编译器要求变量使用前必须进行初始化。
  • 对于基本数据类型的类成员变量,会被自动赋于一个初始值。
  • 对于对象引用的类成员变量,会获得特殊值null
类型
char '\u0000'
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0
boolean false
Object null

自动初始化:

类型
char '\u0000'
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0
boolean false
Object null

初始化顺序

类的初始化顺序(同级按从上到下的顺序):

  1. 父类静态成员自动初始化
  2. 父类静态初始块、父类静态成员指定初始化
  3. 子类静态成员自动初始化
  4. 子类静态初始块、类静态成员指定初始化
  5. 父类初始块、父类成员变量指定初始化
  6. 父类构造函数(若没有在构造器里super指定,调用无参构造函数)
  7. 子类初始块、子类成员变量指定初始化
  8. 子类构造函数

静态初始化

静态成员的指定初始化和静态初始块会在类第一次使用时执行一次,包括new和调用静态成员或方法。

对象创建过程

创建过程:

  1. 创建类的对象或访问类的静态方法/静态域时,解释器查找类路径,定位class文件。
  2. 载入class文件,创建对应的Class对象,执行静态初始化动作。
  3. 在堆上为对象分配空间,并将空间数值置为0,即自动初始化。、
  4. 执行指定初始化动作。
  5. 执行构造函数

5.8 数组初始化

数组只是一个相同类型、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。

// 初始化表达式
int[] a = {1,2,3};

// 进行自动初始化
int[] b = new int[3];

// 另一种初始化写法
Integer[] c = new Integer[]{
  new Integer(1),
  new Integer(2),
  3
}

可变参数列表

通过数组能够传递可变数量的方法参数

void printArray(Object[] args){
  for(Object obj:args){
    System.out.println(obj+"");
  }
}
// 需要传递数组
printArray(new Object[]{"one",1});

在JAVA5之后,可变参数列表特性添加了进来。

  • 调用时会先寻找固定参数的方法,然后才是可变参数方法。
  • 可变参数只能位于一般参数后
  • 方法寻找顺序:恰好>自动提升>包装>可变参数
void printArray(Object... args){
  for(Object obj:args){
    System.out.println(obj+"");
  }
}
// 编译器会创建数组传递
printArray("one",1);

5.9 枚举

  • enum关键字在Java5中添加。
  • enmu实际是实现了Enum的类,包含了name和ordinal两个实例域和一些方法。
  • 枚举类型具有有限的实例(具名值),即实例都为常量。
  • 枚举可以在switch语句中使用。
public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
          private final String name;
          private final int ordinal;
}

5.10 总结

  • 再总结了C++由于初始化问题中产生的居多问题后,Java使用一种精巧的初始化机制————构造器来确保正确的初始化。
  • 在Java中,由垃圾回收器来自动为对象释放内存,极大地简化了编程工作。
  • 垃圾回收器增加了运行时的开销,使得垃圾回收器的实现一直在优化,以提升它的效率和速度。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容