表达式之谜
1、取余时要注意操作数的和结果的符号,操作数是负数时,结果并不显而易见。
2、对精度要求更高的时候,要避免使用double和float,而使用int、long、BigDecimal。
3、在定义常量时,要考虑到是否使用默认类型,比如final long MICROS_PER_DAY =24 * 60 * 60 * 1000 * 1000,那么这个运算不会达到表达式所想要得到的结果。而应该使用long作为乘积的第一个数值,final long MICROS_PER_DAY = 24L *60 * 60 * 1000 * 1000。
4、在给变量命名时不要使用易混淆的字母,如 l(L的小写)和1。
5、混合类型的计算容易产生混淆,如八进制和十六进制,在高位置为时它们是负数,而往往不容易被发现。
6、多重转型会导致精度丢失,从而出现预期外的结果。
7、java并不能通过复合的异或赋值操作符来互换内容,与c++不同的是,java的语言规范描述了:操作符的操作数是从左向右求值的,如x ^=expr,在计算expr之前提取x的值,并且将这两个值得异或结果赋给变量x,像x ^= y ^= x ^= y在java中并不能交换值,因为x得值被提取了两次,每次都在赋值操作前提取,所以达不到交换的效果。
8、?:操作符可以明显的体现出混合运算引起的混乱,其核心是三点
- (1)如果第二个和第三个操作数具有相同的类型,那么它就是条件表达式的类型。换句话说,可以通过绕过混合类型的计算来避免大麻烦。
- (2)如果一个操作数的类型是T,T表示byte、short或char,而另一个操作数是一个int类型的常量表达式,它的值可以用类型T表示,那么表达式的类型就是T。
- (3)否则,将对操作数类型进行二进制数字提升,而条件表达式的类型就是第二个和第三个操作数被提升之后的类型。
9、类型窄化的赋值是非法的,而用复合赋值表达式会进行隐式转型,如
short x = 0;
int i = 123456;
x += i; //合法
x = x + i;// 非法
字符之谜
1、注意字符拼接时得到的还是字符
'H' + 'a' 等价于 72+97
"H" + "a" 等价于 "Ha"
2、单独打印字符数组会得到它的内容,若是跟其它字符串拼接则会打印内存地址。
3、字符串拼接优先级大于比较操作符。
4、编译器在将程序解析成各种符号之前,先将Unicode转义字符转换成为它们所表示的字符。如
"a\0022.length() + \u0022b".length();
等价于
"a".length() + "b".length();
5、即使是在注释中含有病构的Unicode转义字符也会导致编译失败。如 \units \u后面跟的不是四个十六进制数,所以是病构的。
6、\u000A代表换行,如果是在一个单行注释的内容中写了这个符号会导致编译失败。
看着是:
// Note: \u000A is a Unicode representation of linefeed(LF)
实际是:
// Note:
is a Unicode representation of linefeed(LF)
这当然会编译失败。
7、可以直接用Unicode来编写程序,但这会增加阅读成本,只有在你要向程序中插入其它任何方式都无法表示的字符时,Unicode转义字符才是必需的,否则任何情况都应该避免使用它们。Unicode转义字符降低了程序的清晰度,并且增加了产生bug的可能性。
8、在使用String(byte[])构造器时,若是byte数组中的字节在缺省字符集中并非全部有效时,这个构造器的行为是不确定的。所以每当要将一个byte序列转换成一个String时,都应该明确的指定一个字符集。
9、在使用块注释符时,可能会被意外的打断。/* 后的某一个 */。
10、使用正则表达式时,注意点 . 代表的是匹配任何一个字符,需要反斜杠来转义 .代表的是所想的"."。
11、replace不同于replaceAll,前者是匹配字符串,后者是匹配正则表达式。当使用不熟悉的类库时,一定要格外小心,当你心存疑虑时,就要求助于Javadoc。
12、java可以在任何语句前放置标号,但我们需要仔细地写注释,并让它们跟上时代,取出那些已遭废弃的代码。
13、要当心栅栏柱错误,即考虑边界。并且要尽可能使用熟悉的惯用法和API,在使用不熟悉的API时,要注意仔细阅读其文档。