前两章:概述&设计环境
第3章 基本程序设计结构
3.1 概览
大小写敏感。
访问修饰符:程序其他部分对这段代码的访问级别。
类是构建所有java应用程序和applet的构建块。Java应用程序的全部内容必须放置在类中。
类命名规范:大写字母开头。多个单词首字母均大写的骆驼命名法CamelCase。
源代码的文件名必须与公共类的名字相同,并用.java作为扩展名。
Java虚拟机规范 http://docs.oracle.com/javase/specs/jvms/se7/html
Java中所有函数都属于某个类的方法,标准术语称为方法而不是函数。所以main方法也必须有个外壳类。Main方法必须是静态的。
3.2 注释
普通的// 单行注释 , /* */ 多行注释 多行注释不能嵌套。
以/**开头以 */结束可以自动生成文档的。
3.3 数据类型
强类型语言,意味着必须为每个变量声明一种类型。Java共有8个基本类型,其中有4种整形、2种浮点类型、1种用于表示Unicode编码的字符单元的字符类型char和1种用于表示真值的boolean类型。
注释:Java有一个能表示任意精度的算术包,通常称为“大数值”,但它并不是一种新的Java类型,而是一个Java对象。
3.3.1 整型
long 8 int 4 short 2 byte 1
通常使用int,更大数量用long,byte和short用于特定应用场合如底层文件处理或需要控制占用存储空间量的大数组。
Java中整型范围与运行Java代码的机器无关(C/C++有关)。
长整型:后缀L 十六进制数值:前缀0x 八进制数值:前缀0(容易混淆少用)
从Java7开始 0b前缀表示二进制数,可以为数字字面量加下划线如1_000_000表示100w,编译器会去除下划线。
3.3.2 浮点类型
double 8 float 4
精度方面double是float的两倍,有人称之为双精度数值。
大部分应用程序使用double类型,很多情况下float的精度很难满足要求。如需快速处理单精度数据或存储大量数据时可用float。
float:后缀F double:无后缀或后缀D
JDK5.0中 可用十六进制数表示浮点数,如0.125可表示为0x1.0p-3,使用p表示指数而不是e。尾数采用十六进制,指数采用十进制,指数的基数是2不是10.
浮点数计算遵循IEEE754规范。特殊浮点数值:正无穷大、负无穷大、NaN(not a number)
检查一个特定值是否等于Double.Nan 不能用 x== Double.NaN 而是 Double.isNan(x)
浮点数不适用于禁止出现舍入误差的金融计算中。可用BigDecimal类。
3.3.3 char类型
用于表示单个字符,通常用来表示字符常量。在Java中char类型用UTF-16编码描述一个代码单元。
最好不要在程序中使用char类型,除非确实需要对UTF-16代码单元进行操作。
Unicode打破了传统字符编码方法的限制:一个是对于任意给定的代码值,不同的编码方法下可能对应不同的字母;二是采用大字符集的语言其编码长度有可能不同。
编码单元可以表示为十六进制值,范围从u0000到uffff
代码点:code point是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,代码点采用十六进制书写,并加上前缀U+,Unicode的代码点可以分成17个代码级别code plane。第一个代码级别称为基本的多语言级别,代码点从U+0000到U+FFFF,其中包括了经典的Unicode代码;其余的16个附加级别,代码点从U+10000到U+10FFFF,包括一些辅助字符。
UTF-16编码采用不同长度的编码表示所有Unicode代码点。在基本的多语言级别中,每个字符用16位表示,通常被称为代码单元;而辅助字符采用一对连续的代码单元进行编码。这样构成的编码值一定落入基本的多语言级别中空闲的2048字节内,通常称为替代区域。这样设计可以从中迅速知道一个代码单元是一个字符的编码还是一个辅助字符的第一或第二部分。(有具体的编码算法)
Unicode编码转义。特殊转义 退格 制表 换行 回车 ’ ” \
3.3.4 boolean类型
false true 判断逻辑条件。整型值和布尔值之间不可相互转换。
C++中数值或指针可替代boolean值,0相当于false,非0相当于true,Java中不可以。
3.4 变量
Java中每个变量属于一种类型。声明变量时,类型+变量名;
变量名必须以字母开头、并且由字母或数字组成。字母包括常规的a~z A~Z _ $ 等还包括在某种语言中代表字母的任何Unicode字符。同样数字包括0~9 以及在某种语言中代表数字的任何Unicode字符。但+ 这样的字符不可以,空格不可以。变量名所有字符都是有意义的,大小写敏感,长度无限制。
尽管$是一个合法的Java字符,但不要在自己的代码中使用这个字符。只用在Java编译器或其他工具生成的名字中。
不能将变量命名为Java保留字,可以在一行中声明多个变量,但逐行声明每一个变量可提供程序可读性。
如果要知道哪些Unicode字符属于Java中的字母,可以使用Character类的isJavaIdentifierStart和isJavaIdentifierPart方法进行检查。
取名:有时很难给变量取一个好名字,于是很多程序员将变量名命名为类型名,如Box box ;还有一些喜欢在变量前加前缀 a如 Box aBox;
3.4.1 变量初始化
变量声明后,在使用之前必须进行显示初始化。声明或初始化的位置可随意,但必须在使用之前。良好的习惯是尽可能靠近变量第一次使用的地方。
3.4.2 常量
使用final指示常量,只能被赋值一次,一旦赋值后就不能再更改了。习惯上常量名使用全大写。
使用static final设置一个类常量, 可以在一个类的多个方法中使用。类常量定义与main方法的外部。因此在同一个类的其他方法中可以使用这个常量。而且如果被声明为public,其他类的方法也可使用这个常量。
const是Java保留的关键字,但并没有使用。
3.5 运算符
+ - * / 加减乘除。 % 求余。
除法时,两个操作数都是整数结果也是整数,否则表示浮点除法。所以5/2这样想得到2.5的结果必须写成 5.0/2 或 5/2.0 或 5.0/2.0
整数被0除产生一个异常,浮点数被0出将会得到无穷大或NaN结果。
简化的二元运算符 如x+=4; 等价于 x = x+4; 通常将运算符放在赋值号的左侧,如 *= 或%=
浮点数的跨平台运算,很难保证结果的同一性。在默认情况下,虚拟机设计者允许将中间结果采用扩展的精度,同时对于使用strictfp关键字标记的方法必须使用严格的浮点计算来产生理想的结果。如果对一个类标记为strictfp,这个类中所有方法都要使用严格的浮点计算。
实际的计算方式取决于Intel处理器,默认情况下,中间结果允许使用扩展指数,不允许使用扩展的尾数。因此两种方式的区别仅在于采用默认的方式不会产生溢出,而采用严格的计算可能有产生溢出。
大多数程序来说,浮点溢出不属于大问题。
3.5.1 自增自减
n++与++n 首先这种运算符只能应用于变量,常量无法增加或减少。前缀先变化后使用,后缀先使用后变化。
建议不要在其他表达式的内部使用++ , 这样编写的代码容易令人困惑并产生烦人的bug。
3.5.2 关系运算符与boolean运算符
== 是否相等 != 是否不相等 其他 <= < > >=
&& 逻辑与 || 逻辑或 ! 逻辑非
&&与|| 采用 短路 方式求值,如果第一个操作数可确定第二个就不必计算了。
三元操作符 ?: 与C++C#一样,满足条件返回?:之间的表达式 否则返回:之后的表达式 x<y?x:y 返回小的
3.5.3 位运算符
& 与 | 或 ^ 异或 ~ 非 << >> 移位操作 >>>用0填充高位 没有<<<运算符
在处理整型数值时,可以直接对组成整型数值的各个位进行操作。意味着可以使用屏蔽技术获得整数中的各个位。
如 int i = (n & 0b1000) / 0b1000; 如果二进制表示的n右数第4位为1,那么i=1,否则i=0;
通过运用2的幂次方的&运算可以将其他位屏蔽。
&和|运算符应用于布尔值,得到的结果也是布尔值,与&&与||很像,但不按短路方式计算。
3.5.4 数学函数与常量
Math类包含了一些数学函数。平方根、次幂、三角函数、指数函数及其反函数,常量π和e
导入包 import static java.lang.Math.*; 之后,可直接使用方法及常量而不用加 Math.
Math类为了达到最快性能,所有方法使用计算机浮点单元中的例程。如果得到一个完全可预测的结果比运行速度更重要的话应使用 StrictMath类。
3.5.5 数值类型之间转换
无丢失情况:整型按字节由少到多;char转int;int转double;
丢失情况:int转float;long转float;long转double;
两个数值进行二元操作时,先要将两个操作数转换为同一种类型,然后再进行计算:
有一个double,另一个会转换成double
否则,如果其中一个是float,另一个会转换为float
否则,如果其中一个是long,另一个会转换为long
否则,都被转为int。
3.5.6 强制类型转化
有时会进行一些丢失信息的强制类型转换。 (类型)变量
对浮点数强制转换int直接截断小数部分,如果四舍五入则需要Math.round方法。
将一个数值从一种类型强制转换为另一种类型,而又超出了目标类型的表示范围,结果就会截断成一个完全不同的值。
不要在boolean类型与任何数值类型直接进行强制转换,可以防止发生错误。如果真的需要转换为数值,可使用条件表达式 b?1:0 这样
3.5.7 括号与运算符级别
优先级表,如果不使用圆括号,就按照运算符优先级次序进行计算,同一级别按照结合性顺序计算。
优先级 |
运算符 |
结合性 |
1 |
[].()(方法调用) |
→ |
2 |
! ~ ++ -- +(一元) –(一元) ()(强制类型转换) new |
← |
3 |
* / % (二元) |
→ |
4 |
+ - (二元) |
→ |
5 |
<< >> >>> |
→ |
6 |
< <= >= > instanceof |
→ |
7 |
== != |
→ |
8 |
& |
→ |
9 |
^ |
→ |
10 |
| |
→ |
11 |
&& |
→ |
12 |
|| |
→ |
13 |
?: |
← |
14 |
= += -= *= /= %= &= |= ^= <<= >>= >>>= |
← |
3.5.8 枚举类型
枚举类型包含有限个命名的值,
例如 enum Size{SMALL,MEDIUM,LARGE,EXTRA_LARGE}; Size s= Size.MEDIUM;
这样Size类型的变量只能存储这个类型声明中给定的某个枚举值或null值。
3.6 字符串
从概念上讲,Java字符串就是Unicode字符序列。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,叫做String。每个用双引号括起来的字符串都是String类的一个实例。
3.6.1 不可变字符串
String类没有提供用于修改字符串的方法,即不能修改字符串中的字符,所以在Java文档中将String类对象称为不可变字符串,如同数字3永远是3,给字符串变量赋新值也只是让它引用了另外一个字符串,并没有改变原来的字符串,当原来的字符串不再使用后,Java会自动进行垃圾回收。
记:因为String不是基本数据类型,而是一个类。
3.6.2 代码点和代码单元
Java字符串由char序列组成,而char数据类型是一个采用UTF-16编码表示的Unicode代码点的代码单元。大多数的常用Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表。
Java中的代码单元和代码点从0开始计数。
length方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。
codePointCount(0,str)方法可以得到实际的代码点长度。
charAt(n) 返回位置n的代码单元
offsetByCodePoints(0,i) codePointAt(i) 第i个代码点
3.6.3 操作和特殊值
子串: substring
拼接: 使用 + 号拼接字符串 ,+ 会将非字符串值转换成字符串。 如把一个数字转为字符串,则可 ""+i
相等: equals equalsIgnoreCase 一定不能用==判断,这样只会比较内存地址是否相等。
空串: "" 是长度为0的字符串,是Java对象 通过str.length()==0 或str.equals("")判断
null: String变量还可存放null,表示目前没有任何对象与该变量关联。 str==null
检测: 同时检测空串和null时 if(str !=null && str.length()!=0) 顺序不能变,基于短路方式判断。
其他API
3.6.4 构建字符串
有时需要由较短的字符串构建字符串,采用字符串连接的方式效率较低,每次连接字符串都会构建一个新的String对象,此时可使用StringBuilder类。
StringBuilder builder = new StringBuilder();
builder.append("123"); builder.toString();
关于类的使用说明可参考API,不再详述
3.7 输入输出
控制台应用的输入输出
3.8 控制流程
块作用域:花括号括起来的部分。在作用域内的变量不可重名。 可以嵌套
仅列出示例语法
3.8.1 条件语句
if(...){...}
if(...){...} else{...}
if(...){...} else if(...){...} ... else{...}
可以嵌套。
3.8.2 循环语句
while(...){...}
do{...} while(...)
for(int i=1;i<-10;i++){...}
for(int i : array){...} foreach循环,针对数组等
设计者认为应当使用foreach in 这样的关键字,但这种循环是后来添加去的,并且没人打算废除已有的同名方法或变量的旧代码,所以使用了现在的语法
C#中的 foreach(int i in array){...}就是上述关键字的表现。
3.8.3 多重选择
switch(choice){case 1:... break; case 2:... break; default:... break;}
3.8.4 中断
Java设计者保留了goto关键字,但并未使用。
break:常规不带标签的可直接中断距离break最近的外层循环。
带标签的break语句,可用于跳出多重循环,
label: 循环体 ,当跳出时使用break label;即可
事实上label可用于任何语句块。
continue:结束当前循环进入下一次循环。带标签的continue语句将跳到与标签匹配的循环首部。
3.9 大数值
基本的整数和浮点数精度不足够时,可使用java.math包中的两个类:BigInteger 和BigDecimal,可处理包含任意你孤独数字序列的数值。前者任意精度的整数,后者任意精度的浮点数。
不能使用基本算术运算符,要使用类中的方法来计算如add代替+
3.10 数组
int[] array = new int[100];
元素个数:array.length ,数组创建后就不能改变大小了。数组长度可以为0,与null不同。
数字数组所有元素初始化为0,boolean为false,对象类为null
Arrays.toString(array);返回array数组的所有元素,放在括号内用逗号隔开,如 [2,3,4]
C++中 int array[] 中括号的位置不同。C#中相同。
3.10.1 数组初始化及匿名数组
创建一个数组并初始化
int[] array={2,3,4,5,6};
new int[] {2,3,4,5,6}; 匿名数组
3.10.2 数组拷贝
若用赋值使一个数组赋值为另一个,则是把左边的数组指向了右边的数组地址,两者引用的是同一块内容。
若要保持两个的独立性只是使值相同,则使用copyTo方法。
其他:多元数组,不规则数组。