3.1 使用Java 运算符
一个运算符可改变运算对象的值,这叫作“副作用”(Side Effect)。
几乎所有运算符都只能操作“主类型”(Primitives)。
唯一的例外是“=”、“==”和“!=”,它们能操作所有对象(也是对象易令人混淆的一个地方)。
除此以外,String 类支持“+”和“+=”。
3.1.1 优先级
3.1.2 赋值
取得右边的值,把它复制到左边。
左边的值必须是一个明确的、已命名的变量。
(如果您的 main()用 package 语句封装到一个文件里,那么必须在程序名前面指定完整的包裹名称,否则不能运行程序。在这种情况下,命令行是:java c03.Assignment)
对一个对象进行操作时,我们真正操作的是它的句柄。所以倘若“从一个对象到另一个对象”赋值,实际就是将句柄从一个地方复制到另一个地方。这意味着假若为对象使用“C=D”,那么C 和 D 最终都会指向最初只有 D 才指向的那个对象。
3.1.3 算术运算符
用于打印(显示)的一些快捷方法:prt()方法打印一个String;pInt()先打印一个 String,再打印一个 int;而pFlt()先打印一个 String,再打印一个 float。当然,它们最终都要用System.out.println()结尾。
Random(随机)对象。
3.1.4 自动递增和递减
对于前递增和前递减(如++A 或–A),会先执行运算,再生成值。而对于后递增和后递减(如A++或A–),会先生成值,再执行运算。
3.1.5 关系运算符
尽管对象的内容相同,句柄却是不同的,而==和!=比较的正好就是对象句柄。
若想对比两个对象的实际内容是否相同,又该如何操作呢?此时,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“主类型”,那些类型直接使用==和!=即可。
3.1.6 逻辑运算符
只可将 AND,OR 或NOT 应用于布尔值。
操作逻辑运算符时,我们会遇到一种名为“短路”的情况。这意味着只有明确得出整个表达式真或假的结论,才会对表达式进行逻辑求值。
3.1.7 按位运算符
按位运算符可与等号(=)联合使用,以便合并运算及赋值:&=,|=和^=都是合法的(由于~是一元运算符,所以不可与=联合使用)。
我们可执行按位AND,OR 和 XOR,但不能执行按位 NOT。对于布尔值,按位运算符具有与逻辑运算符相同的效果,只是它们不会中途“短路”。
3.1.8 移位运算符
左移位运算符(<<)在低位补0。
“有符号”右移位运算符(>>)
“无符号”右移位运算符(>>>)
移位可与等号(<<=或>>=或>>>=)组合使用。此时,运算符左边的值会移动由右边的值指定的位数,再将得到的结果赋回左边的值。
pBinInt()和pBinLong()。它们分别操作一个int 和long 值,并用一种二进制格式输出,同时附有简要的说明文字。
3.1.9 三元 if-else 运算符
布尔表达式 ? 值 0:值 1
3.1.10 逗号运算符
在Java 里需要用到逗号的唯一场所就是for 循环
3.1.11 字串运算符+
在Java 里有一项特殊用途:连接不同的字串。
“缩小转换”(Narrowing Conversion)
“放大转换”(Widening conversion)
3.1.12 运算符常规操作规则
3.1.13 造型运算符
“造型”(Cast)的作用是“与一个模型匹配”。
表达式中最大的数据类型是决定了表达式最终结果大小的那个类型。
3.1.14 Java 没有“sizeof”
Java 不需要 sizeof()运算符来满足这方面的需要,因为所有数据类型在所有机器的大小都是相同的。我们不必考虑移植问题——Java 本身就是一种“与平台无关”的语言。
3.1.15 复习计算顺序
3.1.16 运算符总结
3.2 执行控制
3.2.1 真和假
3.2.2 if-else
将流程控制语句缩进排列
if(布尔表达式)
语句
if(布尔表达式)
语句
else
语句
3.2.3 反复
while(布尔表达式)
语句
3.2.4 do-while
do
语句
while(布尔表达式)
while 和do-while 唯一的区别就是do-while 肯定会至少执行一次
3.2.5 for
for(初始表达式; 布尔表达式; 步进)
语句
无论初始表达式,布尔表达式,还是步进,都可以置空。每次反复前,都要测试一下布尔表达式。若获得的结果是 false,就会继续执行紧跟在 for 语句后面的那行代码。在每次循环的末尾,会计算一次步进。
for 循环通常用于执行“计数”任务。
for( char c = 0; c < 128; c++)
Java 里唯一用到逗号运算符的地方就是for 循环的控制表达式。在控制表达式的初始化和步进控制部分,我们可使用一系列由逗号分隔的语句。而且那些语句均会独立执行。
3.2.6 中断和继续
break 用于强行退出循环,不执行循环中剩余的语句。
continue 则停止执行当前的反复,然后退回循环起始和,开始新的反复。
“无限循环”
标签机制,如汇编语言的跳转。
e.g.:while:
(1) 简单的一个 continue 会退回最内层循环的开头(顶部),并继续执行。
(2) 带有标签的 continue 会到达标签的位置,并重新进入紧接在那个标签后面的循环。
(3) break 会中断当前循环,并移离当前标签的末尾。
(4) 带标签的break 会中断当前循环,并移离由那个标签指示的循环的末尾。
3.2.7 开关
switch(整数选择因子) {
case 整数值 1 : 语句; break;
case 整数值 2 : 语句; break;
case 整数值 3 : 语句; break;
case 整数值 4 : 语句; break;
case 整数值 5 : 语句; break;
//..
default:语句;
}
3.3 总结
3.4 练习
1.编写程序以打印从1到100的值。
package control;
public class E01_To100{
public static void main(String[] args){
for(int i=1;i<=100;i++)
System.out.print(i+" ");
}
}
2.编写程序以生成25个随机int值。 对每个值使用if-else语句将其分类为大于,小于或等于第二个随机生成的值。
package control;
import java.util.*;
public class E02_RandomInts{
static Random r=new Random(47);
public static void compareRand(){
int a=r.nextInt();
int b=r.nextInt();
System.out.println("a="+a+",b="+b);
if(a<b)
System.out.println("a<b");
else if (a>b)
System.out.println("a>b");
else
System.out.println("a=b");
}
public static void main)String[] args){
for(int i=0;i<25;i++)
compareRand();
}
}
3.修改练习2,使代码被“无限”while循环包围。 然后它将运行,直到您中断它,通常使用Control-C。
package control;
public class E03_RandomInts2{
public static void main(String[] args){
while(true)
E02_RandomInts.compareRand();
}
}
main()之外的方法完成了上一个练习中的大部分工作,因此这个解决方案只需要对main()进行微小的更改。 正确构建程序,在其生命周期内需要更少的代码更改。 好处可能在于降低软件的维护成本而不是初始版本的成本,但精心设计的程序通常更容易开始运行。
4.编写一个程序来检测和打印素数(整数只能被它们自己和1整除),使用两个嵌套的for循环和模数运算符(%)。
package control;
public class E04_FindPrimes{
public static void main(String[] args){
int max=100;
if(args.length!=0)
max=Integer.parseInt(args[0]);
for(int i=1;i<max;i++){
boolean prime=true;
for(int j=2;j<i;j++)
if(i%j==0)
prime=false;
if(prime)
System.out.print(i+" ");
}
}
}
注意,程序包括1作为素数,即使2通常被认为是最小素数。
找到素数的最快方法之一叫做the Sieve of Eratosthenes。
5.重复上一章的练习10,但使用三元运算符和按位测试而不是Integer.toBinaryString()来显示1和0。
私有静态方法toBinaryString()的行为类似于Integer.toBinaryString(),使用缓冲区来保存二进制数字,因为打印出遇到的数字会产生反转输出。
6.修改前两个程序中的两个test()方法,使它们有两个额外的参数,begin和end,这样testval就会测试它是否在(包括)begin和end之间的范围内。
package control;
public class E06_RangeTest{
static boolean test(int testval,int begin,int end){
boolean result=false;
if (testval>=begin && testval<=end)
result=true;
return result;
}
public static void main(String[] args){
System.out.println(test(10,5,15));
System.out.println(test(5,10,15));
System.out.println(test(5,5,5));
}
}
7.修改练习1,以便程序通过在值99处使用break关键字退出。请尝试使用return。
package control;
public class E07_To98{
public static void main(String[] args){
for(int i=1;i<=100;i++){
if(i==99)
break;
System.out.print(i+" ");
}
}
}
8.在for循环中创建一个switch语句,尝试每个case并打印一条消息。 在每个案例之后break并测试它,然后看看当你移除break时会发生什么。
package control;
public class E08_SwitchDemo{
public static void main(String[] args){
for(int i=0;i<7;i++)
switch(i){
case 1:System.out.println("case 1");break;
case 2:System.out.println("case 2");break;
case 3:System.out.println("case 3");break;
case 4:System.out.println("case 4");break;
case 5:System.out.println("case 5");break;
default: System.out.println("default");
}
}
}
有break的输出:
default
case 1
case 2
case 3
case 4
case 5
default
没有break的输出:
default
case 1
case 2
case 3
case 4
case 5
default
case 2
case 3
case 4
case 5
default
case 3
case 4
case 5
default
case 4
case 5
default
case 5
default
default
9.Fibonacci序列是数字1,1,2,3,5,8,13,21,34等的序列,其中每个数字(从第三个开始)是前两个的总和。 创建一个以整数作为参数的方法,并从头开始显示许多斐波那契数字。 例如,如果您运行java Fibonacci 5(其中Fibonacci是类的名称),则输出将为:1,1,2,3,5。
package control;
public class E09_Fibonacci{
static int fib(int n){
if(n<=2)
return 1;
return fib(n-1)+fib(n-2);
}
public static void main(String[] args){
int n=Integer.parseInt(args[0]);
if(n<0){
System.out.println("cannot use negative numbers");
return;
}
for (int i=1;i<=n;i++)
System.out.println(fib(i)+",");
}
}
此问题通常在介绍性编程类中提供,它使用递归,这意味着函数会调用自身,直到达到触底条件并返回。
10.吸血鬼号码具有偶数个数字,并且通过乘以包含结果的一半数字位数的一对数字而形成。 数字以任何顺序从原始数字中获取。 不允许成对的尾随零。 例子包括:1260 = 21×60,1827 = 21×87,2187 = 27× 81。编写一个程序,找到所有4位数的吸血鬼号码。
package control;
public class E10_Vampire{
public static void main(String[] args){
int[] startDigit=new int[4];
int[] productDigit=new int[4];
for(int num1=10;num1<=99;num1++)
for(int num2=num1;num2<=99;num2++){
// Pete Hartley's theoretical result:
// If x·y is a vampire number then
// x·y == x+y (mod 9)
if((num1*num2)%9!=(num1+num2)%9)
continue;
int product=num1*num2;
startDigit[0]=num1/10;
startDigit[1]=num1%10;
startDigit[2]=num2/10;
startDigit[3]=num2%10;
productDigit[0]=product/1000;
productDigit[1]=(product%1000)/100;
productDigit[2]=product%1000%100/10;
productDigit[3]=product%1000%100%10;
int count=0;
for(int x=0;x<4;x++)
for(int y=0;y<4;y++){
if(productDigit[x]==startDigit[y]){
count++;
productDigit[x]=-1;
startDigit[y]=-2;
if(count==4)
System.out.println(num1+*num2+":"+product);
}
}
}
}
}