第一章 Java程序设计概述java
在网页中运行的Java程序称为 applet.express
在服务器中运行的Java程序称为 servlet.数组
关于Java的常见误解:服务器
其中第三点说到: 3.Java是一种很是容易学习的程序设计语言app
像Java这种功能强大的语言大都不太容易学习. 首先,必须将编写玩具式程序的轻松和开发实际项目的艰难区分开来.函数
第二章 Java程序设计环境学习
Windows 或 Linux : 32位选择x86, 64位以 x64测试
第三章 Java的基本程序设计结构this
3.1 一个简单的Java应用程序编码
根据Java语言规范, main方法必须声明为pulic, 不过, 当main方法不是public时, 有些版本的Java解释器也能够执行Java程序.
在Java SE 1.4 及之后的版本中,强制main方法时public的.
3.2 注释
在Java中,有三种标记注释的方式。最经常使用的方式是使用 // ,其注释内容从 // 开始到本行结束
System.out.println(" We will not use 'Hello World!'"); // is this too cute?
当须要长篇的注释时时,既能够在每行注释前标记//,也可使用/* 和 */ 将一段比较长的注释括起来。
第三种注释能够用来自动生成文档,这种文档以/** 开始,以*/ 结束。
/** * This is the first sample program in Core Java Chapter 3 * @param args */ public static void main(String[] args) { System.out.println(" We will not use 'Hello World!'"); // is this too cute? }
在Java中, /* */ 注释不能嵌套。也就是说,不能简单地把代码用/* 和 */括起来做为注释,由于这段代码自己可能也含一个 */ 。
3.3 数据类型
Java是一种强类型语言. 这就意味着必须为每个变量声明一种类型.
在Java中,一共有8种基本类型(primitive type)
3.3.1 整型
其中有4种整型、2种浮点类型、1种用于表示Unicode编码的字符单元的字符类型 char 和 1 种用于表示真值的boolean 类型。
类型 | 存储需求 | 取值范围 |
int |
4字节 | -2 147 483 648 ~ 2 147 483 647 (正好超过21亿) |
short |
2字节 | -32 768 ~ 32767 |
long |
8字节 | -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807 |
byte |
1字节 | -128 ~ 127 |
在一般状况下,int类型最经常使用。但若是表示星球上的居住人数,就须要使用long类型了。byte 和 short 类型主要用于特定的应用场合,例如,底层的文件处理或者须要控制占用空间量的大数组。
3.3.2 浮点类型
浮点类型用于表示有小数部分的数值。在Java中有两种浮点类型
类型 | 存储需求 | 取值范围 |
float | 4字节 | 大约 +- 3.402 823 47E+38F(有效位数为6~7位) |
double | 8字节 | 大约 +- 1.797 693 134 862 315 72E+308(有效位数为15位) |
可使用十六进制表示浮点数值。例如,0.125=2-3 能够表示成0x1.0p-3
在十六进制表示法中,使用p表示指数,而不是e。注意,尾数采用十六进制,指数采用十进制。指数的基数是2,而不是10。
用于表示溢出或出错状况的三个特殊的浮点数值:
例如:一个正整数除以0的结果为正无穷大。计算0/0或者负数的平方根结果为NaN。
特别要说明的是,不能这样检测一个特定值是否等于Double.NaN:
double x = 0.2; if (x == Double.NaN){ // is never true System.out.println("x == Double.NaN"); }全部“非数值”的值都认为i是不相同的。然鹅,可使用Double.isNaN方法:
if (Double.isNaN(x))// check whether x is "not a number"浮点数不适用于没法接受舍入偏差的金融计算中。例如:
System.out.println(2.0-1.1); // 输出结果为:0.8999999999999999而不是凡人们想象的 0.9 。
这种舍入偏差的主要缘由是浮点数值采用二进制系统表示,而在二进制系统中没法精确地表示分数1/10 。
这就好像十进制没法精确地表示分数1/3 同样。
若是在数值计算中不容许有任何舍入偏差,就应该使用BigDecimal类。
3.3.3 char类型
char类型的字面量值要用单引号括起来。例如'A' 是编码值为65所对应的字符常量。它与"A" 不一样,"A"是包含一个字符A的字符串。char类型的值能够表示为十六进制,其范围从 \u0000 到 \Uffff 。例如:
\u2122 表示注册符号(™),\u03C0 表示希腊字母π。
3.3.4 Unicode与char类型
3.3.5 boolean类型
boolean(布尔)类型有两个值:false和true,用来判断逻辑条件。整型值和布尔值之间不能进行相互转换。
3.4 变量
3.4.1 变量初始化
3.4.2 常量
在Java中,可使用关键字static final 设置一个常量类。须要注意的是,常量类定义位于main方法地外部。
3.5 运算符
须要注意:整数被0除将会产生一个异常,而浮点数被0除将会获得无穷大或NaN结果。
3.5.1 数学函数与常量
在Java中,没有幂运算,须要借助Math类得pow方法。语句:
double x = 2; double a = 3; double y = Math.pow(x,a); System.out.println(y); // 输出 8.0
3.5.2 数值类型之间的转换
上图中6个实心箭头,表示无信息丢失的转换;有3个虚箭头,表示可能有精度损失地转换。例如:123456789 是一个大整数,它所包含的位数比float类型所可以表达的位数大,当将这个整数数值转换为float类型时,将会获得一样大小的结果,但却失去了必定的精度。
int n = 123456789; float f = n; // f is 1.23456792E8
当使用上面的两个数值进行二元操做时,先将两个操做数转换为同一种类型,而后再进行计算。
3.5.3 强制类型转换
在上一小节中看到,在必要的时候,int 类型地值将会自动地转换为double类型。但另外一方面,有时也须要将double转换成int。在Java中,容许进行这种数值之间的类型转换。固然,有可能会丢失一些信息。在这种状况下,须要经过强制类型转换(cast)实现这个操做。强制类型转换地格式是在圆括号中给出想要转换地目标类型,后面紧跟待转换地变量名。例如:
double x = 9.997; int nx = (int) x; // nx is 9
这样,变量nx的值为9。强制类型转换经过截断小数部分将浮点型转换为整型。
若是想对浮点数进行摄入运算,以便的到最接近的整数,那就须要使用Math.round()方法:
double x = 9.997; int nx = (int) Math.round(x); // nx is 10
如今,变量nx的值为10。当调用round的时候,仍然须要强制类型转换(int)。其缘由是round方法返回的结果是long类型,因为存在信息丢失的可能性,因此只有使用显式的强制类型转换才可以将long类型转换成int 类型。
3.5.4 结合赋值和运算符
能够在赋值中使用二元运算符,这是种很简便的方式。例如:
x += 4;
等价于:
x = x + 4;
(通常的,要把运算符放在=号左边,如*=或%=)。
注释:若是运算符获得一个值,其类型与左侧操做数的类型不一样,就会发生强制类型转换。例如,若是 x 是一个int,则如下语句:
x += 3.5;
是合法的,将把x 设置为(int)(x + 3.5)。
3.5.5 自增与自减运算符
因为自增,自减运算符会改变变量的值,因此他们的操做数不能是数值。例如, 4++; 就不是一个合法的语句。
运算符放在操做数后面是“后缀”形式,如: n++;
运算符放在操做数前面是“前缀”形式,如: ++n;
前缀形式会先完成加1,然后缀形式会使用变量原来的值。
int m = 7; int n = 7; int a = 2 * ++m; int b = 2 * n++; System.out.println("a now is :" + a +",and m now is "+m); // a now is :16,and m now is 8 System.out.println("b now is :" + b +",and n now is "+n); // b now is :14,and n now is 8
建议不要在表达式中使用++,由于这样的代码很容易让人困惑,并且会带来烦人的bug。
3.5.6 关系和boolean运算符
Java支持三元操做符?: ,这个操做符又是颇有用。若是条件为true,下面的表达式
condition ? expression1 : expression2
就为第一个表达式的值,不然计算为第二个表达式的值。例如:
int x = 3; int y = 4; int nx = x < y ? x : y; System.out.println(nx);
会返回x 和 y 中较小的一个。
3.5.7 位运算符
处理整型类型时,能够直接对组成整型数值的各个位完成操做。这意味着可使用掩码技术获得整数中的各个位。位运算符包括:
&("and") | ("or") ^ ("xor") ~ ("not")
这些运算符按位模式处理。例如,若是n是一个整数变量,并且用二进制表示的n 从右边数第4位为1,则:
int n = 8; int fourthBitFromRight = (n & 0b1000) / 0b1000; System.out.println(fourthBitFromRight); // 1 由于十进制 8 用二进制表示为 1000 int m = 4; fourthBitFromRight = (m & 0b1000) / 0b1000; // 0 由于十进制 4 用二进制表示为 0100 System.out.println(fourthBitFromRight);
会返回1,不然返回0。利用& 并结合使用适当的 2 的幂,能够把其余位掩掉,而只保留其中一位。
注释:应用在布尔值上,& 和 | 运算符也会获得布尔值。这些运算符与 && 和 || 运算符很相似,不过 & 和 | 运算符不采用“短路”方式求值,也就是说,获得计算结果以前两个操做数都须要计算。
另外,还有 >> 和 << 运算符将位模式左移或右移。须要创建位模式来完成位掩码,这两个运算符很方便:
int n = 4; int fourBitFromRight = (n & (1 << 3)) >> 3; System.out.println(fourBitFromRight); // 0
最后,>>> 运算符会用0 填充高位,这与 >> 不一样,它会用符号位填充高位。不存在 <<< 运算符。
警告:位移运算符的有操做要完成模32的运算,(除非左操做数是long类型,在这种状况下须要对右操做数模64)。例如,1<<35 的值等同于 1 << 3或8。
3.5.8 括号与运算符级别
同一级别的运算符按照从左到右的次序依次计算(除了表中给出的右结合运算符外)。例如:因为&&的优先级比||的优先级高,因此表达式
a && b || c ;
等价于
(a && b)|| c ;
又由于 += 是右结合运算符,因此表达式
a += b += c;
等价于
a += (b += c) ;
也就是将 b += c的结果(加上c以后的b)加到 a 上。
运算符 | 结合性 |
[].() (方法调用) | 从左至右 |
! ~ ++ -- +(一元运算) - (一元运算) () (强制类型转换) new | 从右至左 |
* / % | 从左至右 |
+ - | 从左至右 |
<< >> >>> | 从左至右 |
< <= > >= instanceof | 从左至右 |
== != | 从左至右 |
& | 从左至右 |
^ | 从左至右 |
| | 从左至右 |
&& | 从左至右 |
|| | 从左至右 |
?: | 从右至左 |
= += -= *= /= %= &= |= ^= <<= >>= >>>= | 从右至左 |
3.5.9 枚举类型
3.6 字符串
从概念上讲,Java字符串就是Unicode字符串序列。例如,串“Java\u2122” 由5个Unicode字符 J、a、v、a、和™。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预约义类,很天然地叫作String。
3.6.1 子串
String类的substring方法能够从一个较大的字符串提取出一个字串。
String greeting = "Hello"; String s = greeting.substring(0,3); // Hel
substring方法的第二个参数是不想复制的第一个位置。这里要复制位置为0、一、2(从0到2,包括0和2)的字符。在substring中从0开始计数,直到3为止,但不包含3。
substring的工做方式有一个优势:容易计算子串的长度。字符串s.substring(a,b)的长度为b-a。例如,子串“Hel”的长度为3-0=3。
3.6.2 拼接
若是须要把多个字符串放在一块儿,用一个定界符分隔,可使用静态join方法:
String all = String.join(" / ","S","M","L","XL"); System.out.println("all is the string : \""+all+"\"");
// all is the string : "S / M / L / XL"
3.6.3 不可变字符串
String类没有提供用于修改字符串的方法。若是但愿将greeting的内容改成"Help!",不能直接将greeting的最后两个位置的字符串修改成‘p’和‘!’。在Java中实现这项操做很是容易。首先提取须要的字符,而后在拼接上替换的字符串:
String greeting = "Hello"; greeting = greeting.substring(0,3) + "p!"; System.out.println("greeting is changed to \"" + greeting +"\""); // greeting is changed to "Help!"
因为不能修改Java字符串中的字符,因此在Java文档中将String类对象称为不可变字符串,如同数字3永远是数字3同样,字符串“Hello”永远包含字符H、e、l、l 和 o 的代码单元序列,而不能修改其中的任何一个字符。固然,能够修改字符串变量greeting,让它引用另一个字符串,这就如同能够将存放3的数值变量改为存放4同样。
不可变字符串却有一个优势:编译器可让字符串共享。
3.6.4 检查字符串是否相等
可使用equals方法检测两个字符串是否相等。对于表达式:
s.equals(t)
若是字符串s与字符串t相等则返回true;不然返回false。须要注意,s与t 能够是字符串变量,也能够是字符串字面量。例如,下面的表达式是合法的:
"Hello".equals(greeting);
要想检测两个字符串是否相等,而不区分大小写,可使用equalsIgnoreCase方法。
"Hello".equalsIgnoreCase(greeting);
必定不要使用==运算符检测两个字符串是否相等!这个运算符只可以肯定两个字符串是否放置的在同一个位置上。固然,若是字符串放置在同一个位置上,他们必然相等。可是彻底有可能将内容相同的多个字符串的拷贝放置在不一样的位置上。
String greeting = "Hello"; // initailize greeting to a string if (greeting == "Hello"){ System.out.println("greeting == \"Hello\""); // greeting == "Hello" }else { System.out.println("greeting != \"Hello\""); } if (greeting.substring(0,3) == "Hel"){ System.out.println("greeting.substring(0,3) == \"Hello\""); }else { System.out.println("greeting.substring(0,3) != \"Hello\""); // greeting.substring(0,3) != "Hello" }
若是虚拟机始终将相同的字符串共享,就可使用==运算符检测是否相等。但实际上只有字符串常量是共享的,而+或substring等操做产生的结果并非共享的。所以,千万不要使用==运算符测试字符串的相等性,以避免在程序中出现糟糕的bug。
3.6.5 空串与Null串
空串""是长度为0的字符串,能够调用如下代码检查一个字符串是否为空:
String str = ""; if (str.length() == 0 && str.equals("")){ System.out.println("str is \"\""); }
固然 str.length() == 0 或 str.equals("") 均可以检验一个字符串是否为空。
空串是一个Java对象,有本身的串长度(0)和内容(空)。不过,String变量还能够存放一个特殊的值,名为null,这表示目前没有任何对象与该变量关联。
有时要检查一个字符串既不是null也不为空串,这种状况下要使用如下条件,注意检查的前后顺序:
if (str != null && str.length() != 0)
3.66 码点与代码单元
Java字符串由char值序列组成。char数据类型是一个采用UTF-16编码表示的Unicode码点的代码单元。大多数经常使用Unicode字符使用一个代码单元就能够表示,而辅助字符须要一对代码单元表示。
length方法将返回采用UTF-16编码表示的给定字符串所须要的代码单元数量例如:
String greeting = "Hello"; int n = greeting.length(); // n is 5
要想获得实际的长度,即码点数量,能够调用:
String greeting = "Hello"; int cpCount = greeting.codePointCount(0, greeting.length()); System.out.println("cpCount is "+ cpCount); // cpCount is 5
调用s.charAt(n)将返回位置n的代码单元, n 介于0 ~ s.length()-1 之间。
3.7.2 printf
3.7.3 文件输入与输出
文件读取:
Scanner in = new Scanner(Paths.get("myfile.txt"),"UTF-8");
文件写入:
PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");
能够用下面的调用方式找到路径的位置:
System.getProperty("user.dir")
3.8.3 循环
程序清单3-3 Retirement/Retirement.Java
while(){}
public class Retirement { public static void main(String[] args) { // read inputs Scanner in = new Scanner(System.in); System.out.print("How much money do you need to retire? "); double goal = in.nextDouble(); System.out.print("How much money will you contribute every year? "); double payment = in.nextDouble(); System.out.print("Interest rate in %: "); double interestRate = in.nextDouble(); double balance = 0; int years = 0; // update account balance while goal isn't reached while (balance < goal) { // add this year's payment and interest balance += payment; double interest = balance * interestRate / 100; balance += interest; years++; } System.out.println("You can retire in " + years + " years"); } }
do{......}while(boolean)
public class Retirement2 { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("How much money will you contribute every year? "); double payment = in.nextDouble(); System.out.print("Interest rate is %: "); double interestRate = in.nextDouble(); double balance = 0; int year = 0; String input; // update account balance while user isn't ready to retire do { // add this year's payment and interest balance += payment; double interest = balance * interestRate / 100; balance += interest; year++; // print current balance System.out.printf("After year %d, your balance is %,.2f%n", year, balance); // ask if ready to retire and get input System.out.println("Reday to retire? (Y/N) "); input = in.next(); } while (input.equals("N")); } }
3.8.4 肯定循环
do/while
for
for语句是while循环的一种简化形式。
for (int i = 10; i > 0; i--){ System.out.println("Counting down for... " + i); }
// 可重写为: int i = 10; while (i > 0){ System.out.println("Counting down while ... " + i); i--; }
程序清单3-5 LotteryOdds/LotteryOdds.java
public class LotteryOdds { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("How many numbers do you need to draw? "); int k = in.nextInt(); System.out.println("What is the highest number you can draw? "); int n = in.nextInt(); /** * compute binomial coefficient n*(n-1)*(n-2)*...*(n-k+1)/(1*2*3*...*k) */ int lotterOdds = 1; for (int i = 1; i <= k; i++){ lotterOdds = lotterOdds * (n - i + 1) / i; } System.out.println("Your odds are 1 in " + lotterOdds + ". Good luck!"); } }