异常概述
程序运行过程中出现的不正常的严重错误称异常,会中断程序运行,对异常的处理称异常处理,是程序设计的重难点之一
异常分类
Throwable
有两个直接子类,Error类和Exception类。
有两个常用方法public String getMessage():获取异常信息
public void printStackTrace():输出异常堆栈中的异常信息
Error
合理的程序执行过程中发生异常,在控制台通知用户并终止程序
如,
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Object> vector = new ArrayList<Object>(10);
for (int i = 1; i < 999999000; i++) {
Object obj = new Object();
vector.add(obj);
}
}
}
Exception
运行时异常/RuntimeException
可通过编译
RuntimeException异常类及其下面的子类均为运行时异常。
非运行时异常,检查时异常/CheckedException
编译不可通过
Exception异常类及其子类(除去RuntimeException异常类及其子类)都是检查时异常。
两个构造方法(了解)
public Exception():无参构造方法;
public Exception(String message):可以指定详细异常信息的有参构造方法;
异常处理
通过try、catch、和finally关键字捕获异常
捕获异常语法结构
try{}块抛出异常
catch{}块捕获异常
finally{}一般用于释放资源
try {
//可能抛出异常的语句块
} catch(SomeException1 e) {
//捕获到SomeException1类型的异常时执行的语句块
} catch(SomeException2 e) {
//捕获到SomeException2类型的异常时执行的语句块
} finally {
//无论是否发生异常都会执行的代码块
}
需要注意的
(1)try{}块是必需的,catch和finally至少出现一个
(2)try{}中包含的是检查时异常,且在没有通过throws抛出该异常类的情况下,try与catch是绑定的,要一起使用,去掉try{}中代码时catch也要去掉,下图便是这种情况
try {
Class.forName("java.lang.Object");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
多重catch
try语句块中代码可能会有多种类型的异常,然而只会执行第一个与异常类型匹配的catch语句,这点像if{}else if{}else if{}语句,其后catch语句被忽略
因此在捕获异常时,应先紧着子类,即从小到大的顺序,如下段代码:
ArrayIndexOutOfBoundsException异常类是RuntimeException的子类,
RuntimeException异常类是Exception的子类
public class TestException {
public static void main(String[] args) {
try {
String[] nameArray = { "小王", "小李", "小高" };
for (int i = 0; i < 4; i++) {
System.out.println(nameArray[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {// 捕获下标越界异常
System.out.println("发生数组下标越界异常,成功捕获!");
} catch (RuntimeException e) {// 捕获运行时异常
System.out.println("发生运行时异常,成功捕获!");
} catch (Exception e) {// 捕获所有异常
System.out.println("发生异常,成功捕获!");
}
System.out.println("显示完毕!");
}
}
finally关键字
无论是否异常,都将执行finally块中语句。即使return也不例外。
仅当程序调用System.exit(1)才不执行该块。
public class TestException {
public static void main(String[] args) {
try {
String[] nameArray = { "小王", "小李", "小高" };
for (int i = 0; i < 4; i++) {
System.out.println(nameArray[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数据下标越界,请修改程序!");
System.out.println("调用异常对象的getMessage()方法:");
System.out.println(e.getMessage());
System.out.println("调用异常对象的printStackTrace()方法:");
e.printStackTrace();
return;// finally语句块仍然执行
// System.exit(1);//直接退出JVM,finally语句块不再执行
} finally {
System.out.println("显示完毕!");
}
System.out.println("显示完毕!");
}
}
代码总结
import org.apache.log4j.Logger;
public class Test {
static Logger logger=Logger.getLogger(Test.class);
public static void main(String[] args) {
// System.out.println(111);
// try {
// System.out.println(1/0);//如果程序出现异常,则同级代码不再运行。解决异常问题的办法就是用异常类中的打印异常信息的方法
// } catch (Exception e) {
// e.printStackTrace();
// }
// System.out.println(222);
// System.out.println(1/0);//运行时异常:可以不显式对异常处理,javac可编译
// try {
// Class.forName("");//检查时异常:必须显式对异常处理,javac不可编译
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
// Class.forName("java.lang.Objt");//检查时异常
// String name=null;
// System.out.println(name.length());//运行时异常
// String name=null;
// System.out.println(name.length());
// System.out.println(1/0);//这行代码可以执行吗?不可以,同级
// try {
// String name=null;
// Integer.parseInt("QQQQ");//运行时异常
// }catch(NullPointerException e) {
// System.out.println("NUll");
// }catch(ArithmeticException e) {
// System.out.println("0");
// }catch(Exception e) {
// System.out.println("other"+e);
// }//像极了if else if else if ...... else
// int i=1;
// while (true) {
// try {
// System.out.println(1 /0);
// } catch (Exception e) {
// System.out.println(i);
// e.printStackTrace();//将异常信息打印在控制台——>存入一段缓存,缓存有大小——>满了还没打印完,则会将
// //先进入缓存的异常信息清除——>导致可能发现不了全部异常问题——>log4j包将异常信息输出到一个文件中
// }
// i++;
// }
int i=1;
while (true) {
try {
System.out.println(1 /0);
} catch (Exception e) {
logger.debug(e.getMessage(), e);
}
i++;
}
//思考:将所有异常信息放在一个文件中——>文件太大——>分文件保存信息
}
}