按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
用这样的一条注释结尾,它标志着源代码清单的结束。这样一来,可将代码从本书的正文中方便地提取出
来,并用一个编译器检查。这方面的细节在第 17章讲述。
2。9 编码样式
一个非正式的Java 编程标准是大写一个类名的首字母。若类名由几个单词构成,那么把它们紧靠到一起(也
就是说,不要用下划线来分隔名字)。此外,每个嵌入单词的首字母都采用大写形式。例如:
class AllTheColorsOfTheRainbow { // 。。。}
对于其他几乎所有内容:方法、字段(成员变量)以及对象句柄名称,可接受的样式与类样式差不多,只是
标识符的第一个字母采用小写。例如:
class AllTheColorsOfTheRainbow {
int anIntegerRepresentingColors;
void changeTheHueOfTheColor(int newHue) {
// 。。。
}
// 。。。
}
当然,要注意用户也必须键入所有这些长名字,而且不能输错。
2。10 总结
通过本章的学习,大家已接触了足够多的 Java 编程知识,已知道如何自行编写一个简单的程序。此外,对语
言的总体情况以及一些基本思想也有了一定程度的认识。然而,本章所有例子的模式都是单线形式的“这样
做,再那样做,然后再做另一些事情”。如果想让程序作出一项选择,又该如何设计呢?例如,“假如这样
做的结果是红色,就那样做;如果不是,就做另一些事情”。对于这种基本的编程方法,下一章会详细说明
在Java 里是如何实现的。
2。11 练习
(1) 参照本章的第一个例子,创建一个“Hello,World”程序,在屏幕上简单地显示这句话。注意在自己的
类里只需一个方法(“main ”方法会在程序启动时执行)。记住要把它设为static 形式,并置入自变量列
表——即使根本不会用到这个列表。用javac 编译这个程序,再用java 运行它。
(2) 写一个程序,打印出从命令行获取的三个自变量。
(3) 找出Property。java 第二个版本的代码,这是一个简单的注释文档示例。请对文件执行javadoc,并在
自己的Web 浏览器里观看结果。
(4) 以练习(1)的程序为基础,向其中加入注释文档。利用javadoc,将这个注释文档提取为一个HTML 文
件,并用Web 浏览器观看。
59
…………………………………………………………Page 61……………………………………………………………
第 3 章 控制程序流程
“就象任何有感知的生物一样,程序必须能操纵自己的世界,在执行过程中作出判断与选择。”
在Java 里,我们利用运算符操纵对象和数据,并用执行控制语句作出选择。Java 是建立在C++基础上的,所
以对C 和C++程序员来说,对Java 这方面的大多数语句和运算符都应是非常熟悉的。当然,Java 也进行了自
己的一些改进与简化工作。
3。1 使用 Java 运算符
运算符以一个或多个自变量为基础,可生成一个新值。自变量采用与原始方法调用不同的一种形式,但效果
是相同的。根据以前写程序的经验,运算符的常规概念应该不难理解。
加号(+)、减号和负号(…)、乘号(*)、除号(/)以及等号(=)的用法与其他所有编程语言都是类似
的。
所有运算符都能根据自己的运算对象生成一个值。除此以外,一个运算符可改变运算对象的值,这叫作“副
作用”(Side Effect)。运算符最常见的用途就是修改自己的运算对象,从而产生副作用。但要注意生成的
值亦可由没有副作用的运算符生成。
几乎所有运算符都只能操作“主类型”(Primitives)。唯一的例外是“=”、“==”和“!=”,它们能操作
所有对象(也是对象易令人混淆的一个地方)。除此以外,String 类支持“+”和“+=”。
3。1。1 优先级
运算符的优先级决定了存在多个运算符时一个表达式各部分的计算顺序。Java 对计算顺序作出了特别的规
定。其中,最简单的规则就是乘法和除法在加法和减法之前完成。程序员经常都会忘记其他优先级规则,所
以应该用括号明确规定计算顺序。例如:
A = X + Y 2/2 + Z;
为上述表达式加上括号后,就有了一个不同的含义。
A = X + (Y 2)/(2 + Z);
3。1。2 赋值
赋值是用等号运算符(=)进行的。它的意思是“取得右边的值,把它复制到左边”。右边的值可以是任何常
数、变量或者表达式,只要能产生一个值就行。但左边的值必须是一个明确的、已命名的变量。也就是说,
它必须有一个物理性的空间来保存右边的值。举个例子来说,可将一个常数赋给一个变量(A=4; ),但不可
将任何东西赋给一个常数(比如不能4=A)。
对主数据类型的赋值是非常直接的。由于主类型容纳了实际的值,而且并非指向一个对象的句柄,所以在为
其赋值的时候,可将来自一个地方的内容复制到另一个地方。例如,假设为主类型使用“A=B”,那么B 处的
内容就复制到A 。若接着又修改了A,那么B 根本不会受这种修改的影响。作为一名程序员,这应成为自己的
常识。
但在为对象“赋值”的时候,情况却发生了变化。对一个对象进行操作时,我们真正操作的是它的句柄。所
以倘若“从一个对象到另一个对象”赋值,实际就是将句柄从一个地方复制到另一个地方。这意味着假若为
对象使用“C=D”,那么C 和 D 最终都会指向最初只有 D 才指向的那个对象。下面这个例子将向大家阐示这一
点。
这里有一些题外话。在后面,大家在代码示例里看到的第一个语句将是“package 03”使用的“package”语
句,它代表本书第 3 章。本书每一章的第一个代码清单都会包含象这样的一个“package”(封装、打包、包
裹)语句,它的作用是为那一章剩余的代码建立章节编号。在第17 章,大家会看到第 3 章的所有代码清单
(除那些有不同封装名称的以外)都会自动置入一个名为c03 的子目录里;第4 章的代码置入c04;以此类
推。所有这些都是通过第 17 章展示的CodePackage。java 程序实现的;“封装”的基本概念会在第 5 章进行
详尽的解释。就目前来说,大家只需记住象“package 03”这样的形式只是用于为某一章的代码清单建立相
应的子目录。
为运行程序,必须保证在classpath 里包含了我们安装本书源码文件的根目录(那个目录里包含了 c02,
c03c,c04 等等子 目录)。
60
…………………………………………………………Page 62……………………………………………………………
对于Java 后续的版本(1。1。4 和更高版本),如果您的 main()用 package 语句封装到一个文件里,那么必须
在程序名前面指定完整的包裹名称,否则不能运行程序。在这种情况下,命令行是:
java c03。Assignment
运行位于一个“包裹”里的程序时,随时都要注意这方面的问题。
下面是例子:
//: Assignment。java
// Assignment with objects is a bit tricky
package c03;
class Number {
int i;
}
public class Assignment {
public static void main(String'' args) {
Number n1 = new Number();
Number n2 = new Number();
n1。i = 9;
n2。i = 47;
System。out。println(〃1: n1。i: 〃 + n1。i +
〃; n2。i: 〃 + n2。i);
n1 = n2;
System。out。println(〃2: n1。i: 〃 + n1。i +
〃; n2。i: 〃 + n2。i);
n1。i = 27;
System。out。println(〃3: n1。i: 〃 + n1。i +
〃; n2。i: 〃 + n2。i);
}
} ///:~
Number 类非常简单,它的两个实例(n1 和n2)是在main()里创建的。每个Number 中的i值都赋予了一个不
同的值。随后,将n2 赋给n1,而且n1 发生改变。在许多程序设计语言中,我们都希望n1 和n2 任何时候都
相互独立。但由于我们已赋予了一个句柄,所以下面才是真实的输出:
1: n1。i: 9; n2。i: 47
2: n1。i: 47; n2。i: 47
3: n1。i: 27; n2。i: 27
看来改变n1 的同时也改变了n2!这是由于无论n1 还是n2 都包含了相同的句柄,它指向相同的对象(最初
的句柄位于 n1 内部,指向容纳了值9 的一个对象。在赋值过程中,那个句柄实际已经丢失;它的对象会由
“垃圾收集器”自动清除)。
这种特殊的现象通常也叫作“别名”,是 Java 操作对象的一种基本方式。但假若不愿意在这种情况下出现别
名,又该怎么操作呢?可放弃赋值,并写入下述代码:
n1。i = n2。i;
这样便可保留两个独立的对象,而不是将 n1 和n2 绑定到相同的对象。但您很快就会意识到,这样做会使对
象内部的字段处理发生混乱,并与标准的面向对象设计准则相悖。由于这并非一个简单的话题,所以留待第
12章详细论述,那一章是专门讨论别名的。其时,大家也会注意到对象的赋值会产生一些令人震惊的效果。
1。 方法调用中的别名处理
将一个对象传递到方法内部时,也会产生别名现象。
//: PassObject。java
// Passing objects to methods can be a bit tricky
61
…………………………………………………………Page 63……………………………………………………………
class Letter {
char c;
}
public class PassObject {
static void f(Letter y) {
y。c = 'z';
}
public static void main(String'' args) {
Letter x = new Letter();
x。c = 'a';
System。out。println(〃1: x。c: 〃 + x。c);
f(x);
System。out。println(〃2: x。c: 〃 + x。c);
}
} ///:~
在许多程序设计语言中,f()方法表面上似乎要在方法的作用域内制作自己的自变量Letter y 的一个副本。
但同样地,实际传递的是一个句柄。所以下面这个程序行:
y。c = 'z';
实际改变的是f()之外的对象。输出结果如下:
1: x。c: a
2: x。c: