Java异常

什么是异常?

程序运行过程中,由于程序中数据不合法,发生了不正常的情况,造成程序中断向下执行,最终导致JVM非正常终止

异常的存在形式?

以异常类型的对象存在的,对象携带了异常相关的信息

异常的体系

编译时异常

public class ExceptionDemo1 {
    public static void main(String[] args) {
//日期格式对象
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//书写代码时,代码没有问题,但发生:错误提示(当前位置可能会发生异常)
     Date date = sdf.parse("2022-11-07");//编译时异常
    }
}
-------------------------------------1public class ExceptionDemo1 {
    public static void main(String[] args) throws ParseException {
//日期格式对象
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//书写代码时,代码没有问题,但发生:错误提示(当前位置可能会发生异常)
 Date date = sdf.parse("2022-11-07");//编译时异常
    }
}
-------------------------------------------2public class ExceptionDemo1 {
    public static void main(String[] args) {
     //日期格式对象
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//书写代码时,代码没有问题,但发生:错误提示(当前位置可能会发生异常)
     try {
         Date date = sdf.parse("2022-11-07");//编译时异常
    } catch (ParseException e) {
     throw new RuntimeException(e);
        }
    }
}

运行时异常

public class ExceptionDemo3 {
    public static void main(String[] args) {
        String name = null;
        //要处理method方法中抛出的异常
        method(name);

    }

    public static void method(String name) {
        //校验:参数不能为空
        if(name == null ||"".equals(name)){
            throw new RuntimeException("参数不能为空!");
            //throw代码后面不能写任意代码
            //System.out.println("当前代码不能执行");//报错
        }
        System.out.println("你好");//可以写
    }
}
/**
Exception in thread "main" java.lang.RuntimeException: 参数不能为空!
	at com.ExceptionDemo3.method(ExceptionDemo3.java:14)
	at com.ExceptionDemo3.main(ExceptionDemo3.java:7)*/

虚拟机默认处理异常?

当前发生异常的代码位置处,有处理异常的代码,那么异常就会被处理掉,程序继续执行

当前发生异常的代码位置处,没有处理异常的代码(程序中没有处理异常的代码),最终异常会抛出给JVM来处理

JVM处理异常的方式:

  1. 打印异常的信息(异常的类型、异常发生的位置、异常的原因)

  2. JVM停止

异常处理的方式

1. 声明:throws

- 遇到异常发生了,自己不处理,交给别人处理
  • 最终还是需要有一个位置使用try…catch来处理异常

  • 结论:在main方法中,只能使用try…catch

使用声明的方式处理异常:
//使用声明的方式处理异常,声明是书写在方法定义上
修饰符号  返回值类型 方法名(参数类型 参数,...) throws 异常类1 , 异常类2.... 
{
    
}

//在定义方法时,使用声明的方式处理异常
public void method(String name) throws NullPointerException {
   
}



public class ExceptionDemo5 {
    private static final Logger LOGGER = LoggerFactory.getLogger("ExceptionDemo5类");
    public static void main(String[] args) {
        String strDate = "2000年10月10日";
        try {//监视可能会发生异常的代码
            //调用的方法可能会发生异常(自己处理)
            Date birthday = method (strDate);
            System.out.println("生日:"+birthday);//跳过运行
        } catch (ParseException e) {//处理异常:拿异常对象类型和当前定义的异常类型进行匹配
            System.out.println("处理异常");
            /**输出:
             * 处理异常
             */
           System.out.println(e.toString());//把异常对象转化成字符串
            /**输出:
             * java.text.ParseException: Unparseable date: "2000年10月10日"
             */

            //在开发中,出现异常后,为了方便程序员调试代码,需要把异常信息打印出来(是哪个类,哪个位置)
           e.printStackTrace();
            /**输出:
             * java.text.ParseException: Unparseable date: "2000年10月10日"
             * 	at java.base/java.text.DateFormat.parse(DateFormat.java:399)
             * 	at com.ExceptionDemo5.method(ExceptionDemo5.java:37)
             * 	at com.ExceptionDemo5.main(ExceptionDemo5.java:17)
             */
             LOGGER.error(e.getMessage());//获取异常原因
            /**输出:
             * 2025-07-27 22:09:28.965 [ERROR]  ExceptionDemo5类 [main] : Unparseable date: "2000年10月10日"
             */

        }
        System.out.println("程序继续执行");
        /**输出
         * 程序继续执行
         */

    }

    public static Date method(String strDate) throws ParseException {
        //格式化对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.parse(strDate);//有发生异常
    }
}

public class ExceptionDemo6 {
    private static final Logger LOGGER = LoggerFactory.getLogger("ExceptionDemo5类");

    public static void main(String[] args) {
        //键盘录入
        Scanner sc = new Scanner(System.in);
        Date birthday = null;
        while (true) {
            System.out.println("请输入您的生日(年-月-日):");
            String strDate = sc.next();
            try {
                //调用的方法可能会发生异常(自己处理)
                birthday = new SimpleDateFormat("yyyy-MM-dd").parse(strDate);
                break;//当输入正确,停止循环
            } catch (ParseException e) {
                System.out.println("您输入的格式错误,请重新输入");
            }
        }
            System.out.println("生日:" + birthday);

            System.out.println("程序继续执行");

    }

}
/**
 * 请输入您的生日(年-月-日):
 * 2025年8月9日
 * 您输入的格式错误,请重新输入
 * 请输入您的生日(年-月-日):
 * 2025-8-9
 * 生日:Sat Aug 09 00:00:00 CST 2025
 * 程序继续执行
 */

2. 捕获:try..catch

阻止异常的传递,能让代码继续往下运行
public class ExceptionDemo4 {

    public static void main(String[] args) {
        int[] array = null;
      //  method2(array);
//法1
       method1(array);
        /**
         * Exception in thread "main" java.lang.RuntimeException: 传递的参数不能为空
         * 	at com.ExceptionDemo4.method1(ExceptionDemo4.java:21)
         * 	at com.ExceptionDemo4.main(ExceptionDemo4.java:14)
         */
//        法2
//        try {
//            method1(array);
//        }catch (RuntimeException e){
//            System.out.println(e.getMessage());
//        }
//        System.out.println("main方法继续执行");
        /**
         * 传递的参数不能为空
         * main方法继续执行
         */

    }

    public static void method1(int[] arr) {
        if(arr == null){
            //手动引发异常并抛出
            /**
             * 注意:
             * 1.抛出异常的格式必须在方法内部完成
             * 2.如果手动抛出一个异常,下面的代码无法执行
             */
            throw new RuntimeException("传递的参数不能为空");
        }
       
        //遍历数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

    }

    public static void method2(int[] arr) {
        if(arr == null){
            System.out.println("传递的参数不能为空nh");
           //会产生运行时异常,最终导致JVM终止,并抛出异常
            /**
             * 传递的参数不能为空nh
             * Exception in thread "main" java.lang.NullPointerException: Cannot read the array length because "arr" is null
             * 	at com.ExceptionDemo4.method2(ExceptionDemo4.java:51)
             * 	at com.ExceptionDemo4.main(ExceptionDemo4.java:7)
             */
        }
        //遍历数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

throws和throw的区别

throws :

用在方法声明后面,跟的是异常类名

表示声明异常,调用该方法有可能会出现这样的异常

异常对象有JVM创建

throw : 抛出 (手动引发异常)

用在方法体内

表示手动抛出异常对象,告知调用者数据传入有误

异常对象我们自己创建

程序员手动创建一个异常对象,并招抛出给调用者
//把创建的异常类对象抛出给调用者 
 throw new RuntimeException("参数不能为空");
注意:
1.抛出异常的格式必须在方法的内部完成

2.如果手动抛出异常,下面的代码无法执行

异常的解决方式在开发中怎么选择?

自定义方法(程序员自己写的方法),通常都可以使用:声明

方法体内代码比较清爽(阅读性好)

把异常统一抛出到main方法中,进行统一的处

捕获的使用场景:

  1. main方法中只能使用捕获

  2. 父类型中的方法不支持throws,在子类重写方法时,重写的方法只能使用:捕获

 public class Demo  extends Thread{
         //重写方法
         public void run(){
             try {
                 Thread.sleep(100);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
     }

Throwable类中常用方法

Throwable类 //异常的顶层父类型

子类:Error类(错误类)
//异常处理无法解决错误
子类:Exception类(异常类)
//可以使用异常处理解决(保证程序运行过程中不会中断)
编译时异常:Exception类
运行时异常:RuntimeException类 (继承了Exception)

Throwable的成员方法:

public String getMessage()   //返回throwable的详细消息字符串
public String toString()     //返回此可抛出的简短描述
public void printStackTrace()  //把异常的错误信息输出在控制台

自定义异常:

  • 程序员自己编写的异常类
  • 解决问题: JDK提供的异常类在命名上做不到见名其知意,通常在开发中程序员会自定义自己的异常类(见名其知意)
public 自定义异常类 extends Exception{ //当前自定义异常类为:编译时异常
      public 自定义异常类(){
          //super();//调用父类中的无参构造方法
      }
      public 自定义异常类(String message){
          super(message);
      }
  }
  
  public 自定义异常类 extends RuntimeException{ //当前自定义异常类为:运行时异常
      
  }

//自定义异常类
public class AgeOutOfBoundsException extends RuntimeException{
    public AgeOutOfBoundsException() {
    }

    public AgeOutOfBoundsException(String message) {
        super(message);
    }
}
public class ExceptionDemo7 {
private static final Logger logger = LoggerFactory.getLogger("ExceptionDemo7类");
    //自定义异常处理
    public static void main(String[] args) {
        try {
            printInfo("熊大", 9);
        } catch (NullPointerException e){
            System.out.println("处理空值异常");
        }catch (AgeOutOfBoundsException e){
            System.out.println("处理年龄超出范围异常");
            //记录到日志中
            logger.error(e.getMessage());
            /**
             * 处理年龄超出范围异常
             * 2025-07-27 22:23:37.295 [ERROR]  ExceptionDemo7类 [main] : 传递的值为:9,传递的年龄必须是18~50之间
             */

        }catch (RuntimeException e){
            System.out.println("处理其他运行异常");
        }catch (Exception e){
            System.out.println("可以处理任何异常");
        }
    }
    //因为异常默认的处理方式就是:当前没有异常处理,抛出异常
    public  static void printInfo(String  name , Integer age){
        //校验:传入的数据不能为空
        if(name == null || "".equals(name)){
            throw  new NullPointerException("传递的姓名不能为空");
        }
        if(age < 18 || age > 50){
            //使用自定义异常
            throw new AgeOutOfBoundsException("传递的值为:"+age+",传递的年龄必须是18~50之间");
        }
        System.out.println("姓名:"+name);
        System.out.println("年龄:"+age);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值