异常--java基础语法

本文详细解读了异常的概念,包括Java中的异常体系、编译时异常如`Exception`和`ParseException`的处理,运行时异常如`ArrayIndexOutOfBoundsException`和`NullPointerException`的处理方式,以及自定义异常的实践。强调了异常处理在提升程序健壮性和安全性的重要性。
摘要由CSDN通过智能技术生成

异常的概念和体系

/**
    目标:

    什么是异常?
         异常是程序在"编译"或者"执行"的过程中可能出现的问题。
         异常是应该尽量提前避免的。
         异常可能也是无法做到绝对避免的,异常可能有太多情况了,开发中只能提前干预!!
         异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止,开发中异常是需要提前处理的。

         研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性!!!

         Java会为常见的代码异常都设计一个类来代表。

    异常的体系:
         Java中异常继承的根类是:Throwable。

             Throwable(根类,不是异常类)
          /              \
        Error           Exception(异常,需要研究和处理)
                        /            \
                       编译时异常     RuntimeException(运行时异常)


        Error : 错误的意思,严重错误Error,无法通过处理的错误,一旦出现,程序员无能为力了,
            只能重启系统,优化项目。
            比如内存奔溃,JVM本身的奔溃。这个程序员无需理会。

        Exception:才是异常类,它才是开发中代码在编译或者执行的过程中可能出现的错误,
            它是需要提前处理的。以便程序更健壮!

    Exception异常的分类:
         1.编译时异常:继承自Exception的异常或者其子类,编译阶段就会报错,
                必须程序员处理的。否则代码编译就不能通过!!

         2.运行时异常: 继承自RuntimeException的异常或者其子类,编译阶段是不会出错的,它是在
                运行时阶段可能出现,运行时异常可以处理也可以不处理,编译阶段是不会出错的,
                但是运行阶段可能出现,还是建议提前处理!!
    小结:
        异常是程序在编译或者运行的过程中可能出现的错误!!
        异常分为2类:编译时异常,运行时异常。
            -- 编译时异常:继承了Exception,编译阶段就报错,必须处理,否则代码不通过。
            -- 运行时异常:继承了RuntimeException,编译阶段不会报错,运行时才可能出现。
        异常一旦真的出现,程序会终止,所以要研究异常,避免异常,处理异常,程序更健壮!!
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        int[] arr = {10 , 20 ,30};
        System.out.println(arr[2]);
        System.out.println("程序结束。。。。");
    }
}

常见的运行时异常

/**
    拓展: 常见的运行时异常。(面试题)
         运行时异常的概念:
             继承自RuntimeException的异常或者其子类,
             编译阶段是不会出错的,它是在运行时阶段可能出现的错误,
             运行时异常编译阶段可以处理也可以不处理,代码编译都能通过!!

             1.数组索引越界异常: ArrayIndexOutOfBoundsException。
             2.空指针异常 : NullPointerException。
               直接输出没有问题。但是调用空指针的变量的功能就会报错!!
             3.类型转换异常:ClassCastException。
             4.迭代器遍历没有此元素异常:NoSuchElementException。
             5.数学操作异常:ArithmeticException。
             6.数字转换异常: NumberFormatException。

    小结:
        运行时异常继承了RuntimeException ,编译阶段不报错,运行时才可能会出现错误!
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。");
        /** 1.数组索引越界异常: ArrayIndexOutOfBoundsException。*/
        int[] arrs = {10 ,20 ,30};
        System.out.println(arrs[2]);
        // System.out.println(arrs[3]); // 此处出现了数组索引越界异常。代码在此处直接执行死亡!

        /** 2.空指针异常 : NullPointerException。直接输出没有问题。但是调用空指针的变量的功能就会报错!! */
        String name = null ;
        System.out.println(name); // 直接输出没有问题
        // System.out.println(name.length());  // 此处出现了空指针异常。代码在此处直接执行死亡!

        /** 3.类型转换异常:ClassCastException。 */
        Object o = "齐天大圣";
        //Integer s = (Integer) o;  // 此处出现了类型转换异常。代码在此处直接执行死亡!


        /** 5.数学操作异常:ArithmeticException。 */
        // int c = 10 / 0 ; // 此处出现了数学操作异常。代码在此处直接执行死亡!


        /** 6.数字转换异常: NumberFormatException。 */
        String num = "23aa";
        Integer it = Integer.valueOf(num); // 此处出现了数字转换异常。代码在此处直接执行死亡!
        System.out.println(it+1);

        System.out.println("程序结束。。。。。。");
    }
}

常见的编译时异常认识

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
    目标:常见的编译时异常认识。

    编译时异常:继承自Exception的异常或者其子类,没有继承RuntimeException
               "编译时异常是编译阶段就会报错",
               必须程序员编译阶段就处理的。否则代码编译就报错!!

    编译时异常的作用是什么:
            是担心程序员的技术不行,在编译阶段就爆出一个错误, 目的在于提醒!
            提醒程序员这里很可能出错,请检查并注意不要出bug。

            编译时异常是可遇不可求。遇到了就遇到了呗。
    小结:
        编译时异常是编译阶段就会报错的,继承了Exception,编译时
        异常是可遇不可求。遇到了就遇到了呗。

        编译时异常编译阶段必须处理,否则代码编译不通过!!

 */
public class ExceptionDemo {
    public static void main(String[] args) throws ParseException {
        String date = "2015-01-12 10:23:21";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sdf.parse(date);
        System.out.println(d);
    }
}

异常的产生默认的处理过程解析。(自动处理的过程!)

/**
     目标:异常的产生默认的处理过程解析。(自动处理的过程!)
    (1)默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException。
    (2)异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。
    (3)虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。
    (4)直接从当前执行的异常点干掉当前程序。
    (5)后续代码没有机会执行了,因为程序已经死亡。

 小结:
     异常一旦出现,会自动创建异常对象,最终抛出给虚拟机,虚拟机
     只要收到异常,就直接输出异常信息,干掉程序!!

     默认的异常处理机制并不好,一旦真的出现异常,程序立即死亡!
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。。。。。");
        chu( 10 ,0 );
        System.out.println("程序结束。。。。。。。。。。");
    }

    public static void chu(int a , int b){
        System.out.println(a);
        System.out.println(b);
        int c = a / b ;// 出现了运行时异常,自动创建异常对象:ArithmeticException
        System.out.println("结果是:"+c);
    }
}

编译时异常的处理

编译时异常的处理方式一

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
    目标:编译时异常的处理方式一。

    编译时异常:编译阶段就会报错,一定需要程序员处理的,否则代码无法通过!!

    抛出异常格式:
        方法 throws 异常1 ,  异常2 , ..{

        }
        建议抛出异常的方式:代表可以抛出一切异常,
        方法 throws Exception{

        }

    方式一:
        在出现编译时异常的地方层层把异常抛出去给调用者,调用者最终抛出给JVM虚拟机。
        JVM虚拟机输出异常信息,直接干掉程序,这种方式与默认方式是一样的。
        虽然可以解决代码编译时的错误,但是一旦运行时真的出现异常,程序还是会立即死亡!
        这种方式并不好!

    小结:
        编译时异常编译阶段就报错,必须程序员处理。
        方式一:出现异常的地方层层抛出,谁都不处理,最终抛出给虚拟机。
        这种方式虽然可以解决编译时异常,但是如果异常真的出现了,程序会直接死亡,所以这种方式并不好!

 */
public class ExceptionDemo01 {

    public static void main(String[] args) throws Exception {
        System.out.println("程序开始。。。。");
        parseDate("2013-03-23 10:19:23");
        System.out.println("程序结束。。。。。");
    }

    // Exception是异常最高类型可以抛出一切异常!
    public static void parseDate(String time) throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sdf.parse(time);
        System.out.println(d);

        InputStream is = new FileInputStream("D:/meinv.jpg");
    }



//    public static void main(String[] args) throws ParseException, FileNotFoundException {
//        System.out.println("程序开始。。。。");
//        parseDate("2013-03-23 10:19:23");
//        System.out.println("程序结束。。。。。");
//    }
//
//    // Exception是异常最高类型可以抛出一切异常!
//    public static void parseDate(String time) throws ParseException, FileNotFoundException {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        Date d = sdf.parse(time);
//        System.out.println(d);
//
//        InputStream is = new FileInputStream("D:/meinv.jpg");
//    }

}

编译时异常的处理方式二

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
    目标:编译时异常的处理方式二。

    方式二:在出现异常的地方自己处理,谁出现谁处理。

    自己捕获异常和处理异常的格式:捕获处理
         try{
            // 监视可能出现异常的代码!
         }catch(异常类型1 变量){
            // 处理异常
         }catch(异常类型2 变量){
            // 处理异常
         }...

    监视捕获处理异常企业级写法:
         try{
             // 可能出现异常的代码!
         }catch (Exception e){
            e.printStackTrace(); // 直接打印异常栈信息
         }
         Exception可以捕获处理一切异常类型!

    小结:
        第二种方式,可以处理异常,并且出现异常后代码也不会死亡。
        这种方案还是可以的。
        但是从理论上来说,这种方式不是最好的,上层调用者不能直接知道底层的执行情况!

 */
public class ExceptionDemo02 {

    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        parseDate("2013-03-23 10:19:23");
        System.out.println("程序结束。。。。。");
    }

    public static void parseDate(String time)  {
        try{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date d = sdf.parse(time);
            System.out.println(d);

            InputStream is = new FileInputStream("D:/meinv.png");
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常栈信息
        }
    }

    // JDK 1.7之后
//    public static void parseDate(String time)  {
//        try{
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            Date d = sdf.parse(time);
//            System.out.println(d);
//
//            InputStream is = new FileInputStream("D:/meinv.png");
//        } catch (FileNotFoundException|ParseException e) {
//            e.printStackTrace(); // 打印异常栈信息
//        }
//    }

//    public static void parseDate(String time)  {
//        try{
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
//            Date d = sdf.parse(time);
//            System.out.println(d);
//
//            InputStream is = new FileInputStream("D:/meinv.png");
//        } catch (FileNotFoundException e) {
//            e.printStackTrace(); // 打印异常栈信息
//        } catch (ParseException e) {
//            e.printStackTrace(); // 打印异常栈信息
//        }
//    }


    public static void parseDate1(String time)  {
        try{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
            Date d = sdf.parse(time);
            System.out.println(d);

            InputStream is = new FileInputStream("D:/meinv.png");
        } catch (FileNotFoundException e) {
            System.err.println("文件根本不存在!");
        } catch (ParseException e) {
            System.err.println("解析有问题,请检查代码!");
        }
    }
}

编译时异常的处理方式三

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
    目标:编译时异常的处理方式三。

    方式三: 在出现异常的地方把异常一层一层的抛出给最外层调用者,
            最外层调用者集中捕获处理!!(规范做法)

    小结:
        编译时异常的处理方式三:底层出现的异常抛出给最外层调用者集中捕获处理。
        这种方案最外层调用者可以知道底层执行的情况,同时程序在出现异常后也不会立即死亡,这是
        理论上最好的方案。

        虽然异常有三种处理方式,但是开发中只要能解决你的问题,每种方式都又可能用到!!
 */
public class ExceptionDemo03 {

    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        try {
            parseDate("2013-03-23 10:19:23");
            System.out.println("功能成功执行!!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("功能执行失败!!");
        }
        System.out.println("程序结束。。。。。");
    }

    // 可以拦截所以异常!
    public static void parseDate(String time) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sdf.parse(time);
        System.out.println(d);

        InputStream is = new FileInputStream("D:/meinv.png");
    }
}

运行时异常的处理机制

/**
    目标:运行时异常的处理机制。

    运行时异常在编译阶段是不会报错,在运行阶段才会出错。
    运行时异常在编译阶段不处理也不会报错,但是运行时如果出错了程序还是会死亡
    所以运行时异常也建议要处理。

    运行时异常是自动往外抛出的,不需要我们手工抛出。

    运行时异常的处理规范:直接在最外层捕获处理即可,底层会自动抛出!!

    小结:
         运行时异常编译阶段不报错,可以处理也可以不处理,建议处理!!
         运行时异常可以自动抛出,不需要我们手工抛出。
         运行时异常的处理规范:直接在最外层捕获处理即可,底层会自动抛出!!
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        try{
            chu(10 , 0);
            System.out.println("操作成功!");
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("操作失败!");
        }
        System.out.println("程序结束。。。。");
    }

    public static void chu(int a , int b)  {
        System.out.println( a / b );
    }
}

finally关键字

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
    目标:finally关键字

    用在捕获处理的异常格式中的,放在最后面。
        try{
            // 可能出现异常的代码!
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            // 无论代码是出现异常还是正常执行,最终一定要执行这里的代码!!
        }
        try: 1次。
        catch:0-N次  (如果有finally那么catch可以没有!!)
        finally: 0-1次

    finally的作用: 可以在代码执行完毕以后进行资源的释放操作。
    什么是资源?资源都是实现了Closeable接口的,都自带close()关闭方法!!

 */
public class FinallyDemo {
    public static void main(String[] args) {
        //chu();
        System.out.println(chu1());
    }

    public static int chu1(){
        try{
            int a = 10 / 2 ;
            return a ;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }finally {
            System.out.println("=====finally被执行");
            return 111; // 不建议在finally中写return,会覆盖前面所有的return值!
        }
    }

    public static void chu(){
        InputStream is = null;
        try{
            //System.out.println(10/0);
            is = new FileInputStream("D:/cang.png");
            System.out.println(10 / 0 );

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("==finally被执行===");
            // 回收资源。用于在代码执行完毕以后进行资源的回收操作!
            try {
                if(is!=null)is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

异常的语法注意:(了解)

/**

     目标:异常的语法注意:(了解)
         - 运行时异常被抛出可以不处理。可以自动抛出,编译时异常必须处理.按照规范都应该处理!
         - 重写方法申明抛出的异常,应该与父类被重写方法申明抛出的异常一样或者范围更小
         - 方法默认都可以自动抛出运行时异常!  throws RuntimeException可以省略不写!!
         - 当多异常处理时,捕获处理,前边的异常类不能是后边异常类的父类。
         - 在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收操作。
*/
public class ExceptionDemo {
}

class Fu{
    public void run() throws Exception{

    }
}

class Zi extends Fu{
    @Override
    public void run() throws Exception{

    }
}

自定义异常(了解)

/**
    目标:自定义异常(了解)

    引入:Java已经为开发中可能出现的异常都设计了一个类来代表.
        但是实际开发中,异常可能有无数种情况,Java无法为
        这个世界上所有的异常都定义一个代表类。
        假如一个企业如果想为自己认为的某种业务问题定义成一个异常
        就需要自己来自定义异常类.

    需求:认为年龄小于0岁,大于200岁就是一个异常。

    自定义异常:
        自定义编译时异常.
            a.定义一个异常类继承Exception.
            b.重写构造器。
            c.在出现异常的地方用throw new 自定义对象抛出!
            编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理!!

        自定义运行时异常.
            a.定义一个异常类继承RuntimeException.
            b.重写构造器。
            c.在出现异常的地方用throw new 自定义对象抛出!
            提醒不强烈,编译阶段不报错!!运行时才可能出现!!
    小结:
        自定义异常是程序员自己定义的异常
        继承Exception/RuntimeException,重写构造器。
        在出现异常的地方用throw new 自定义异常对象抛出!
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            checkAge(101);
        } catch (ItheimaAgeIllegalException e) {
            e.printStackTrace();
        }
    }

    public static void checkAge(int age) throws ItheimaAgeIllegalException {
        if(age < 0 || age > 200){
            // 出现异常了!
            // throws:用在方法上,用于抛出方法中的异常。
            // throw:用在出现异常的地方,用于创建异常对象且立即从此处抛出!
            throw new ItheimaAgeIllegalException("/ age is illegal!");
            //throw new ItheimaAgeIllegalRuntimeException("/ age is illegal!");
        }else{
            System.out.println("年龄是:"+age);
        }
    }
}

自定义编译时异常类

/**
    自定义编译时异常类:
        1.继承Exception。
        2.重写构造器。
 */
public class ItheimaAgeIllegalException extends Exception {
    public ItheimaAgeIllegalException() {
    }

    public ItheimaAgeIllegalException(String message) {
        super(message);
    }

    public ItheimaAgeIllegalException(String message, Throwable cause) {
        super(message, cause);
    }

    public ItheimaAgeIllegalException(Throwable cause) {
        super(cause);
    }

    public ItheimaAgeIllegalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

自定义运行时异常类

/**
    自定义运行时异常类:
        1.继承RuntimeException
        2.重写构造器。
 */
public class ItheimaAgeIllegalRuntimeException extends RuntimeException {
    public ItheimaAgeIllegalRuntimeException() {
    }

    public ItheimaAgeIllegalRuntimeException(String message) {
        super(message);
    }

    public ItheimaAgeIllegalRuntimeException(String message, Throwable cause) {
        super(message, cause);
    }

    public ItheimaAgeIllegalRuntimeException(Throwable cause) {
        super(cause);
    }

    public ItheimaAgeIllegalRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

异常的强大之处

import java.util.Scanner;

/**
     拓展:异常的作用
         1.可以处理代码问题,防止程序出现异常后的死亡。
         2.提高了程序的健壮性和安全性。
 */
public class Demo {
    public static void main(String[] args) {

        // 需求:请输入一个合法的年龄为止。  12\r\n
        while(true){
            try{
                Scanner sc = new Scanner(System.in);
                System.out.println("请您输入您的年年龄:");
                int age = sc.nextInt();
                System.out.println("您是:"+age);
                break;
            }catch (Exception e){
                System.err.println("您的年龄是瞎输入的!");
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值