Java是面向对象的编程语言,JVM的工作方式决定了Java具有“Write Once,Run Anywhere”的特点。Java数据类型、基本运算、变量和常量等,是构建Java程序的基础。Java程序由顺序、选择和循环三种基本结构组成,是结构化程序。网页设计中的Java程序,可以是Java Application、Java Applet或者JavaBean。Javadoc命令从文档注释语句中提取信息,根据程序结构生成HTML格式的程序文档。Java API对程序设计人员是非常有价值的资源。
1 Java语言的元素
任何编程语言都有组成语言的基本元素,包括数据类型、基本运算、变量和常量等,这些元素是构建程序的基础。Java语言的基本元素是构建Java程序的基础。
1.1 基本数据类型
数据不仅有值,还有类型。数据类型决定着数据的取值范围、及可以对此数据施行的运算。
Java语言定义了四类八种基本数据类型,分别是:
逻辑型:boolean
字符型:char
整型:byte,short,int,和long
浮点型:double和float
逻辑型数据有两个值,true和false。例如:
boolean truth = true; //声明了逻辑型变量truth,并为其赋值为true。
字符型数据描述了单一字符,由一对单引号括起。
例如:
'a' 表示字母a
'\t' 表示tab符,即横向制表符。其中,'\'起转义作用
'\u840c' 表示汉字萌
'\u2211' 表示字符∑
'\u????' 形式中的“????”由四位十六进制数字代替,表示特定的Unicode字符。
Java语言使用Unicode字符集。Unicode为国际字符集标准,由十六位二进制数据表示(人们熟悉的ASCII字符集由八位二进制数据表示),它足够大的字符空间,支持当前世界上使用的主要语言。Unicode字符集中包含了ASCII字符的一个子集(前128个字符)。
Java语言也有字符串型,写为String。String不是基本数据类型,而是一个类。
String型数据用一对双引号括起,可如下方式使用,如:
String greeting = "Hello World! ";
String errorMessage = "Record Not Found !";
整型数据byte,short,int和long,有三种形式:十进制、八进制和十六进制。如:
2 表示十进制整数 2
077 首位为0表示八进制整数值
0xBAAC 首位为0x表示十六进制整数值
整型常数的缺省类型为int。如果特别指定为long整数,需要使用“L”或者“l”后缀。如:27L或者27l。整型数据的取值范围如表1-1。
浮点型存储有小数位的数值,其所能表示的最大或最小值并不确定。参见表1-2。
表1-1 整数型
类型 |
整数长度 |
取 值 范 围 |
byte |
8 bit |
-27 – 27 -1(-128 – 127, or 256) |
short |
16 bit |
-215 – 215 -1(-32,768 to 32,767, or 65,535) |
int |
32 bit |
-231 – 231 -1(-2,147,483,648 – 2,147,483,647 or 4,294,967,296) |
long |
64 bit |
-263 – 263 -1(-9,223,372,036,854,775,808 to 9,223,372,036854,775,807, or 18,446,744,073,709,551,616) |
表1-2 浮点型
类 型 |
浮点长度 |
允许的常数值示例 |
float |
32 bits |
99F,-327,456,99.01F ,4.2E6F(4.2 * 106的工程记数法) |
double |
64 bits |
-1111,2.1E12,999,701,327,456,99.999 |
1.2 变量和常量
变量有类型、名字和值。如:
int x, y; //声明int型变量x和y
float z = 3.414f; //声明float型变量z,并赋值3.414f
变量的名字,也称变量标识符。
为变量选用标识符,必须遵循Java标识符命名规则,避免使用Java关键字。同时,还应尽量遵循Java技术的命名约定,这些约定使代码更可读,而程序的可读性非常重要。
Java标识符用于命名Java类、方法或者变量等,命名规则为:
● 第一个字符可以是A-Z、a-z、_ 或 $。
● 第二个及其后字符可以是上述所列字符、或者0-9数字。
Java技术关键字参见表1-3。
表1-3 Java关键字
abstract |
do |
implements |
protected |
throws |
boolean |
double |
import |
public |
transient |
break |
else |
instanceof |
return |
true |
byte |
extends |
int |
short |
try |
case |
false |
interface |
static |
void |
catch |
final |
long |
strictpf |
volatile |
char |
finally |
native |
super |
while |
class |
float |
new |
switch |
|
const |
for |
null |
synchronized |
|
continue |
goto |
package |
this |
|
default |
if |
private |
throw |
|
Java技术约定,变量标识符以小写字母开头。如果标识符由两个或者两个以上单词组成,则除标识符第一个字母外,大写每个单词的首字母。单词之间不用分隔符(如:下划线)。
使用变量目的是引用值,为便于了解变量值的含义,应该为变量选择既简单、又具有描述性的名字,尽量做到“顾名识义”。下面为一些好的标识符示例:
isFull、price、studentName
Java是区分大、小写字母,如:“order”与“Order”代表不同的标识符。
Java语言通过关键词“final”定义赋值后不能再更改的值,使其成为常量。如:
final double SALES_TAX = 6.25;
final double PI = 3.14159;
试图改变常量的值,将引起编译错误。也就是说,除非在定义之初,否则不能为常量赋值。
命名常量标识符也要尽量做到“顾名识义”,同时遵循Java技术约定:常量的标识符全部使用大写字母,可以有下划线。
1.3 基本运算
运算符连接数据形成表达式,实现对数据的运算。基本运算包括赋值运算、算术运算、逻辑运算、关系运算、位运算和位移位运算等。
在表达式中,运算符与操作数间遵守结合性规则,各运算符间按照优先级进行运算。基本运算符的结合性和优先级参见表7-4,其中,“R”代表“Right”;“L”代表“Left”,表中出现在同一行的各运算符具有相同的优先级;出现在不同行的运算符优先级从上到下依次递减。
表1-4 运算符
结合性规则 |
运 算 符 |
R to L |
++ -- + - ~ !(数据类型) |
L to R |
* / % |
L to R |
+ - |
L to R |
<< >> >>> |
L to R |
< > <= >= instanceof |
L to R |
== != |
L to R |
& |
L to R |
^ |
L to R |
| |
L to R |
&& |
L to R |
|| |
R to L |
?: |
R to L |
= *= /= %= += -= <<= |
表1-4中,<<、>>和>>>是整数移位运算符。
<<(左移)的运算规则是:将运算分量的每个二进制位向左移动指定位数,被移出的高位部分将丢弃,右边空出的低位部分补0。
>>(右移),也称算术右移或带符号右移,运算规则是:将运算分量的每个二进制位向右移动指定位数,右边被移出的低位部分将丢弃,左边空出的高位部分用符号填充。
>>>为逻辑右移、也称无符号右移,运算规则是:将运算分量的每个二进制位向右移动指定位数,右边被移出的低位部分将丢弃,左边空出的高位部分用0填充。
赋值运算符将运算符右边表达式的值赋给左边的变量。而*=、/=、%=、+=、-=、<<=、>>=、>>>=、&=、^=、|=等称为复合赋值运算符,是对赋值表达式的简写。如:
a=a+2 等价于 a+=2
value >>>= 1等价于value = value>>>1
instanceof用于判断对象的类型。
例1-1 位的“与”运算,文件名BitDemo.java。
//引自“The Java Tutorial”
class BitDemo {
public static void main(String[] args){
int bitmask = 0x000F;
int val = 0x2222;
System.out.println(val & bitmask);
}
}
运行结果:
2
Java语言规定源文件名是与类名绑定的,必须为类名加扩展名java,上例即BitDemo.java。因此,本书Java板块的实例,无须再专门指出每个Java类的源文件名。
1.4 赋值类型转换
数据类型的长度越长,即占用二进制位数越多,就认为其精度越高。无论是运算还是赋值,当数据类型不相同时,就会引起类型转换。在需要和允许的情况下,系统总是自动将变量向着更高精度类型的方向进行转换,避免引起信息丢失,这个过程也称类型提升(Promotion)。系统实现类型提升的重要前提条件是不会丢失信息。
在进行赋值时,只要被赋值变量的数据类型精度不低于赋值表达式的数据类型精度,就符合类型提升的条件,将是合法的赋值运算,并称表达式是赋值兼容的。如:
long bigval = 6; // 合法,6 为int型, 赋值兼容
int smallval = 99L; // 非法,99L是long型,无法实现类型提升
double z = 12.414F; //合法,12.414F为float型, 赋值兼容
float z1 = 12.414; // 非法,12.414为double型, 无法实现类型提升
如果将计算所得高精度的数据值赋给较低精度的变量,将会引起信息丢失,因此是系统所不允许的。需要程序员通过类型转换运算符“()”强制转换变量的数据类型,称为显式类型转换(cast)。如:
long bigValue = 99L; //合法,赋值运算符两边的数据类型相同
int squashed = bigValue; //非法,编译错误:可能会损失精度
int squashed =(int)bigValue; // 合法,对变量bigValue进行显式类型转换
int squashed = 99L; //非法,编译错误:可能会损失精度
int squashed =(int)99L; // 合法,但是不合理
int squashed = 99; // 合法,整型常量值的缺省类型为int
注意,在进行赋值运算时,Java语言与C语言不相同。在C语言中,将高精度数值赋给低精度变量是系统所允许的,不会出现编译错误。
在运算时,如果表达式所含各分量的数据类型不相同,系统将自动提升各变量到更高的精度类型,以避免信息丢失。例如:
long bigValue = 99L;
int squashed = 97;
bigValue =(squashed > bigValue)?squashed:bigValue;
//合法,bigValue的值为99
squashed =(squashed < bigValue)?squashed:bigValue;
//非法,编译错误:(赋值运算)可能会引起精度损失
int a = 1;
double d = 1.5;
long l = 2l;
System.out.println(d=(a+l)*d); // 合法,输出4.5
// 表达式d=(a+l)*d 可简写为(d*=(a+l))
System.out.println(d*=(a+l*1.5)); //合法,输出6.0
System.out.println(l=(a+l)*d);
//非法,编译错误:(赋值运算)可能会引起精度损失
2 Java语句
Java语句含基本语句和控制流语句。基本语句完成一些基本操作,如声明、赋值等。控制流语句用于控制程序流程,决定语句执行的顺序,包括选择语句和循环语句。
Java是结构化的程序设计语言,其程序有顺序、选择和循环三种基本结构组成。Java语言没有goto 语句。
2.1 语句、空语句和块
Java中的每条语句均以分号(;)结束,可以是单行或多行代码。
只有一个分号(;)的语句称为空语句,用在语法上需要出现一个语句,但语义上并不需要任何行为的情况。这种情况在if、for或 while、do-while这样的控制流语句中常会发生。Java程序中允许使用任意数量的空语句。
块是以左大括号和右大括号为边界的语句集合。块在语法上等价于单个语句,能用在单个语句可以出现的任何地方。语句块可以嵌套。
Java是面向对象的语言,Java程序以类的形式模块化。在类声明中必须使用块,如:
public class Dog {
private int weight;
}
2.2 选择语句
选择语句又称分支语句,用于改变程序顺序执行的流程,有选择地执行程序的不同部分。Java语言用于实现选择结构的语句有if和switch语句,可以实现单分支、双分支和多分支选择。
if语句的一般语法形式如下:
if(布尔表达式){
语句1或语句块1;
} else {
语句2或语句块2;
}
执行流程分别如图2.2和图2.3所示,其中else语句可缺省。
图2.2 if语句:单分支结构 图2.3 if-else语句:双分支结构
if-else语句可以嵌套,并经常用于处理多分支选择的问题。各个布尔表达式依次求值,一旦某个布尔表达式值为true,那么就执行与之相关的语句,从而终止整个语句序列的执行。如果所有表达式值为false,就执行最后一个else的相关部分。其语法形式如下:
if(布尔表达式1)
语句1或语句块1
else if(布尔表达式2)
语句2或语句块2
else if(布尔表达式3)
语句3或语句块3
……
else if(布尔表达式n)
语句n或语句块n
else
语句n+1或语句块n+1
switch语句是一种多分支选择语句,常用来实现多选择程序结构。其一般语法形式为:
switch(表达式){
case 常量表达式1: 语句或语句块1;break;
case 常量表达式2: 语句或语句块2;break;
……
case 常量表达式n: 语句或语句块n;break;
default: 语句或语句块n+1 break;
}
switch语句中的
case 常量表达式:
只起到标号的作用,用来指定语句执行的入口位置。如果case标号与switch表达式的值相匹配,就将从这个case标号的相关语句开始,执行包括其后所有case标号的语句序列以及default的语句序列。因此,为了实现正确的控制流程,需要使用break语句。
需要注意,每个case标号的常量表达式值各不相同。也就是说,case标号应该唯一。
switch语句中的default部分是任选的。如果所有case标号与switch表达式的值均不匹配,那么执行default的语句序列。虽然default部分可出现在switch语句的任何位置,但通常将其放在最后。
2.3 循环语句
Java语言的while、for和do-while语句都提供实现行为重复的功能,称为循环语句。while循环语句的一般语法形式为:
while(布尔表达式){
语句或语句块;
}
while语句的执行流程如图2.4所示,for语句的执行流程如图2.5所示。
图2.4 while 语句执行流程 图2.5 for 语句的执行流程
for循环语句的一般语法形式为:
for(初始化表达式; 布尔表达式; 增量表达式){
语句或语句块;
}
for(初始化表达式; 布尔表达式; 增量表达式)的三个表达式中,语法上任何一个都可以省略,但分号必须保留。缺省初始化表达式和增量表达式的for语句,其功能相当于while。
while与for这两个循环语句是先测试循环条件,再执行循环体。而do- while循环语句则是先执行循环体,再测试循环条件。只要条件为真,do-while循环就重复进行。区别在于,while与for语句可能出现不执行循环体的情况,而do- while语句的循环体至少要被执行一次,其条件测试语句在循环的底部。
do - while循环语句的一般语法形式为:
do{
语句或语句块
}while(布尔表达式)
无论for语句、while语句,还是do-while 语句,如果只有一条语句重复,那么大括号不是必需的。但是使用大括号程序结构更清楚,是良好的编程习惯。
例2-2 对int数据进行移位运算,并输出移位后的数值及位模式。
public class TestShift {
// bitPattern(int)方法用于建立位模式
public static String bitPattern(int value){
int BIT1_MASK = 1;
final char[] bits = new char[32];
for(int i = 31; i >= 0; i--){
if((value & BIT1_MASK)== 1){
bits[i] = '1';
} else {
bits[i] = '0';
}
value >>>= 1;
}
return new String(bits);
}
public static void main(String[] args){
int num1 = 1234;
int num2 = -1234;
System.out.println("num1(" + num1 + ")的位模式: " + bitPattern(num1));
System.out.println("num2(" + num2 + ")的位模式: " + bitPattern(num2));
System.out.println("" + num1 + " >> 5 =(" +(num1 >> 5)+ ")" + bitPattern(num1 >> 5));
System.out.println("" + num2 + " >> 5 =(" +(num2 >> 5)+ ")" + bitPattern(num2 >> 5));
System.out.println("" + num1 + " >>> 5 =(" +(num1 >>> 5)+ ")" + bitPattern(num1 >>> 5));
System.out.println("" + num2 + " >>> 5 =(" +(num2 >>> 5)+ ")" + bitPattern(num2 >>> 5));
System.out.println("" + num1 + " << 5 =(" +(num1 << 5)+ ")" + bitPattern(num1 << 5));
System.out.println("" + num2 + " << 5 =(" +(num2 << 5)+ ")" + bitPattern(num2 << 5));
}
}
运行结果:
num1(1234)的位模式: 00000000000000000000010011010010
num2(-1234)的位模式: 11111111111111111111101100101110
1234 >> 5 =(38)00000000000000000000000000100110
-1234 >> 5 =(-39)11111111111111111111111111011001
1234 >>> 5 =(38)00000000000000000000000000100110
-1234 >>> 5 =(134217689)00000111111111111111111111011001
1234 << 5 =(39488)00000000000000001001101001000000
-1234 << 5 =(-39488)11111111111111110110010111000000
2.4 break语句、continue语句和标号
在循环语句执行过程中,除了通过测试循环条件从循环语句的顶部或底部正常退出外,有时需要根据情况提前退出循环。正如break语句可以立即终止switch语句的执行,将控制流程转移到switch的下一条语句一样,break语句可用于中断循环,从for、while或do - while语句中提前退出。
continue语句绕过循环的剩余代码部分,强制执行循环条件测试。在 while与do-while语句中,continue语句的执行意味着控制流程转至测试循环条件部分;在for循环语句中,continue语句的执行则意味着控制流程转至增量表达式部分。continue语句只能用于循环语句,不能用于switch语句。
break和continue语句的区别在于,break中断整个循环的执行,而continue仅中断本次循环的执行,开始下一次循环。
特别要注意的是,break语句常出现在循环体包含的if-else结构中,但它的作用是退出循环,而不是跳出if-else结构。同时,break语句只终止包含它的for、while、do-while或者switch语句,它不会跳出嵌套的循环或者嵌套的switch语句。
标号是以冒号结尾的一个字符串,它的作用是指示程序中的一个位置点。如果需要一次退出多重循环,可以使用带标号的break语句。语法形式为:
break 标号;
其作用是跳出标号指示的循环,执行该循环的后续语句。
除带标号的break语句之外,还可以使用带标号的continue语句,其语法形式为:
continue 标号;
作用是中断本次循环,控制流程转向标号指定循环的条件判断,开始下一次循环。
一般来说,只建议将标号用于多重循环的外循环句首,目的是一次跳出多重循环,开始标号指定的循环语句的下一条语句(break)、或者下一次循环(continue)。
无论是break、continue语句,还是标号,都会影响程序的结构化,导致程序可读性下降。因此,Java语言中不只没有goto语句,也严格限制了标号的使用方式,并建议要尽量避免使用break或continue语句,除非这种做法极有效率和有必要,而通常情况下,总能找到解决问题的其他替代方式。
2.5 return语句和System.exit()方法
return语句从一个方法强制返回,并且可以为调用它的方法携带一个返回值。例如,下面的方法返回它的两个参数的乘积。
public int multiply(int a,int b){
return a*b
}
如果当前方法是main主方法,则执行return语句将会退出应用程序。
要想从程序的任意地方直接一步到位地退出程序,可以使用System.exit()方法。
2.6 注释语句和javadoc
Java有三种注释语句。
// 单行注释
/* */ 一行或多行注释
/** */ 文档注释
注释语句与程序的缩进书写风格一样,对Java编译器不会产生更多的信息,但是有助于理解程序,增加程序的可读性。
Java的文档注释语句,可用于产生注释文档。
文档对于程序来说非常重要。尤其对于中型、大型程序来说,文档是协作开发以及进行维护的重要依据。传统方式需要手工编写程序文档,是一项极为枯燥、繁琐的工作,质量难以保证,效率也很低。当程序修改时,必须及时更新文档,这一点往往容易被编程人员忽略,实际操作时也有很多困难。
Java系统提供的javadoc工具可以根据程序结构自动产生文档。当程序修改时,方便及时更新文档。
javadoc命令从文档注释语句中提取文档,生成的程序文档十分专业。所输出的文件是HTML格式的,可以通过Web浏览器查看,参见例2-3。
例2-3 用javadoc生成下面程序HelloDate.java的文档。
import java.util.*;
/** 引自Thinking in Java的实例程序
* Displays a string and today's date.
* @author Bruce Eckel
* @author www.MindView.net
* @version 4.0
*/
public class HelloDate {
/** Entry point to class & application.
* @param args array of string arguments
* @throws exceptions No exceptions thrown
*/
public static void main(String[] args){
System.out.println("Hello, it's: ");
System.out.println(new Date());
}
} /* Output:(55% match)
Hello, it's:
Wed Oct 05 14:39:36 MDT 2007
*/
运行结果:
Hello, it's:
Thu May 18 16:07:03 CST 2006
运行命令,为程序自动生成文档:
javadoc HelloDate.java
图2.6 运行javadoc的过程
javadoc在当前目录下生成了许多HTML文件,这些就是程序文档。其中,index.html文件是起始文档。打开该文件,显示内容如图2.7所示。
图2.7 javadoc生成的HelloDate.java程序文档部分页面
javadoc命令可以带参数,下面的javadoc命令可以将版本和作者信息写入文档,更新后的文档如图2.8所示。
javadoc HelloDate.java -version -author
javadoc还可以一次性为整个包生成文档,命令形式为:
javadoc 包名
需要了解javadoc命令的更多用法,可以通过如下命令获得帮助。
javadoc –help
图2.8 javadoc更新后的文档部分页面
3 Java API
Java包含了许多预定义的类,用不同的目录将这些类归入相关集合,从而构成包,这些包的总和称为Java应用程序编程接口,即Java API。其中,每个包都提供了相对独立、相对完整和相对专用的功能,编程时可以根据功能需要导入相应包,或者导入包中的有关类和接口。借助API的预编写代码,程序员能够省时省力地编写出高品质的代码。Java API是Java最显著的优点之一,Java API文档对于程序设计人员是非常有价值的资源。在学习Java时,应该多花时间阅读Java API文档,
在程序需要使用Java API定义的包、类和接口时,通过import语句导入,使编译器知道从什么位置装入所需类和接口。图3.9基于功能分类示意了常用API包概图,详细资料请查阅Java API文档。
图3.9 Java包的分类概图
4 Web中使用Java程序
Java起源于Internet,适合编写基于Internet和基于WWW的应用程序,是有效的网络编程语言。事实上,Java具有更大的潜力,不仅用于网络编程,也适合创建大型应用程序。Java迅速发展成为一种功能强大而有效的编程工具,成为世界上重要的具有通用目的的一种编程语言。
Web中使用Java主要有以下几种方式:
(1)使用JDK自带的appletviewer.exe调用
这种方式使用Java程序,首先要编制扩展了Applet类的应用程序,基本形式为:
Import java.applet.*;
Public class className extends Applet
{
//Java程序体
}
然后要编制一个调用上述类的HTML页面文件(如为testApplet.htm),插入这个对象,即在其中写上:
<applet code=className.class height=givenHeight width=givenWidth>
</applet>
这里className是类名,givenHeight和givenWidth分别为给定的applet作为插件在网页中的高度和宽度。
最后在命令提示符下用appletviewer.exe运行:
appletviewer testApplet.htm
(2)采用基本JSP方式
夹在HTML网页中的Java语句组或程序,只要用开始符“<%”和结束符“%>”隔开,在页面任意地方都可以运行,可以犬牙交错与HTML互相穿插。这种页面需要用“.jsp”作为扩展名,不能直接点击运行,需要放在在Web服务器中以网址的形式访问。第1章中的三个例子即如此。详见本书JSP板块的第13章至第15章。
(3)采用Servlet方式
Servlet是用Java编写的服务器端小程序,与客户端的applet小程序对应。Servlet和applet分别在处于服务器和客户机两端。Servlet没有main方法,要继承特定的类,编写特定的方法。详见本书JSP板块的第17章。
(4)采用JavaBean方式
JavaBean作为Java语言写成的可重用组件,是一种特殊的类,在Web编程中广泛使用。很多重复使用的算法或业务逻辑都编写成JavaBean,然后在JSP页面中通过<useBean>标记引用。详见本书JSP板块的第18章和第26章。
小 结
Java是面向对象的编程语言。
Java语言定义了四类八种基本数据类型,分别是boolean、char、byte、short、int、long、double和float。Java使用Unicode字符集。
不同类型的数据之间实现计算或赋值,将发生类型转换。类型提升(promotion)由系统自动实现,类型转换(cast)需要程序员通过类型转换运算符“()”强制进行。
Java技术约定,变量标识符以小写字母开头。常量的标识符全部使用大写字母,可以有下划线。
Java控制流语句实现选择和循环结构。return语句返回调用方法,并可携带一个返回值。System.exit()方法从程序的任意地方直接退出程序。
Java语言有单行、多行和文档注释三种注释语句。javadoc命令从文档注释语句中提取信息,生成HTML格式的程序文档。
Java API包中含有大量的类和接口,程序员可以根据需要使用这些类。