第 3章 表达式和流程控制语句表达式
定义:由 运算符 和 操作数 组成,对操作数进行运算符指定的操作,并得出一个结果
Java运算符按功能可分为:算术运算符、关系运算符、
逻辑运算符、位运算符、赋值运算符、条件运算符、
数组下标运算符等。 操作数可以是变量、常量或具有返回值的方法调用等
如果表达式中仅含有算术运算符,如,*”,则为算术表达式,计算结果是算术量(,+”用于字符串连接除外)
如果表达式中含有关系运算符,如,>”,则为关系表达式,计算结果是逻辑值,即 true或 false
如果表达式中含有逻辑运算符,则为逻辑表达式,相应的计算结果为逻辑值操作数
常量
只有简单数据类型和 String类型才有相应的常量形式常量 含义
23.59 double型常量
-1247.1f float型常量
true boolean型常量
"This is a String" String型常量操作数
变量
存储数据的基本单元,它可以用作表达式中的操作数,在使用之前要先说明
变量说明的基本格式为:
类型 变量名 1[ = 初值 1][,变量名 2 [= 初值 2]]…;
类型既可以是简单类型,也可以是类类型。有时也把类类型的变量称为引用。
变量说明的地方有两处,一处是在 方法内,另一处是在 类定义内 。方法内定义的变量称作自动变量,局部变量、临时变量或栈变量。类中定义的变量就是它的成员变量。
简单类型的变量在说明之后,系统自动在内存分配相应的存储空间。说明引用后,系统只分配引用空间,程序员要调用 new来创建对象实例,然后才分配相应的存储空间。
操作数
变量初始化
Java不允许将未经初始化的变量用做操作数。
对简单变量在说明的同时可以进行初始化如 int x=3,y=4;
创建一个对象后,使用 new运算符分配存储空间时,系统按表中的值自动初始化成员变量类型 初始值
byte (byte)0
short (short)0
int 0
long 0L
float 0.0f
double 0
char \u0000'(null)
boolean FALSE
所有引用类型 null
操作数
自动变量在使用之前必须初始化
编译器扫描代码,判定每个变量在首次使用前是否已被显式初始化。如果某个变量没有初始化,会发生编译时错误
例 3-2
int x = (int)( Math.random() * 100 );
int y;
int z;
if (x > 50) {
y = 9;
}
z = y + x; // 可能在初始化之前使用,导致编译错误操作数
变量作用域
变量的作用域是指可访问该变量的代码范围
类中定义的成员变量的作用域是整个类
方法中定义的局部变量的作用域是从该变量的说明处开始到包含该说明的语句块结束处
块内说明的变量将屏蔽其所在类定义的同名变量操作数
程序 3-1 冲突引起编译错误例子操作数
程序 3-2 修改程序 3-1,把第二个局部变量说明改为赋值语句操作数
程序 3-3
main()方法中两次说明了同名局部变量 name,
但第 6行说明的变量只在第 6至第 9行的块内有效,在块外该变量消失,第 11行不在其作用域内运算符
算术运算符
算术运算符包括通常的加( +)、减( -)、乘( *)、
除( /)、取模( %),完成整型或浮点型数据的算术运算
算术运算符还有,++”、,--”两种,分别表示加 1和减
1操作
i=3;
b=i++; //执行完后 i为 4,b为 3。若改为 b=++i;执行后 i为 4,b
为 4
3/2 // 结果是 1
15.2 % 5 // 结果是 0.2
运算符
关系运算符
关系运算符用来比较两个值,包括大于( >)、
大于等于( >=)、小于( <)、小于等于
( <=)、等于( ==)、不等于( !=) 6种。关系运算符都是二元运算符,运算的结果是一个逻辑值
Java允许,==”和,!=”两种运算用于任何数据类型
可以判定两个实例是否相等
但要注意判断的是“引用”相等,还是对象的内容相等!
逻辑运算符
逻辑运算符包括逻辑与( &&)、逻辑或
( ||)和逻辑非( ! )。前两个是二元运算符,后一个是一元运算符
Java对逻辑与和逻辑或提供短路操作功能。
进行运算时,先计算运算符左侧表达式的值,
如果使用该值能得到整个表达式的值,则跳过运算符右侧表达式的计算,否则计算运算符右侧表达式,并得到整个表达式的值运算符 例 3-3
String unset = null;
if ((unset != null) && (unset.length() > 5)) {
// 对 unset进行某种操作
}
空串 unset不能使用,因此不能访问 unset.length()
if()语句中的逻辑表达式是合法的,且完全安全。因为第一个子表达式
( unset != null)结果为假,它马 上导致整个表达式的结果为假。所以 &&
运算符跳过不必要的( unset.length()
> 5)计算,因为没有计算它,避免了空指针异常 。
位运算符
位运算符用来对二进制位进行操作,包括按位取反( ~)、按位与( &)、按位或
( |)、异或( ^)、右移( >>)、左移
( <<)及无符号右移( >>>)。位运算符只能对 整型 和 字符型 数据进行操作。
运算符,>>”
运算符,>>”执行算术右移,它使用最高位填充移位后左侧的空位。右移的结果为:
每移一位,第一个操作数被 2除一次,移动的次数由第二个操作数确定。
128 >> 1 得到 64
256 >> 4 得到 16
-256 >> 4 得到 -16
逻辑右移运算符
逻辑右移或叫无符号右移运算符 >>>只对位进行操作,而没有算术含义,它用 0填充左侧的空位
算术右移不改变原数的符号,而逻辑右移不能保证这一点
(byte)0x80 >> 2 得到 –32
0xa2 >>> 2 得到 40
(byte) 0xa2 >> 2 得到 -24
(byte) 0xa2>>>2 得到 1073741800
移位运算符
移位运算符约简其右侧的操作数,当左侧操作数是 int类型时,右侧以 32取模;当左侧是 long类型时,右侧以 64取模
,>>>”运算符只用于整型,它只对 int或 long值起作用。如果用于 short或 byte值,则在进行,>>>”
操作之前,使用符号扩展将其提升为 int型,然后再移位
int x;
x = x >>> 32;
x的结果不改变,而不是通常期望的 0。
这样可以保证不会将左侧操作数完全移走。
其他运算符
Java中的运算符还包括扩展赋值运算符( =、
+=,-=,*=,/=,%=,&=,|=,^=,>>=、
<<=)及( >>>=),条件运算符(?:),点运算符(,),实例运算符( instanceof),
( new)运算符,数组下标运算符( [ ])
等。
扩展赋值运算符
扩展赋值运算符是在赋值号( =)前再加上其他运算符,是对表达式的一种简写形式。如果有赋值语句:
var = var op expression;
其中,var是变量,op是算术运算符或位运算符,
expression为表达式。使用扩展赋值运算符可表示为:
var op= expression;
例 3-6
条件运算符
条件运算符(?:)是三元运算符,它的一般形式为:
表达式? 语句 1,语句 2;
表达式得到一个逻辑值,根据该值的真假决定执行什么操作。如果值为真,执行语句 1,否则执行语句 2。
注意,语句 1和语句 2需要返回相同的类型,且不能是 void。
运算符的优先次序
运算符的优先次序
在对一个表达式进行计算时,如果表达式中含有多种运算符,则要按运算符的优先顺序依次从高向低进行,同级运算符则从左向右进行。
括号可以改变运算次序运算符的优先次序表达式的提升和转换
Java语言不支持变量类型间的自动任意转换,有时必须显式地进行变量类型的转换。
一般的原则是,变量和表达式可转换为更一般的形式,而不能转换为更受限制的形式
例如,int型表达式可看作是 long型的;而 long
型表达式当不使用显式转换时是不能看作 int型的
一般地,如果变量类型至少与表达式类型一样
(即位数一样多),就可以认为表达式是赋值相容的表达式的提升和转换
例 3-7
long bigval = 6; // 6是整型量,所以该语句正确
int smallval = 99L; // 99L是长整型量,该语句错误
float z = 12.414F; // 12.414F是浮点量,该语句正确
float z1 = 12.414; // 12.414是双精度量,该语句错误
99L是长整型量,smallval是 int型量,赋值不相容。
同样,12.414是双精度型的,不能赋给单精度变量 z1
表达式的提升和转换
long bigValue = 99L;
int squashed = (int) (bigValue);
当表达式不是赋值相容时,有时需进行转换以便让编译器认可该赋值
让一个 long型值“挤”入 int型变量中。显式转换如下:
转换时,目标类型用括号括起来,放到要修改的表达式的前面。为避免歧义,被转换的整个表达式最好也用括号括起来数学函数
数学函数类 Math,几个常用的函数调用:
Math.sin(0) //返回 0.0,这是 double类型的值
Math.cos(0) //返回 1.0
Math.tan(0.5) //返回 0.5463024898437905
Math.round(6.6) //返回 7
Math.round(6.3) //返回 6
Math.ceil(9.2) //返回 10,0
Math.ceil(-9.8) //返回 -9,0
Math.floor(9.2) //返回 9,0
Math.floor(-9.8) //返回 -10,0
Math.sqrt(144) //返回 12.0
Math.pow(5,2) //返回 25.0
Math.exp(2) //返回 7.38905609893065
Math.log(7.38905609893065) //返回 2.0
Math.max(560,289) //返回 560
Math.min(560,289) //返回 289
Math.random() //返回 0.0到 1.0之间双精度的一个随机数值流控制语句
语句与表达式
每个表达式都会得到一个值,即表达式的计算结果。语句也会有一个值,但这个值并不是语句的计算结果,而是执行结果
语句是 Java的最小执行单位,语句间以分号( ;)
作为分隔符。语句分为 简单语句 及 复合语句
简单语句就是通常意义下的一条语句,即单语句;而复合语句是一对花括号,{”和,}”括起来的语句组,也称为,块,,块后没有分号表达式语句
表达式可当作一个值,有的表达式也可当作语句
方法调用通常返回一个值,一般用在表达式中。有的方法调用可直接当作语句
System.out.println("Hello World!");
customer1 = new Customer();
point2 = new Point();
x = 12;
x++;

块是一对花括号,{”和,}”括起来的语句组。
例如:
方法体是一个块。块还用在流控制的语句中,如 if语句,switch语句及循环语句
{ }
{
Point point1 = new Point();
int x = point1.x;
}
分支语句
分支语句共有两种,if语句和 switch语句
if语句
是单重选择,最多只有两个分支。
if语句的基本格式是:
if (逻辑表达式 )
语句 1;
[else
语句 2;
]
分支语句
if关键字之后的逻辑表达式必须得到一个逻辑值,
不能象其他语言那样以数值来代替。因为 Java不提供数值与逻辑值之间的转换
int x = 3;
if (x)
{...}
i !=0)
if 语句常见的形式
形式一:
形式二:
if (逻辑表达式 ) {
//逻辑表达式为 true时要执行的语句 ;
}
if (逻辑表达式 ) {
//逻辑表达式为 true时要执行的语句 ;
}
else {
//逻辑表达式为 false时要执行的语句 ;
}
if 语句常见的形式三
形式三( if语句的嵌套 ):
if (逻辑表达式 1) {
//逻辑表达式 1为 true时要执行的语句 ;
}
else if (逻辑表达式 2) {
//逻辑表达式 1为 false,但逻辑表达式 2为 true时要执行的语句 ;
}

else {
//前面的逻辑表达式全为 false时要执行的语句 ;
}
if 语句
例 3-8
1 int count;
2 count = getCount();
3 if (count < 0) {
4 System.out.println("Error,count value is negative!");
5 }
6 else {
7 System.out.println("There will be " + count +
8 " people for lunch today.");
9 }
if 语句
else子句属于逻辑上离它最近的 if语句
if (firstVal == 0)
if (secondVal == 1)
firstVal++;
else
firstVal--;
这两个匹配
if 语句
例 3-10
1 if (firstVal == 0){
2 if (secondVal == 1)
3 firstVal++;
4 }
5 else
6 firstVal--;
这两个匹配
switch语句
switch语句含义与嵌套的 if语句是类似的,格式更加简捷
switch (表达式 ) {
case c1:
语句组 1;
break;
……
case ck:
语句组 k;
break;
[default:
语句组 ;
break;]
}
switch语句
表达式的计算结果必须是 int型或字符型,
即是 int型赋值相容的。当用 byte,short或
char类型时,要进行提升。 switch语句不允许使用浮点型或 long型表达式。 c1、
c2,…,ck是 int型或字符型常量。 default
子句是可选的,并且,最后一个 break语句完全可以不写。
switch语句例
例 3-11
1 // colorNum是整型变量
2 switch (colorNum) {
3 case 0:
4 setBackground(Color.red);
5 break;
6 case 1:
7 setBackground(Color.green);
8 break;
9 default:
10 setBackground(Color.black);
11 break;
12 }
switch语句
switch语句和 if语句可以互相代替
例 3-11用 if语句实现:
if (colorum == 0)
setBackground(Color.red);
else if (colorNum == 1)
setBackground(Color.green);
else
setBackground(Color.black);
例 3-13
使用 if语句:
static int daysInMonth(int month) {
if (month == 2)
return(28);
if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
return(30);
return(31);
}
使用 switch语句:
static int daysInMonth(int month) {
int days;
switch(month) {
case 2,days = 28; break;
case 4,
case 6,
case 9,
case 11,days = 30; break;
default,days = 31;
}
return(days);
}
分支语句
程序 3-4
当主程序执行时,如果第一个命令行参数的首字符分别是数字、小写字母及大写字母时,系统会显示这个首字符。如果输入的是非数字或字母,则显示不是数字或字母。输出如图所示:
分支语句
如果上述方法中的最后一个 break语句(第 32行)不写的话,程序执行完第 30,31行后将不停止,一直执行下去。程序的输出如图 3-6所示:
循环语句
三种循环语句,for语句,while语句和 do语句
for语句语法格式:
for语句的语义是
先执行初始语句,判断逻辑表达式的值,当逻辑表达式为真时,执行循环体语句,执行迭代语句,然后再去判别逻辑表达式的值。直到逻辑表达式的值为假时,循环结束
for (初始语句 ; 逻辑表达式 ; 迭代语句 )
循环体语句 ;
循环语句
例 3-14 该段程序共执行 3次第 2行的输出语句( i为 0,1,2时)。当 i等于 3时,逻辑表达式的值为假,退出循环,执行第 4行语句
for (int i = 0; i < 3; i++) {
System.out.println("Are you finished yet?");
}
System.out.println("Finally!");Are you finished yet?
Are you finished yet?
Are you finished yet?
Finally!
循环变量循环语句
例 3-15
for ( ; ; )
System.out.println("Always print!");
该语句等价于:
for ( ; true ; )
System.out.println("Always print!");
这段循环不会停止。
循环语句
下面是初始语句及迭代语句包含多个语句时的情况:
例 3-16
int sumi = 0,sumj = 0;
for ( int i = 0,j = 0; j < 10; i++,j++) {
sumi += i;
sumj += j;
}
while循环
while循环
for语句中常常用循环控制变量显式控制循环的执行次数。当程序中不能明确地指明循环的执行次数时,可以仅用逻辑表达式来决定循环的执行与否。这样的循环可用 while语句来实现
while循环的语法是:
while (逻辑表达式 )
语句 ;
和 if语句一样,while语句中的逻辑表达式亦不能用数值来代替循环语句
while语句的语义:
计算逻辑表达式,当逻辑表达式为真时,重复执行循环体语句,直到逻辑表达式为假时结束。
如果第一次检查时逻辑表达式为假,则循环体语句一次也不执行。如果逻辑表达式始终为真,
则循环不会终止循环语句
例 3-14的 for语句可以改写为例 3-17中的
while语句
int i = 0;
while (i < 3) {
System.out.println("Are you finished yet?");
i++;
}
System.out.println("Finally!");
do循环
do语句与 while语句很相似。它把 while语句中的逻辑表达式移到循环体之后。 do语句的语法格式是:
do语句的语义是:
首先执行循环体语句,然后判定逻辑表达式的值,当表达式为真时,重复执行循环体语句,
直到表达式为假时结束。不论逻辑表达式的值是真是假,do循环中的循环体都至少执行一次
do
语句 ;
while (逻辑表达式 );
循环语句 例
例 3-18
1 //do语句
2 int i = 0;
3 do {
4 System.out.println("Are you finished yet?");
5 i++;
6 } while (i < 3);
7 System.out.println("Finally!");
循环语句
for,while及 do语句可互相替代例如:
do
语句 1;
while (逻辑表达式 );
等价于:
语句 1;
while(逻辑表达式 )
语句 1;
break与 continue
Java语言抛弃了 goto语句,代之以两条特殊的 break和 continue语句
标号
标号可以放在 for,while或 do语句之前,其语法格式为:
标号,语句 ;
break语句
break语句可用于三类语句中
一类是 switch语句中,一类是 for,while及 do
等循环语句中,还有一类是块语句中
在 switch语句及循环语句中 break的语义是跳过本块中余下的所有语句,转到块尾,
执行其后的语句
for (int i = 0; i < 100; i++) {
if ( i == 5 )
break;
System.out.println("i= " + i);
}
break语句
break语句的第三种使用方法是和标号结合使用,其语义是跳出标号所标记的语句块,继续执行其后的语句。多用于嵌套块中,控制从内层块跳到外层块之后。其语法格式为:
break 标号 ;
out,for (int i=0; i<10; i++) {
while (x<50) {
if ( i*x == 400)
break out;
}
}
break与 continue
程序 3-5
continue语句
在循环语句中,continue可以立即结束当次循环而执行下一次循环,当然执行前先判断循环条件是否满足
continue语句也可以和 标号 一起使用,立即结束标号标记的那重循环的当次执行,
开始下一次循环。多用于多重循环中。 其语法格式为:
continue 标号 ;
例 3-20
例 3-20
结果,
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
注释语句
Java中共有三种注释形式:
// 在一行内的注释
/* 一行或多行的注释 */
/** 文档注释 */
注释语句
第一种形式表示从,//”开始一直到行尾均为注释,
一般用它对说明的变量、一行程序的作用作简短说明
第二种形式可用于 多行注释,,/*”是注释的开始,
,*/”表示注释结束,,/*”和,*/”之间的所有行均是注释语句。这种注释多用来说明方法的功能等
第三种形式是 文档注释 。文档注释放在(一个变量或是一个函数的)说明之前,表示该段注释应包含在自动生成的任何文档中(即由 javadoc命令生成的 HTML文件)