Thinking in Java:第五章 初始化与清理

5.1 用构造器确保初始化

定义类时,若未定义构造函数,则系统会自动创建一个无参构造器(默认构造器),若已经定义了构造器,则不会自动创建无参构造器。

5.2 方法重载

方法重载时,利用参数类型列表来区分方法,这里包括:参数类型、顺序、数量;

涉及基本类型的重载时,基本类型能从一个“较小”的类型自动提升至一个“较大”的类型。也就是说方法接受较小的基本类型作为参数,如果传入的实际参数较大,就得通过类型转换来执行窄化转换。

5.3 默认构造器

5.4 this关键字

为了能用简便、面向对象的语法来编写代码——即“发送消息给对象”,编译器做了一些幕后工作。它暗指把“所操作对象的引用”作为第一个参数传给类,所以如下的方法调用为:

//: initialization/BananaPeel.java class Banana { void peel(int i) { /* ... */ } } public class BananaPeel { public static void main(String[] args) { Banana a = new Banana(), b = new Banana(); a.peel(1); b.peel(2); } } ///:~ 此时,在编译器内部,两个方法的调用变为:

Banana.peel(a,1)

Banana.peel(b,2)

另外,为一个类写了多个构造器,有时可能想在一个构造器中调用另一个构造器,以避免重复代码,此时使用this关键字。但是此时只能在构造器的开始处调用构造器,能且仅能调用一次。

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

java为类提供了finalize方法,该方法可以在垃圾回收时刻做一些重要的清理工作。

对此,需要对垃圾回收做一个说明:对象可能不被垃圾回收;垃圾回收并不等于“析构”;垃圾回收只与内存有关。

此时,我们可以知道,如果使用了java的native方法(如调用c++new了一个对象),此时如果不明确的调用C++ delete掉这个对象,则垃圾回收器是无法回收这个对象的。另外,你做的一些其他操作可能也无法清楚,比如你在屏幕上绘制了一个图像,如果不显示擦除,则该图像永远保留在屏幕上。

如下是一个书籍借阅时签入的例子,所有的book对象在被当做垃圾回收前都应该被签入:

//: initialization/TerminationCondition.java // Using finalize() to detect an object that // hasn't been properly cleaned up. class Book { boolean checkedOut = false; Book(boolean checkOut) { checkedOut = checkOut; } void checkIn() { checkedOut = false; } protected void finalize() { if(checkedOut) System.out.println("Error: checked out"); // Normally, you'll also do this: // super.finalize(); // Call the base-class version } } public class TerminationCondition { public static void main(String[] args) { Book novel = new Book(true); // Proper cleanup: novel.checkIn(); // Drop the reference, forget to clean up: new Book(true); // Force garbage collection & finalization: System.gc(); } } /* Output: Error: checked out *///:~ 垃圾回收器在内存快要耗尽时开始工作,回收不再使用的对象。很多虚拟机中堆的实现如下:它更像一个传送带,每分配一个新对象,它就往前移动一格。为了做到这一点,垃圾回收期需要整理内存,其有两种方法:“停止——复制”和“标记——清扫”。对于比较稳定的程序(没有新垃圾产生),其会进入“标记——清扫”模式。

另外,java虚拟机为了提高速度,使用了“即时(Juse-in-Time,JIT) ”编译技术,先将类编译为.class文件,然后再将该类的字节码装入内存。此时有两种方法:一种是让即时编译器编译所有代码;另一种是使用惰性评估,意思是即时编译器只在必要的时候才编译代码。

5.6 成员初始化

5.7 构造器初始化

总结一下对象的创建过程,假设有名为dog的类:

1)即使没有显示的使用static关键字,构造器实际上也是静态方法。因此,首次创建类型为dog的对象时(构造器可以看成静态方法),或者dog类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位dog.class文件。

2)然后载入dog.class(后面会学到,这将创建一个class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在class对象首次加载的时候进行一次。

3)的那个用new dog()创建对象时,首先将在堆上为dog对象分配足够的存储空间。

4)这块存储空间会被清零,这就自动地将dog对象中的所有基本类型数据都设置成默认值(对数字来说就是0,对布尔型和字符型也相同),而引用则被设置成null。

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

6)执行构造器。正如将在第7章所看到的,这可能会涉及到很多动作,尤其是涉及继承的时候。

显示静态初始化:

//: initialization/Spoon.java public class Spoon { static int i; static { i = 47; } } ///:~ static后面的代码跟静态初始化动作一样,这段代码仅执行一次:当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时。

非静态实例初始化:

//: initialization/Mugs.java // Java "Instance Initialization." import static net.mindview.util.Print.*; class Mug { Mug(int marker) { print("Mug(" + marker + ")"); } void f(int marker) { print("f(" + marker + ")"); } } public class Mugs { Mug mug1; Mug mug2; { mug1 = new Mug(1); mug2 = new Mug(2); print("mug1 & mug2 initialized"); } Mugs() { print("Mugs()"); } Mugs(int i) { print("Mugs(int)"); } public static void main(String[] args) { print("Inside main()"); new Mugs(); print("new Mugs() completed"); new Mugs(1); print("new Mugs(1) completed"); } } /* Output: Inside main() Mug(1) Mug(2) mug1 & mug2 initialized Mugs() new Mugs() completed Mug(1) Mug(2) mug1 & mug2 initialized Mugs(int) new Mugs(1) completed *///:~ 这种语法对于支持“匿名内部类”的初始化是必须的,但是它使得你可以保证无论调用了哪个显示构造器,某些操作都会发生。从输出可以看出,实例初始化子句是在两个构造器之前执行的。

5.8 数组初始化

int[] a1={1,2,3,4,5,6,}//最后一个逗号可以不要

int a2[];

a2=a1;//此时a2是a1的引用。

另外,数组可以在程序中间用new来初始化。比如:a1=new int[rand.nextInt(20)]

可变参数列表有两种形式:旧版和新版(java SE5):

//: initialization/VarArgs.java // Using array syntax to create variable argument lists. class A {} public class VarArgs { static void printArray(Object[] args) { for(Object obj : args) System.out.print(obj + " "); System.out.println(); } public static void main(String[] args) { printArray(new Object[]{ new Integer(47), new Float(3.14), new Double(11.11) }); printArray(new Object[]{"one", "two", "three" }); printArray(new Object[]{new A(), new A(), new A()}); } } /* Output: (Sample) 47 3.14 11.11 one two three A@1a46e30 A@3e25a5 A@19821f *///:~ 新版:

//: initialization/VarargType.java public class VarargType { static void f(Character... args) { System.out.print(args.getClass()); System.out.println(" length " + args.length); } static void g(int... args) { System.out.print(args.getClass()); System.out.println(" length " + args.length); } public static void main(String[] args) { f('a'); f(); g(1); g(); System.out.println("int[]: " + new int[0].getClass()); } } /* Output: class [Ljava.lang.Character; length 1 class [Ljava.lang.Character; length 0 class [I length 1 class [I length 0 int[]: class [I *///:~ 5.9 枚举类型

//: initialization/Spiciness.java public enum Spiciness { NOT, MILD, MEDIUM, HOT, FLAMING } ///:~
//: initialization/EnumOrder.java public class EnumOrder { public static void main(String[] args) { for(Spiciness s : Spiciness.values()) System.out.println(s + ", ordinal " + s.ordinal()); } } /* Output: NOT, ordinal 0 MILD, ordinal 1 MEDIUM, ordinal 2 HOT, ordinal 3 FLAMING, ordinal 4 *///:~
//: initialization/Burrito.java public class Burrito { Spiciness degree; public Burrito(Spiciness degree) { this.degree = degree;} public void describe() { System.out.print("This burrito is "); switch(degree) { case NOT: System.out.println("not spicy at all."); break; case MILD: case MEDIUM: System.out.println("a little hot."); break; case HOT: case FLAMING: default: System.out.println("maybe too hot."); } } public static void main(String[] args) { Burrito plain = new Burrito(Spiciness.NOT), greenChile = new Burrito(Spiciness.MEDIUM), jalapeno = new Burrito(Spiciness.HOT); plain.describe(); greenChile.describe(); jalapeno.describe(); } } /* Output: This burrito is not spicy at all. This burrito is a little hot. This burrito is maybe too hot. *///:~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值