参考java官网教程:The Java™ Tutorials java.util.logging.Logger使用详解
1. java异常处理包括try
, catch
, finally三个部分,try内是可能会产生异常的代码,例如数组访问,IO操作等等;catch是异常捕捉和处理部分;finally部分主要在于发生异常时候,用于处理异常以及清理(例如下面例子PrinterWriter流需要关闭)。
try {
} catch (ExceptionType name) {
...handler...
} catch (ExceptionType name) {
}
ExceptionType是异常类型,必须是继承自Throwable类。在handler中我们可以通过name引用异常获得相关信息,例如:
try { } catch (IndexOutOfBoundsException e) { System.err.println("IndexOutOfBoundsException: " + e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); }
2. handler不仅仅可以打印异常信息和挂起程序,还可以进行错误恢复(error recovery),让用户决定异常处理,通过chained exceptions传送异常到更高级别。
关于chained exceptions详细参考Chained Exceptions,其中涉及到打印日志和Stack Trace打印:
try{
int a[] = new int[2];
System.out.println("Access element three :" + a[1]);
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("Exception thrown :" + e);
StackTraceElement elements[] = e.getStackTrace();
for (int i = 0 , n = elements.length; i < n; i++){
/*System.out.println("elements: " + i);
System.err.println(elements[i].getFileName()+":" +
elements[i].getLineNumber() + ">>" + elements[i].getMethodName());*/
logger.log(Level.INFO, elements[i].getMethodName());
}
throw e;
}
3. finally部分始终会运行,用于善后处理,这个实例中他负责关闭PrintWriter,如果PrintWriter已经打开。
catch (IndexOutOfBoundsException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (out != null){
// No IOException, Stream open
System.out.println("PrintWriter closed!");
out.close();
}
else{
// Stream not open maybe for IOException
System.out.println("PrintWriter not open!");
}
}
想要了解更多关于finally在资源释放方面作用,请看:
try-with-resources Statement,这里我们提供一个示范
4. 综合应用请看一下例子:
try {
System.out.println("Enter try statement: ");
out = new PrintWriter(new FileWriter("OutFile.txt"));
for(int i = 0; i < SIZE; i++){
out.println("Value at:" + i + list.get(i));
}
}catch (IndexOutOfBoundsException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
out.close();
以上加粗部分新建一个PrintWriter类指向文件输出流,并且获取list数组内容输出到输出流指定文件。因为涉及到新建文件以及获取数组内容,所以需要处理IndexOutOfBoundsException(数组越界)和IOException(IO异常)。我们可以通过触发异常来进行试验:
正常运行时候,程序会建立OutFile.txt文件,并且写入信息。结果如下
Enter try statement: Access element three :0 Out of the block Process finished with exit code 0
OutFile.txt中内容如下:
Value at:0
Value at:1
Value at:2
Value at:3
4.1 我们通过预先在相关目录下建立OutFile.txt文件,并且修改权限为高于目前用户,例如"chown root OutFile.txt"将文件所有权改为root这样程序便会因为无法建立文件产生IO异常,如下:
Enter try statement: java.io.FileNotFoundException: OutFile.txt (Permission denied) at java.io.FileOutputStream.open(Native Method) at java.io.FileOutputStream.<init>(FileOutputStream.java:221) at java.io.FileOutputStream.<init>(FileOutputStream.java:110) at java.io.FileWriter.<init>(FileWriter.java:63) at oracle.ListOfNumbers.writeList(ListOfNumbers.java:28) at oracle.ListOfNumbers.main(ListOfNumbers.java:45) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
4.2 我们在通过"for(int i = 0; i < SIZE + 1; i++)"使数组越界,然后运行程序发现:
java.lang.IndexOutOfBoundsException: Index: 10, Size: 10 at java.util.ArrayList.rangeCheck(ArrayList.java:635) at java.util.ArrayList.get(ArrayList.java:411) at oracle.ListOfNumbers.writeList(ListOfNumbers.java:31) at oracle.ListOfNumbers.main(ListOfNumbers.java:45) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Access element three :0 Out of the block
附注代码:
import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.logging.*; class MyLogHandler extends Formatter{ public String format(LogRecord record){ return record.getLevel() + ":" + record.getMessage() + "\n"; } } public class ListOfNumbers{ private List<Integer> list; private static final int SIZE = 10; public ListOfNumbers(){ list = new ArrayList<Integer>(SIZE); for(int i = 0; i < SIZE; i++){ list.add(new Integer(i)); } } void writeList() { PrintWriter out = null; try { System.out.println("Enter try statement: "); out = new PrintWriter(new FileWriter("OutFile.txt")); for(int i = 0; i < SIZE; i++){ out.println("Value at:" + i + list.get(i)); } }catch (IndexOutOfBoundsException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } out.close(); } public static void main(String args[]) throws IOException{ ListOfNumbers test = new ListOfNumbers(); test.writeList(); Logger logger = Logger.getLogger("oracle"); logger.setLevel(Level.ALL); ConsoleHandler handler = new ConsoleHandler(); handler.setLevel(Level.SEVERE); logger.addHandler(handler); FileHandler fileHandler = null; try { fileHandler = new FileHandler("/users/wsy/language/java/Exception/log.txt"); } catch (IOException e) { System.err.println("Create FileHandler failed!"); e.printStackTrace(); } fileHandler.setLevel(Level.ALL); fileHandler.setFormatter(new MyLogHandler()); logger.addHandler(fileHandler); try{ int a[] = new int[2]; System.out.println("Access element three :" + a[2]); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Exception thrown :" + e); StackTraceElement elements[] = e.getStackTrace(); for (int i = 0 , n = elements.length; i < n; i++){ /*System.out.println("elements: " + i); System.err.println(elements[i].getFileName()+":" + elements[i].getLineNumber() + ">>" + elements[i].getMethodName());*/ logger.log(Level.INFO, elements[i].getMethodName()); } throw e; } System.out.println("Out of the block"); } }