第五章 初始化与清理

[color=blue]用构造器确保初始化[/color]

注意,由于构造器的名称必须与类名完全相同,所以“每个方法首字母小写”的编码风格并不适合于构造器。

[color=blue]区分重载方法[/color]

参数顺序不同也足以区分两个方法。不过一般情况下不要这么做。

[color=blue]设计基本类型的重载[/color]

如果传入方法内部的数据类型小于方法中声明的形式参数类型,实际数据类型就会被提升。Char类型略有不同,如果无法找到恰好接受char类型的参数,它就会把char提升到int类型。

如果方法接受较小的基本类型作为参数。如果传入的实际参数较大,就得通过类型转换来执行窄化转换。如果不这样做编译器就会报错。

[color=blue]在构造器中调用构造器[/color]

构造器Flower表明:尽管可以用this调用一个构造器,但却不能调用两个。此外将构造器调用置于最起始处,否则编译器会报错。
Flower(String s, int p) {
This(p);
//this(); 这个不可以调用了,因为已经有一次了。
}


[color=blue]清理:终结处理和垃圾回收[/color]

Java允许在类中定义一个名为finalize()的方法。它的工作原理“假定”是这样的:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用finalize方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是你打算用finalize,就能在垃圾回收时刻做一些重要的清理工作。
对象可能不被垃圾回收
垃圾回收并不等于析构。
也许你会发现,只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。程序退出了,资源自然也就还给了系统。

[color=blue]finalize的用途何在[/color]

垃圾回收只与内存有关
比如java调用了本地方法,一般这些方法都是C或者C++编的,当这些方法调用如,malloc的方法分配内存。此时我们需要在finalize()中用本地方法调用它。

[color=blue]你必须实施清理[/color]

无论是“垃圾回收”还是“终结”,都不保证一定会发生。如果java虚拟机并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。

[color=blue]终结条件[/color]
class Book {
protected void finalize() {
if(checkout)
System.out.println(“error”)
}
void checkIn() {
checkout = false;
}
}

本例的终结条件是:所有的Book对象在被当做垃圾回收前都应该被签入。但在main方法中,由于程序员的错误,有一本书没有被签入。要是没有finalize来验证终结条件,将很难发现这种缺陷。

[color=blue]构造器初始化[/color]

无法阻止自动初始化的进行,它将在构造器被调用之前发生。
public class Counter {
int i;
Counter() {
i = 8;
}
}
那么i首先会被赋值为0,然后变成8。


[color=red]初始化顺序[/color]

在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。例如:
class Window {
Window(int marker) {
System.out.println(“Window(”+marker+”)”);
}
}
class House {
Window w1 = new Window(1);
House() {
print(“House”);
w3 = new Window(33);
}
Window w2 = new Window(2);
Void f() {
print(“f()”);
}
Window w3 = new Window(3);
}
public class Test() {
public static void main(String[] args) {
House h = new House();
h.f();
}
}
Out put:
Window(1);
Window(2);
Window(3);
House()
Window(3);
f()

[color=red]静态数据的初始化[/color]

初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化),而后是非静态变量。从输出结果看,要执行这个静态方法,就必须加载这个W类,然后其静态域W1被初始化,这将导致它们对应的类也被初始化。

总结一下对象的创建过程,假如有个名为Doc的类:
1.即使没有显示第使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时,或者Dog类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位Dog.class文件。
2.然后载入Dog.class(后面会学到,这将创建一个class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
3.当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4.这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说就是0,布尔型和字符型也相同),而引用则被设置成了null。
5.执行所有出现于字段定义出的初始化动作。
6.执行构造器。

[color=blue]可变参数列表[/color]
static void g(int... args) {
System.out.println(args.getClass());
System.out.println(args.length);
for(int i: args) {
System.out.println(i);
}
}

传入参数的个数无所谓。同时有自动装箱等功能。

[color=blue]枚举类型[/color]

几个小例子:

创建一个enum
public enum Spiciness {
NOT, MULD, MEDIUM, HOT
}


使用enum:
public class Test {
public static void main(String[] args) {
Spiceness hot = Spiceness.MEDIUM;
System.out.println(hot);
}
}

Enum还有一些方法,ordinal方法,用来表示某个特定enum常量的声明顺序。Static values方法,用来按照enum常量的声明顺序,产生由这些常量值构成的数组

for(Spiciness s : Spiciness.values()) {
System.out.println(s + "ordinal" + s.ordinal());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值