开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
异常 Exception
java中所有的异常最终都继承自java.lang.Throwable
1.检查异常(Checked Excecption)
- 这类异常一般难避免,编译器会进行检查(若开发者未处理这类异常,编译器会报错。即受编译器检查的异常)
- 哪些异常是检查型异常?(除Error、RuntimeException以外的异常,即直接继承Exception的异常)
2.非检查异常(Unchecked Excecption)
- 这类异常一般可避免,编译器不会进行检查(若开发者未处理这类异常,编译器不报错)
- 哪些异常是检查型异常?(Error、RuntimeException)
3.常见检查型异常
// java.io.FileNotFoundException 文件不存在
FileOutputStream fos = new FileOutputStream("F:/123.txt");
// java.lang.InterruptedException
Thread.sleep(1000);
// java.lang.ClassNotFoundException,类不存在
Class cls = Class.forName("Dog");
// java.lang.IllegalAccessException,无权限访问构造方法
// java.lang.InstantiationException,没无参构造方法
Dog dog = (Dog)cls.newInstance();
4.常见非检查型异常 - Error
// 内存不够
for(int i = 0; i < 200; i++){
// java.lang.OutOfMemoryError,内存不够
long[] arr = new long[10_0000_0000];
}
// 栈溢出
public static void test(){
test();
}
public static void main(String[] args){
// java.lang.StackOverflowError,栈内存溢出
test();
}
5.常见非检查型异常 - RuntimeException
// java.lang.NullPointerException,空指针异常
StringBuilder sb = null;
sb.append("abc");
// java.lang.NumberFormatException,数字的格式不对
Integer i = new Integer("abc");
// java.lang.ArrayIndexOutOfBoundsException,数组索引越界
int[] arr = {11, 22, 33};
arr[4] = 44;
// java.lang.ClassCastException,类型不匹配
Object obj = "123.4";
Double d = (Double)obj; // 123.4无法强转成Double类型
6.异常处理
不管程序抛出的是检查型异常,还是非检查型异常,只要程序员未主动处理,都会导致程序停止运行。
处理异常有两种方式:(都可用来处理 检查/非检查型异常)
try-cath捕获异常
try{
// 代码1
// 代码2(这段代码可能会抛出异常)
// 代码3
}catch (异常A e){
// 当抛出【异常A】类型的异常,会进入这个代码块
}catch (异常B e){
// 当未抛出【异常A】类型
// 但抛出【异常B】类型的异常,会进入这个代码块
}catch (异常C e){
// 当未抛出【异常A】、【异常B】类型
// 但抛出【异常C】类型的异常,会进入这个代码块
}finally {
// 不管有没有捕获到异常,这里都会执行
// 一般用来释放资源的操作(关闭数据库链接等)
}
// 1.若在执行try或catch时,JVM退出或当前线程被中断、杀死。fianlly可能不会执行。
// 2.若try或catch中使用了return、break、continue等 提前结束了语句。
// finally会在return、break、continue之前执行。
//finally举例
PrintWriter out = null;
try{
out = new PrintWriter("F:/abc.txt");
out.print("ABCDE");
}catch (FileNotFoundException e){
e.printStackTrace();
}finally {
if(out != null){
out.close();
}
}
// java7开始 单个catch可捕获多种类型的异常
// 若并列的几个异常类型之间存在父子关系,保留父类型即可
// 这里的变量e 是隐式final的
//(因为e的类型不确定,非final的话,会出现赋值错误的情况)
try{
}catch(异常A | 异常B | 异常C e){
// 当抛出 A 或B 或C类型的异常,会进入这个代码块
}
// 下列代码输出结果是什么?(1,2,4,5,6)
public static void main(String[] args){
System.out.println(1);
try{
System.out.println(2);
Integer it = new Integer("abc");
System.out.println(3);
}catch (NumberFormatException e){
e.printStackTrace();
System.out.println(4);
}finally {
System.out.println(5);
}
System.out.println(6);
}
throws:将异常抛给上层方法
/*
1.当父类中某个方法无throws异常:子类的重写方法也不能throws异常。
2.当父类中某个方法有throws异常,子类的重写方法可以:
1.不throws异常
2.throws跟父类一样的异常
3.throws父类异常的子异常
*/
public class Persion {
public void test1() {}
public void test2() throws IOException {}
public void test3() throws IOException {}
public void test4() throws IOException {}
}
public class Student extends Persion {
@Override
public void test1() {}
@Override
public void test2() {}
@Override
public void test3() throws IOException {}
@Override
public void test4() throws FileNotFoundException {}
}
- throw:抛出新建的异常
public class Persion {
private int age;
// throws Exception 是为了告诉外界此方法可能会产生异常
public void setAge(int age) throws Exception {
if(age <= 0){
throw new Exception("age必须大于0");
}else {
this.age = age;
}
}
}
throw 和 throws 的区别?
- throws是用来声明一个方法可能抛出的所有异常信息,
- throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。
- throw则是指抛出的一个具体的异常类型。
7.自定义异常
// 自定义一个检查age的异常类
public class WrongAgeException extends RuntimeException {
public WrongAgeException(int age) {
super("wrong age: " + age + "age不能小于0");
}
}
// 调用
public void setAge(int age){
if(age <= 0){
throw new WrongAgeException(age);
}else {
this.age = age;
}
}
8.使用异常的好处
- 将错误处理代码与普通代码区分开
try{
// 正常的逻辑代码
}catch(){
// 错误处理代码
}
- 能将错误信息传播到调用堆栈中
- 能对错误类型进行区分和分组
9.编写一个断言类
// 假设自己写了一个算法,如何测试算法的正确性
public static int sum(int a, int b){
return a + b;
}
// 编写一个断言类
public class Asserts {
public static void test(boolean flag){
if(flag == true){
return;
}
// falg == false 抛出非检查型异常
throw new IllegalArgumentException("条件不成立");
}
}
// 调用断言类 来测试算法
public static void main(String[] args) {
// 这里可以批量写大量测试语句 来看执行结果
// 从而可知哪些数据存在问题
Asserts.test(sum(10, 20) == 30);
Asserts.test(sum(1, 20) == 21);
}
10.常见异常
| 异常 | 描述 |
|---|---|
NullPointerException | 空指针异常 |
SQLException | 提供关于数据库访问错误或其他错误信息的异常 |
IndexOutOfBoundsException | 数组下标越界 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常 |
FileNotFoundException | 当试图打开指定路径名表示的文件失败时,抛出此异常 |
IOException | 当发生某种I/O异常时,抛出此异常。此类是失败或中断的I/O操作生成的异常的通用类 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数 |
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常 |
NoSuchMethodException | 无法找到某一特定方法时,抛出该异常 |
SecurityException | 由安全管理器抛出的异常,指示存在安全风险 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常 |
RuntimeExceptionRuntimeException | 是那些可能在Java虚拟机正常运行期间抛出的异常的超类 |