java异常体系图
- Error是程序无法处理的错误,它是由JVM产生和抛出的,比如OutOfMemoryError、ThreadDeath等
- Exception是程序本身可以处理的异常,这种异常分两大类运行时异常和非运行时异常.运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等.
try catch用法
- 一个catch块可以捕获多种类型的异常,多种异常类型之间用竖线隔开,此时变量有隐式的final修饰;
- 捕获异常时要先捕获小异常再捕获大异常,否则会出现编译错误。
- try catch可以嵌套,且深度没有限制,但是层次太深没必要且会导致程序可读性差。
try {
//代码
}catch(ArrayIndexOutOfBoundsException | NumberFormatException e){//捕获多个异常,小异常
e.printStackTrace();
}catch(NullPointerException e) {//捕获一个异常
e.printStackTrace();
e=new XXXException();//代码错误,多异常时e被finally修饰
}catch(Exception e) {//捕获一个异常,大异常,小异常
e.printStackTrace();
}
finally回收资源
finally回收资源:数据库连接 网络连接,磁盘文件等,物理资源必须显示回收,垃圾回收机制只能回收堆内存中对象所占用的内存。
/**
* 将java源文件复制到相应的bin目录中
* @param clz
*/
private static void readJavaToBinFinally(Class<?> clz) {
BufferedReader br = null;
PrintStream ps = null;
String path = System.getProperty("user.dir");
String pName = clz.getPackage().getName();
String javaName=clz.getSimpleName()+".java";
try {
br = new BufferedReader(new FileReader(
path + File.separator + "src" + File.separator + pName + File.separator + javaName));
String dirPath = clz.getResource("").toString();
if (dirPath.startsWith("file")) {
dirPath = dirPath.substring(6);
}
dirPath = dirPath.replace("/", File.separator);
String pp = dirPath + javaName;
ps = new PrintStream(new FileOutputStream(pp));
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
ps.println(sCurrentLine);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
ps.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
自动回收资源的try语句(java7)
/**
* 自动回收资源的try语句 不需要finally语句了
* @param clz
*/
private static void readJavaToBin(Class<?> clz) {
String path = System.getProperty("user.dir");
String pName = clz.getPackage().getName();
String dirPath = clz.getResource("").toString();
String javaName=clz.getSimpleName()+".java";
if (dirPath.startsWith("file")) {
dirPath = dirPath.substring(6);
}
dirPath = dirPath.replace("/", File.separator);
String pp = dirPath + javaName;
try (BufferedReader br = new BufferedReader(new FileReader(
path + File.separator + "src" + File.separator + pName + File.separator + javaName));
PrintStream ps = new PrintStream(new FileOutputStream(pp));)
{
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
ps.println(sCurrentLine);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
catch和finally语句中的return语句等导致方法终止的语句
- 在catch块里面的return语句,会在finally语句执行完毕之后再执行;
- 如果在catch块中执行System.exit(1)语句退出虚拟机,则finally语句就不再会执行;
- 不要在finally块里面执行return或throw等导致方法终止的语句,因为执行这些语句后,改方法就终止了,try或catch块里面的语句就不会再执行了;
throws声明抛出异常
- 当前方法不知道如何处理该异常,其应该由上一级调用者处理,使用throws声明抛出异常;如果main方法也不知如何处理则交给JVM处理:打印异常的跟踪栈信息,中止程序运行.
- throws声明只能在方法签名中使用
private static void eChecked() throws FileNotFoundException, IOException {
//声明抛出Checked异常
//可以抛出一个,也可以抛出多个
}
private static void eRuntime() throws IndexOutOfBoundsException, NumberFormatException, ArithmeticException {
//声明抛出Runtime异常
//可以抛出一个,也可以抛出多个
}
throw语句抛出异常
- 程序自行抛出异常
- 这种异常是与业务需求不符而产生的异常
- 每次只能抛出一个异常实例
//抛出Runtime异常
private static void throwRuntime(String str) {
if(str.length()>2) {
throw new RuntimeException("字符串长度不能大于2");
}else {
System.out.println("str="+str);
}
}
//抛出Checked异常
private static void throwException(String str) throws Exception {
if(str.length()>2) {
throw new Exception("字符串长度不能大于2");
}else {
System.out.println("str="+str);
}
}
自定义异常 (见throw语句抛出异常)
public class AuctionException extends Exception {
private static final long serialVersionUID = 1926917047098764507L;
public AuctionException(String msg) {
super(msg);
}
}
//catch 和 throw联合处理异常
private static void catchThrow() throws AuctionException {
try {
int a=Integer.parseInt("异常");
System.out.println(a);
} catch (NumberFormatException e) {
//程序对异常做了部分处理,打印跟踪栈信息
e.printStackTrace();
//程序对异常做了部分处理,将异常抛出,由方法的调用者再次进行处理
throw new AuctionException("非数字型的字符串");
} catch (Exception e) {
e.printStackTrace();
}
}
异常跟踪栈
- 异常信息
//e.getLocalizedMessage() ,e.getMessage() 结果一样,最终调用的方法一样
System.out.println("getLocalizedMessage="+e.getLocalizedMessage());
System.out.println("getMessage="+e.getMessage());
//clas name +getLocalizedMessage
System.out.println("toString="+e.toString());
2. StackTraceElement
StackTraceElement[] ss=e.getStackTrace();
for(int i=0;i<ss.length;i++) {
StackTraceElement si=ss[i];
System.out.println("getMethodName="+si.getMethodName());
System.out.println("getClassName="+si.getClassName());
System.out.println("getFileName="+si.getFileName());
System.out.println("getLineNumber="+si.getLineNumber());
System.out.println("isNativeMethod="+si.isNativeMethod());
System.out.println("isNativeMethod="+si.toString());
}
3. 异常跟踪栈信息打印,保存
e.printStackTrace();----->调用的是:e.printStackTrace(PrintStream s); PrintStream s=System.err;
e.printStackTrace(PrintStream s);
e.printStackTrace(PrintStreamOrWriter s);
//打印到System.err
e.printStackTrace();
//保存到文件 方法1
PrintStream printStream=new PrintStream(new File("e://123.txt"));
e.printStackTrace(printStream);
//保存到文件 方法2
PrintWriter pw = new PrintWriter(new File("e://123456.txt"));
e.printStackTrace(pw);
pw.close();