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] ", f); System.out.printf("[%5.3f] ", 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 ", "abcde","abcde",f); forma2.format("%2$-5.2s %1$2s ", "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==》十六进制散列码