《Thinking in Java》学习笔记(五)

1. Java异常补充

  a.使用try/catch捕获了异常之后,catch之后的代码是会正常运行的,认为即使进行了异常捕获,出现了异常就不往下执行,这是很多新手会犯的错误。

public class ExceptionTest {

    public static void main(String [ ] args) {
try{
throw new RuntimeException();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("still operate here!");
} }

  将输出:

  java.lang.RuntimeException
  still operate here!
     at exception.ExceptionTest.main(ExceptionTest.java:20)

  b.捕获多个异常时,一旦匹配将退出,因此捕获Exception时应该放到最后,否则连编译都通不过

public class ExceptionTest {

    public static void main(String [ ] args) {
try{
throw new RuntimeException();
}catch(Exception e){
e.printStackTrace();
}catch(RuntimeException e){
e.printStackTrace();
}
System.out.println("still operate here!");
} }  

  在catch(RuntimeException e){这一行会报错:

    unreachable block for RuntimeException.It is handled by the catch block for Exception。

  正确的顺序是先捕获RuntimeException,再尝试捕获Exception。

  c.告诉调用方法的调用者可能会抛出异常,可以在方法后面加上throws,然后在方法中thorw。这样别人再调用该方法时就必须处理该异常或者抛出该异常。

  下面是BufferedInputStream中的例子:

private byte[] getBufIfOpen() throws IOException {
byte[] buffer = buf;
if (buffer == null)
throw new IOException("Stream closed");
return buffer;
}

  需要注意的是,方法后面加上throws,方法内部不一定非要thorw。

  下面是InputStream中的例子:

 public int available() throws IOException {
return 0;
}

  d.捕获异常时,子类的异常也可以被父类的try/catch所捕获。

public class ExceptionTest {

    public static void main(String [ ] args) {
try{
throw new SubException();
}catch(MyException e){
e.printStackTrace();
}
} } class MyException extends Exception{} class SubException extends MyException{}  

  将会输出:

exception.SubException
   at exception.ExceptionTest.main(ExceptionTest.java:15)

  注意只能先捕获子类异常,再捕获父类异常。

  e.将检查时异常变为运行时异常

  如果调用的方法抛出了一个异常,我们在调用时就需要进行处理,如果不知道怎么处理,又不想catch之后什么都不做(这样是很不好的),可以向上抛出异常或者抛出运行时异常。  

public class ExceptionTest {

    public static void main(String [ ] args) throws IOException{
try{
InputStream is = new FileInputStream(new File("abc.txt"));
is.read();
}catch(IOException e){
//e.printStackTrace();
//throw e; //自己无法处理时向上抛出
throw new RuntimeException(e);
}
} }

  注意,如果方法内throw,则需要再次捕获或者方法上throws。

 2.格式化输出

  Java中的格式化输出需要使用到Formatter类,可以按照格式输出希望得到的结果。 

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Formatter; public class SimpleFormat { public static void main(String [ ] args) throws FileNotFoundException {
float f = 5.54312f; System.out.format("[%5.3f]\n", f);
System.out.printf("[%5.3f]\n", f); Formatter forma = new Formatter();
System.out.println(forma.format("%-3s %3s %5.3f", "abcde","abcde",f));
//System.out.println(forma.format("%2$-5.2s %1$2s", "123", "456")); error Formatter forma2 = new Formatter(System.out);
forma2.format("%-3s %3s %5.3f\n", "abcde","abcde",f);
forma2.format("%2$-5.2s %1$2s\n", "123", "456"); Formatter forma3 = new Formatter(new File("abc.txt"));
forma3.format("%-3s %3s %5.3f", "abcde","abcde",f);
forma3.flush();
forma3.close();
} }

   输出为:

[5.543]
[5.543]
abcde abcde 5.543
abcde abcde 5.543
45    123

  从上面的代码可以看到,可以直接使用System.out.format或者System.out.printf直接在输出中完成格式化。

  更多地,我们使用Formatter类来完成格式化的工作,Formatter的构造函数可以是无参的,可以是一个PrintStream(例子中的System.out),或者File,或者是OutputStream。

  这里还需要注意的是格式化的参数,例如%5.3f表示,格式化的结果为:总长度为5,小数部分长度为3.

  %2$-5.2s, 2$表示取得是第二个参数,-5.2s表示左对齐,长度最小为5位,不足补空格,有效值为2位。

  还有常用的格式类就是SimpleDateFormat,常用来格式化时间、日期或者做一些时间、日期的计算。

  还需要注意,%5.3f中的f不是对应java的float类型,这里的f指的是小数,对应于java的float和double。里面例子中的float f = 5.54312f;可以用double f = 5.54312d;代替。

  d==》整数  f==》浮点型  s==》字符串   c==》unicode  b==》boolean  e==》浮点型 x==》十六进制整数  h==》十六进制散列码

上一篇:Java 从 Map 到 HashMap 的一步步实现


下一篇:Java中Map接口的遍历