欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/51040228
控制程序流程
在Java 里,我们利用运算符操纵对象和数据,并用执行控制语句作出选择。Java 是建立在C++基础上的,所以对C 和C++程序员来说,对Java 这方面的大多数语句和运算符都应是非常熟悉的。当然,Java 也进行了自己的一些改进与简化工作。
1 使用 Java 运算符
加号(+)、减号和负号(-)、乘号(*)、除号(/)以及等号(=)的用法与其他所有编程语言都是类似的。
算术运算举例如下:
class Number {
inti;
}
publicclass test {
publicstaticvoid 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 发生改变。
输出如下:
1:n1.i: 9, n2.i: 47
2:n1.i: 47, n2.i: 47
3:n1.i: 27, n2.i: 27
再来看下方法调用中的别名处理:
class Letter {
charc;
}
publicclass test {
staticvoid f(Lettery) {
y.c ='z';
}
publicstaticvoid 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: z
2 算术运算符
Java 的基本算术运算符与其他大多数程序设计语言是相同的。其中包括加号(+)、减号(-)、除号(/)、乘号(*)以及模数(%,从整数除法中获得余数)。整数除法会直接砍掉小数,而不是进位。 Java也用一种简写形式进行运算,并同时进行赋值操作。这是由等号前的一个运算符标记的,而且对于语言中的所有运算符都是固定的。例如,为了将4 加到变量x,并将结果赋给x,可用:x+=4。
示例如下:
import java.util.*;
publicclass test {
//Create a shorthand to save typing:
staticvoid prt(Strings) {
System.out.println(s);
}
//shorthand to print a string and anint:
staticvoid pInt(Strings,inti) {
prt(s +" = " +i);
}
//shorthand to print a string and a float:
staticvoid pFlt(Strings,floatf) {
prt(s +" = " +f);
}
publicstaticvoid main(String[] args) {
//Create a random number generator,
// seeds with current time by default:
Random rand =new Random();
inti,j,k;
// '%' limits maximum value to 99:
j =rand.nextInt() % 100;
k =rand.nextInt() % 100;
pInt("j",j); pInt("k",k);
i =j +k;pInt("j + k",i);
i =j -k;pInt("j - k",i);
i =k /j;pInt("k / j",i);
i =k *j;pInt("k * j",i);
i =k %j;pInt("k % j",i);
j %=k;pInt("j %= k",j);
// Floating-point number tests:
floatu,v,w; //applies to doubles, too
v =rand.nextFloat();
w =rand.nextFloat();
pFlt("v",v);pFlt("w",w);
u =v +w;pFlt("v + w",u);
u =v -w;pFlt("v - w",u);
u =v *w;pFlt("v * w",u);
u =v /w;pFlt("v / w",u);
// the following also works for
// char, byte, short,int, long,
// and double:
u +=v;pFlt("u += v",u);
u -=v;pFlt("u -= v",u);
u *=v;pFlt("u *= v",u);
u /=v;pFlt("u /= v",u);
}
} ///:~
prt()方法打印一个String;pInt()先打印一个String,再打印一个int;而pFlt()先打印一个 String,再打印一个float。当然,它们最终都要用System.out.println()结尾。
为生成数字,程序首先会创建一个 Random(随机)对象。由于自变量是在创建过程中传递的,所以 Java 将当前时间作为一个“种子值”,由随机数生成器利用。通过Random 对象,程序可生成许多不同类型的随机数字。只需调用不同的方法即可:nextInt(),nextLong(),nextFloat()或者nextDouble()。
若随同随机数生成器的结果使用,模数运算符(%)可将结果限制到运算对象减1的上限(本例是99)之下。
输出如下:
j= -58
k= 13
j+ k = -45
j- k = -71
k/ j = 0
k* j = -754
k% j = 13
j%= k = -6
v= 0.88164216
w= 0.17560738
v+ w = 1.0572495
v- w = 0.7060348
v* w = 0.15482287
v/ w = 5.02053
u+= v = 5.9021726
u-= v = 5.02053
u*= v = 4.426311
u /= v = 5.02053
3 自动递增和递减
和C 类似,Java 提供了丰富的快捷运算方式。这些快捷运算可使代码更清爽,更易录入,也更易读者辨读。
两种很不错的快捷运算方式是递增和递减运算符(常称作“自动递增”和“自动递减”运算符)。其中,递减运算符是“--”,意为“减少一个单位”;递增运算符是“++”,意为“增加一个单位”。
对每种类型的运算符,都有两个版本可供选用;通常将其称为“前缀版”和“后缀版”。“前递增”表示++运算符位于变量或表达式的前面;而“后递增”表示++运算符位于变量或表达式的后面。类似地,“前递减”意味着--运算符位于变量或表达式的前面;而“后递减”意味着--运算符位于变量或表达式的后面。对于前递增和前递减(如++A或--A),会先执行运算,再生成值。而对于后递增和后递减(如A++或A--),会先生成值,再执行运算。下面是一个例子:
publicclass test {
publicstaticvoid main(String[] args) {
inti = 1;
prt("i : " +i);
prt("++i : " + ++i);// Pre-increment
prt("i++ : " +i++);// Post-increment
prt("i : " +i);
prt("--i : " + --i);// Pre-decrement
prt("i-- : " +i--);// Post-decrement
prt("i : " +i);
}
staticvoid prt(Strings) {
System.out.println(s);
}
} ///:~
输出如下:
i: 1
++i: 2
i++: 2
i: 3
--i: 2
i--: 2
i : 1
4 关系运算符
关系运算符生成的是一个“布尔”(Boolean)结果。它们评价的是运算对象值之间的关系。若关系是真实的,关系表达式会生成 true(真);若关系不真实,则生成false(假)。关系运算符包括小于(<)、大于(>)、小于或等于(<=)、大于或等于(>=)、等于(==)以及不等于(!=)。等于和不等于适用于所有内建的数据类型,但其他比较不适用于boolean类型。
示例如下:
publicclass test {
publicstaticvoid main(String[] args) {
Integer n1 =new Integer(47);
Integer n2 =new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
} ///:~
输出如下:
false
true
达式System.out.println(n1== n2)可打印出内部的布尔比较结果。一般人都会认为输出结果肯定先是true,再是 false,因为两个Integer 对象都是相同的。但尽管对象的内容相同,句柄却是不同的,而==和!=比较的正好就是对象句柄。所以输出结果实际上先是false,再是 true。
若想对比两个对象的实际内容是否相同,又该如何操作呢?此时,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“主类型”,那些类型直接使用==和!=即可。
5 逻辑运算符
逻辑运算符 AND(&&)、OR(||)以及 NOT(!)能生成一个布尔值(true 或false)——以自变量的逻辑关系为基础。下面这个例子向大家展示了如何使用关系和逻辑运算符。
示例如下:
import java.util.*;
publicclass test {
publicstaticvoid main(String[] args) {
Random rand =new Random();
inti =rand.nextInt() % 100;
intj =rand.nextInt() % 100;
prt("i = " +i);
prt("j = " +j);
prt("i > j is " + (i > j));
prt("i < j is " + (i < j));
prt("i >= j is " + (i >= j));
prt("i <= j is " + (i <= j));
prt("i == j is " + (i == j));
prt("i != j is " + (i != j));
//Treating anint as a boolean is
// notlegal Java
//! prt("i && jis " + (i && j));
//! prt("i || j is "+ (i || j));
//! prt("!i is " +!i);
prt("(i < 10) && (j < 10) is "
+ ((i < 10) && (j < 10)) );
prt("(i < 10) || (j < 10) is "
+ ((i < 10) || (j < 10)) );
}
staticvoid prt(Strings) {
System.out.println(s);
}
} ///:~
6 按位运算符
按位运算符允许我们操作一个整数主数据类型中的单个“比特”,即二进制位。按位运算符会对两个自变量中对应的位执行布尔代数,并最终生成一个结果。
按位运算来源于C 语言的低级操作。我们经常都要直接操纵硬件,需要频繁设置硬件寄存器内的二进制位。
Java 的设计初衷是嵌入电视顶置盒内,所以这种低级操作仍被保留下来了。然而,由于操作系统的进步,现在也许不必过于频繁地进行按位运算。
若两个输入位都是1,则按位AND 运算符(&)在输出位里生成一个 1;否则生成0。若两个输入位里至少有一个是1,则按位OR运算符(|)在输出位里生成一个 1;只有在两个输入位都是0 的情况下,它才会生成一个0。若两个输入位的某一个是1,但不全都是1,那么按位 XOR(^,异或)在输出位里生成一个1。按位NOT(~,也叫作“非”运算符)属于一元运算符;它只对一个自变量进行操作(其他所有运算符都是二元运算符)。按位NOT生成与输入位的相反的值——若输入 0,则输出1;输入1,则输出0。
按位运算符和逻辑运算符都使用了同样的字符,只是数量不同。因此,我们能方便地记忆各自的含义:由于“位”是非常“小”的,所以按位运算符仅使用了一个字符。
按位运算符可与等号(=)联合使用,以便合并运算及赋值:&=,|=和^=都是合法的(由于~是一元运算符,所以不可与=联合使用)。
我们将boolean(布尔)类型当作一种“单位”或“单比特”值对待,所以它多少有些独特的地方。我们可执行按位AND,OR和XOR,但不能执行按位 NOT(大概是为了避免与逻辑NOT混淆)。对于布尔值,按位运算符具有与逻辑运算符相同的效果,只是它们不会中途“短路”。此外,针对布尔值进行的按位运算为我们新增了一个XOR逻辑运算符,它并未包括在“逻辑”运算符的列表中。在移位表达式中,我们被禁止使用布尔运算。
7 移位运算符
移位运算符面向的运算对象也是二进制的“位”。可单独用它们处理整数类型(主类型的一种)。左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补 0)。“有符号”右移位运算符(>>)则将运算符左边的运算对象向右移动运算符右侧指定的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1。Java也添加了一种“无符号”右移位运算符(>>>),它使用了“零扩展”:无论正负,都在高位插入0。这一运算符是C或C++没有的。
若对char,byte 或者short 进行移位处理,那么在移位进行之前,它们会自动转换成一个int。只有右侧的5个低位才会用到。这样可防止我们在一个 int数里移动不切实际的位数。若对一个long 值进行处理,最后得到的结果也是long。此时只会用到右侧的 6个低位,防止移动超过 long 值里现成的位数。但在进行“无符号”右移位时,也可能遇到一个问题。若对byte 或short 值进行右移位运算,得到的可能不是正确的结果(Java 1.0 和Java 1.1 特别突出)。它们会自动转换成int 类型,并进行右移位。但“零扩展”不会发生,所以在那些情况下会得到-1 的结果。
publicclass test {
publicstaticvoid main(String[] args) {
inti = -1;
i >>>= 10;
System.out.println(i);
longl = -1;
l >>>= 10;
System.out.println(l);
shorts = -1;
s >>>= 10;
System.out.println(s);
byteb = -1;
b >>>= 10;
System.out.println(b);
}
} ///:~
输出:
4194303
18014398509481983
-1
-1
移位可与等号(<<=或>>=或>>>=)组合使用。此时,运算符左边的值会移动由右边的值指定的位数,再将得到的结果赋回左边的值。
8 造型运算符
“造型”(Cast)的作用是“与一个模型匹配”。在适当的时候,Java 会将一种数据类型自动转换成另一种。例如,假设我们为浮点变量分配一个整数值,计算机会将 int自动转换成 float。通过造型,我们可明确设置这种类型的转换,或者在一般没有可能进行的时候强迫它进行。 为进行一次造型,要将括号中希望的数据类型(包括所有修改符)置于其他任何值的左侧。
正如您看到的那样,既可对一个数值进行造型处理,亦可对一个变量进行造型处理。但在这儿展示的两种情况下,造型均是多余的,因为编译器在必要的时候会自动进行 int值到long 值的转换。当然,仍然可以设置一个造型,提醒自己留意,也使程序更清楚。在其他情况下,造型只有在代码编译时才显出重要性。在C 和C++中,造型有时会让人头痛。
在Java 里,造型则是一种比较安全的操作。但是,若进行一种名为“缩小转换”(Narrowing Conversion)的操作(也就是说,脚本是能容纳更多信息的数据类型,将其转换成容量较小的类型),此时就可能面临信息丢失的危险。此时,编译器会强迫我们进行造型,就好象说:“这可能是一件危险的事情——如果您想让我不顾一切地做,那么对不起,请明确造型。”而对于“放大转换”(Widening conversion),则不必进行明确造型,因为新类型肯定能容纳原来类型的信息,不会造成任何信息的丢失。
Java 允许我们将任何主类型“造型”为其他任何一种主类型,但布尔值(bollean)要除外,后者根本不允许进行任何造型处理。“类”不允许进行造型。为了将一种类转换成另一种,必须采用特殊的方法(字串是一种特殊的情况,本书后面会讲到将对象造型到一个类型“家族”里;例如,“橡树”可造型为“树”;反之亦然。但对于其他外来类型,如“岩石”,则不能造型为“树”)。
9 Java 没有“sizeof ”
在C 和C++中,sizeof()运算符能满足我们的一项特殊需要:获知为数据项目分配的字符数量。在C 和C++中,size()最常见的一种应用就是“移植”。不同的数据在不同的机器上可能有不同的大小,所以在进行一些对大小敏感的运算时,程序员必须对那些类型有多大做到心中有数。例如,一台计算机可用32位来保存整数,而另一台只用16位保存。显然,在第一台机器中,程序可保存更大的值。正如您可能已经想到的那样,移植是令C 和C++程序员颇为头痛的一个问题。
Java 不需要sizeof()运算符来满足这方面的需要,因为所有数据类型在所有机器的大小都是相同的。我们不必考虑移植问题——Java 本身就是一种“与平台无关”的语言。