Java雷坑整理(2)"/>
Java雷坑整理(2)
PIT 06:域和流
下面的代码是一个文件拷贝的方法,设计的是即便抛出异常也会关闭流:
public static void pit06(String src,String dest) throws IOException {InputStream in = null;OutputStream out = null;try {in = new FileInputStream(src);out = new FileOutputStream(dest);byte[] buf = new byte[1024];int n;while((n=in.read(buf))>0) {out.write(buf,0,n);}} catch(Exception e) {e.printStackTrace();} finally {if(in!=null) {in.close();}if(out!=null) {out.close();}}}
这个程序看起来已经面面俱到了,不过可惜的是,finally
块里,当close
方法异常时,还是会无法关闭流,即close
的调用可能会导致finally
代码块异常结束,解决的方法也很简单,把close
的调用放到嵌套在try catch
块里即可:
} finally {try {if(in!=null) {in.close();}} catch(Exception ex) {ex.printStackTrace();}try {if(out!=null) {out.close();}} catch(Exception ex) {ex.printStackTrace();}}
PIT 07:有毒的括号
众所周知,Integer.MAX_VALUE
的值是2147483647
,Integer.MIN_VALUE
的值是-2147483648
,但如果这样写:
public static void pit07() {int i = -(2147483648);}
这里编译肯定会报错,程序会先计算括号里的内容,报超出int范围,所以你的业务代码里加括号的内容一定要捋清楚,防止踩坑。
PIT 08:三元表达式
你会怎么理解这段代码呢:
public static void pit08() {char x = 'X';int i = 0;System.out.println(true?x:0);System.out.println(true?x:i);
}
毫无疑问这里两次输出的都是变量x
的值,但并不是X
X
,而是X
88
。
这里可以从条件表达式结果类型的规则来找原因,对于表达式的第二个和第三个操作数的类型判断,其中有这么三条规则:
1.如果这两个操作数具有相同的类型,那么它就是条件表达式的类型;
2.如果一个操作数的类型是T(byte、short、char),而另一个操作数是一个int类型的常量表达式,它的值可以用T来表示,那么条件表达式的类型就是T;
3. 否则,将对操作数的类型进行二进制数字提升,而条件表达式的类型就是提升后的类型。
第一个输出语句满足第二条,所以输出X
,第二个输出语句满足第三条,对char
和int
进行二进制数字提升之后,就是int
,输出X
的Unicode码88
。
PIT 09:转义字符与Unicode
当转义字符遇到Unicode,简直不要再崩溃:
/*** from D:\Test\units\Test01.java*/public static void pit09() {System.out.println("Hello Word!");}
很简单的一个输出语句,却连编译都通不过,问题就出在注释里,\u是Unicode码的开始,即便它在注释里,编译器依旧不会放过它,可想而知,代码里如果有类似现象,写不清楚的Unicode,该是多么崩溃。
PIT 10:i==-i
正常来说,满足i==-i
的整数数值只有0
,但在程序里,还有两个数,那就是Integer.MIN_VALUE
和Integer.MAX_VALUE
,这是因为-
运算符是对数值进行二进制补码运算的,即取反加一,而这两个数补码运算后,它的低32位等于它本身,虽然高位溢出了,但会被Java忽略,故而依旧满足上述表达式。如果你的程序中有该判断逻辑,那就要小心了。
精彩待续。。。
相关阅读:Java雷坑整理(1)
更多推荐
Java雷坑整理(2)
发布评论