Java 异常

1、Java异常

1. 异常概念

Exception ===> 例外

Java中的异常又称为例外,是指程序在运行过程中出现的例外情况。

异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.

2. Java中异常体系

异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception,平常所说的异常指java.lang.Exception

Throwable中的常用方法:

  • public void printStackTrace():打印异常的详细信息。

    包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

  • public String getMessage():获取发生异常的原因。

    提示给用户的时候,就提示错误原因。

3. 异常分类

我们所说的异常通常是指Exception,这种异常一但出现,我们需要对其进行处理。

异常分为:编译时异常运行时异常

  • 编译时异常:

  • 在编译的时候 就必须明确给出处理方案,否则编译无法通过,直接继承Exception。

  • 运行时异常:在编译的时候 不要求给出处理方案,编译能够直接通过 问题会在运行时直接体现出来,继承自RuntimeException。

4. 常见的运行时异常
异常名称异常解读备注
ArithmeticException算术异常在数学当中0不能做除数 在Java当中如果直接除以0,将会导致该异常出现
NegativeArraySizeException负数数组大小异常初始化数组的时候[],当中需要明确的给出数组元素个数, 如果指定的元素个数是负数 ,将直接触发异常
ArrayIndexOutOfBoundsException数组索引值超出边界异常数组允许使用下标索引值直接访问某个元素 ,但是下标可用范围为 (0 - length-1) ,如果指定的下标不在该范围内 ,直接导致该异常
NullPointerException空指针异常Java当中所有引用数据类型默认值为null ,这个null代表对象根本不存在, 拿它调用任何方法 ,访问任何属性 ,都会导致该异常
StringIndexOutOfBoundsException字符串索引值超出边界异常String类提供了很多通过下标索引值进行操作的方法 ,例如:charAt() 、substring() 下标索引值的可用范围 (0 - length()-1) ,如果指定的下标不在该范围内 ,直接导致该异常
NumberFormatException数字格式异常包装类提供了从字符串转换成其对应基本数据类型的方法, 例如: Integer.parseInt() Double.parseDouble() ,如果传入的内容当中包含不合法的字符, 将会直接导致该异常
ClassCastException类造型异常进行强制类型转换的时候 ,如果要转换成的类型和对象本身 没有任何关系, 将会直接导致该异常
IllegalArgumentException非法参数异常初始化ArrayList的时候, 构造方法传入的参数, 可以指定底层Object数组的大小 ,如果传入的参数小于0 将会导致该异常
IndexOutOfBoundsException索引值超出边界异常List集合是有序的 ,可以使用下标操作元素 ,例如: get(int) remove(int) set(int) 可用范围(0 - size()-1) ,如果传入的下标索引值不在范围内 ,直接导致异常
IllegalStateException非法状态异常使用迭代器的时候 ,迭代器光标指向元素的时候 ,才能使用remove() ,如果迭代器光标未指向元素 ,或者指向的元素已经被删掉了 ,还继续尝试remove() 将会导致该异常
ConcurrentModificationException并发修改异常使用迭代器遍历集合的过程当中 ,不允许对集合整体进行添加或者删除操作 ,否则将会导致该异常

import java.util.*;
public class TestRuntimeException{
	public static void main(String[] args){
		//IllegalStateException => 非法状态异常
		List<Integer> list3 = new ArrayList<>();
		Collections.addAll(list3,11,22,33);
		Iterator<Integer> car = list3.iterator();
		car.remove();

		//IndexOutOfBoundsException => 索引值超出边界异常
		List<Integer> list2 = new ArrayList<>();
		Collections.addAll(list2,11,22,33,44);
		System.out.println(list2.get(4));

		//IllegalArgumentException
		List<Integer> list1 = new ArrayList<>(-5);

		//ClassCastException => 类造型异常
		Object stu = new Student();
		Cacti cc = (Cacti)stu;

		//NumberFormatException => 数字格式异常
		String str3 = "123a";
		int num = Integer.parseInt(str3);
		System.out.println(num + 2);

		//StringIndexOutOfBoundsException => 字符串索引值超出边界异常
		String str2 = "ETOAK";
		System.out.println(str2.charAt(5));

		//NullPointerException => 空指针异常
		String str1 = null;
		System.out.println(str1.length());

		//ArrayIndexOutOfBoundsException => 数组索引值超出边界异常
		int[] data2 = new int[]{11,22,33};
		System.out.println(data2[3]);

		//NegativeArraySizeException => 负数数组大小异常
		int[] data1 = new int[-7];

		//ArithmeticException => 算术异常
		System.out.println(7 / 0);
	}
}
class Student{}//学生
class Cacti{}//仙人掌

5. 异常处理
1. 抛出异常

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。将问题标识出来,报告给调用者。关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).

抛出异常格式

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{   }  
public class Test01 {
    //学生会主席
    public static void main(String[] args)throws Exception{
        first();
    }
    //各部门部长
    public static void first()throws Exception{
        second();
    }
    //各部门干事
    public static void second()throws Exception{
        Runtime.getRuntime().exec("notepad");
    }
}
2. 捕获异常

捕获异常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类:

捕获异常格式:

try{
    可能出现异常的语句;
}catch(要捕获的异常类型1 e){
    0.隐瞒不报
    1.System.out.println(e.getMessage());
    2.e.printStackTrace();
    3.谎报  throw new SystemBusyException();
}finally{
    无论是否出现异常最终都要执行的操作
    通常是释放和关闭资源的操作
}

*: 一个try 后面可以多个catch 注意前者不能包含后者 *: JDK7.0开始允许多重catch *: finally当中永远不该出现return语句

public class Test01 {
    public static void main(String[] args){
        first();
    }
    public static void first(){
        second();
    }
    public static void second(){
        System.out.println("你能看到我吗?");
        try{
            System.out.println(7 / 0);
        }catch(Exception e){
            //String msg = e.getMessage();
            //System.out.println(msg);
            e.printStackTrace();
        }finally{
            System.out.println("== 很重要 不执行就爆炸 ==");
        }
        System.out.println("你看我美吗?");
    }
}

执行结果:

3. 捕获多个异常
try{
     编写可能会出现异常的代码
}catch(异常类型A  e){  当try中出现A类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}catch(异常类型B  e){  当try中出现B类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

4. finally 代码块

有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

public class Test01 {
    public static void main(String[] args){
        first();
    }
    public static void first(){
        second();
    }
    public static void second(){
        System.out.println("你能看到我吗?");
        try{
            System.out.println(7 / 0);
        }catch(Exception e){
            //String msg = e.getMessage();
            //System.out.println(msg);
            e.printStackTrace();
        }finally{
            System.out.println("== 很重要 不执行就爆炸 ==");
        }
        System.out.println("你看我美吗?");
    }
}
6. 自定义异常

自己开发一个类 选择继承 Exception / RuntimeException,在其构造方法的首行使用super()指定异常描述信息

// 登录异常
public class LoginException extends Exception {
    /**
     * 空参构造
     */
    public LoginException() {
    }
    /**
     * @param message 表示异常提示
     */
    public LoginException(String message) {
        super(message);
    }
}
7. 异常注意事项
  • 运行时异常被抛出可以不处理。即不捕获也不声明抛出。

  • 如果父类抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集。

  • 父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

  • 当多异常处理时,捕获处理,前边的类不能是后边类的父类

  • 在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收。

  • 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理

  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常

  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常

  • 尽量去处理异常,切记只是简单的调用printStackTrace()去打印

  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定

  • 尽量添加finally语句块去释放占用的资源

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值