[学习笔记]Thinking in Java (the 2nd edition) …

2008-02-23 10:14:26来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

第4章 初始化和清除
“随着计算机的进步,‘不安全’的程序设计已成为造成编程代价高昂的罪魁祸首之一。”

“初始化”和“清除”是这些安全问题的其中两个。


4.1 构造函数

<1>不能用返回值来区分不同的函数,比如:
void f() {}
int f() {}
我们可能调用一个方法,同时忽略返回值;通常把这称为“为它的副作用去调用一个方法”,因为我们关心的不是返回值,
而是方法调用的其他效果。所以假如我们象下面这样调用方法:
f();
Java怎样判断f()的具体调用方式呢?而且别人如何识别并理解代码呢?由于存在这一类的问题,所以不能根据返回值
类型来区分重载的方法。

<2>下面这一行:
new Bird();
它的作用是新建一个对象,并调用默认构建器——即使尚未明确定义一个象这样的构建器。若没有它,就没有方法可以调用,
无法构建我们的对象。然而,如果已经定义了一个构建器(无论是否有自变量),编译程序都不会帮我们自动合成一个:

class Bush {
Bush(int i) {}
Bush(double d) {}
}

现在,假若使用下述代码:
new Bush();
编译程序就会报告自己找不到一个相符的构建器。就好象我们没有设置任何构建器,编译程序会说:“你看来似乎需要一个
构建器,所以让我们给你制造一个吧。”但假如我们写了一个构建器,编译程序就会说:“啊,你已写了一个构建器,所以
我知道你想干什么;如果你不放置一个默认的,是由于你打算省略它。”

4.2 垃圾收集

finalize()最有用处的地方之一是观察垃圾收集的过程。下面这个例子向大家展示了垃圾收集所经历的过程,并对前面的
陈述进行了总结。

//: Garbage.java
// Demonstration of the garbage
// collector and finalization

class Chair {
static boolean gcrun = false;
static boolean f = false;
static int created = 0;
static int finalized = 0;
int i;
Chair() {
i = created;
if(created == 47)
System.out.println("Created 47");
}
protected void finalize() {
if(!gcrun) {
gcrun = true;
System.out.println(
"Beginning to finalize after "
created " Chairs have been created");
}
if(i == 47) {
System.out.println(
"Finalizing Chair #47, "
"Setting flag to stop Chair creation");
f = true;
}
finalized ;
if(finalized >= created)
System.out.println(
"All " finalized " finalized");
}
}

public class Garbage {
public static void main(String[] args) {
if(args.length == 0) {
System.err.println("Usage: \n"
"java Garbage before\n or:\n"
"java Garbage after");
return;
}
while(!Chair.f) {
new Chair();
new String("To take up space");
}
System.out.println(
"After all Chairs have been created:\n"
"total created = " Chair.created
", total finalized = " Chair.finalized);
if(args[0].equals("before")) {
System.out.println("gc():");
System.gc();
System.out.println("runFinalization():");
System.runFinalization();
}
System.out.println("bye!");
if(args[0].equals("after"))
System.runFinalizersOnExit(true);
}
} ///:~


4.3 对象数组的写法
Integer[] b = new Integer[] {
new Integer(1),
new Integer(2),
new Integer(3), //最后的","是可以存在的
};


第5章 隐藏实施过程

“进行面向对象的设计时,一项基本的考虑是:如何将发生变化的东西与保持不变的东西分隔开。”

第6章 类再生

“Java引人注目的一项特性是代码的重复使用或者再生。但最具革命意义的是,除代码的复制和修改以外,我们还能做多
得多的其他事情。”

在这一章里,我们将介绍两个达到这一目标[即代码复用]的方法。第一个最简单:在新类里简单地创建原有类的对象。
我们把这种方法叫作“合成”,因为新类由现有类的对象合并而成。我们只是简单地重复利用代码的功能,而不是采用它的
形式。第二种方法则显得稍微有些技巧。它创建一个新类,将其作为现有类的一个“类型”。我们可以原样采取现有类的形
式,并在其中加入新代码,同时不会对现有的类产生影响。这种魔术般的行为叫作“继承”(Inheritance)。

6.1 继承:基础类的初始化
//: Cartoon.java
// Constructor calls during inheritance

class Art {
Art() {
System.out.println("Art constructor");
}
}

class Drawing extends Art {
Drawing() {
System.out.println("Drawing constructor");
}
}

public class Cartoon extends Drawing {
Cartoon() {
System.out.println("Cartoon constructor");
}
public static void main(String[] args) {
Cartoon x = new Cartoon();
}
} ///:~

该程序的输出显示了自动调用:
Art constructor
Drawing constructor
Cartoon constructor
这表明:在调用子类的时候 ,父类的构造方法均被调用了一次

--含有自变量的构建器--
上述例子有自己默认的构建器;也就是说,它们不含任何自变量。编译器可以很容易地调用它们,因为不存在具体传递
什么自变量的问题。如果类没有默认的自变量,或者想调用含有一个自变量的某个基础类构建器,必须明确地编写对基

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Java 性能优化技巧集锦 (2)

下一篇:保护您的 J2ME/MIDP 应用程序