java中的异常机制

  • 什么是异常?java中提供异常处理机制有什么作用?
    异常是程序在执行过程中出现的一些不正常情况;
    异常能够提高程序的健壮性,java中提供了异常处理机制,能够将程序执行过程中发生的不正常情况打印到控制台,提醒程序员。异常信息由JVM打印。

  • 异常在java中以什么形式存在?
    异常在java中以类的形式存在,每一个异常类都可以创建异常对象。所有的异常类是从 java.lang.Exception 类继承的子类。异常发生了,底层一定会new一个异常对象出来。

public class TestException {
    public static void main(String[] args) {
//        异常可以创建对象
        NumberFormatException nfe = new NumberFormatException("数字格式化异常");
        System.out.println(nfe);
        int a = 10;
        int b = 0;
        int c = a/b; //实际上JVM执行到此处的时候会new异常对象,并且JVM将异常对象抛出,打印输出信息到控制台
        System.out.println(c);
        System.out.println(100/0);//new ArithmeticException(" / by zero")
    }
}
  • 异常类的层次
    Object: Object下有Throwable(可抛出的),不管是异常还是错误都是可以抛出的
    Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
    Exception下有两个分支:
    Exception的直接子类:编译时异常(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错,因此得名编译时异常。),也被称为受检异常或者受控异常。
    RuntimeException:运行时异常。(在编写程序阶段程序员可以预先处理,也可以不管,都行。),也叫未受检异常或者非受控异常
  • 编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常是不会发生的。因为只有程序运行阶段才可以new对象。因为异常的发生就是new异常对象。
  • 编译时异常和运行时异常的区别?
    编译时异常一般发生的概率比较高。运行时异常一般发生的概率比较低。
  • 假设java中没有对异常进行划分,没有分为:编译时异常和运行时异常,所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果呢?
    首先,如果这样的话,程序肯定是绝对的安全的。但是程序员编写程序太累,代码到处都是处理异常的代码。
  • Java语言中对异常的处理包括两种方式:
    第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级。谁调用我,我就抛给谁。叫异常上抛。
    第二种方式:使用try…catch语句进行异常的捕捉。捕捉后,后面的程序可以继续执行
  • 注意:Java中异常发生之后如果一直上抛,最终抛给了main方法,如果不捕捉的话,main方法会自动向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果。终止java程序的执行。
  • 关于异常处理的两种方式,代码执行效果的差异
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class TestException {
    public static void main(String[] args) {
        try {//尝试执行m1方法
            m1();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
//        这里采用捕捉的方式,故下面这行代码会执行
        System.out.println("main end");
    }
    public static void m1() throws FileNotFoundException{
        System.out.println("m1begin");
        m2();
//        这里继续上抛,下面这行代码不会执行
        System.out.println("m1end");
    }
    public static void m2() throws FileNotFoundException {
        System.out.println("m2begin");
        FileInputStream fileInputStream = new FileInputStream("C:\\Proram Files");//路径不存在,出现FileNotFoundException异常
//        这里采用上抛的处理方式,故下面这行代码不会执行
        System.out.println("m2end");
    }
}
  • 异常中的两个重要方法
/*异常有两个重要的方法*/
public class TestException01 {
    public static void main(String[] args) {
        //        这里虽然创建了异常对象,但是没有将异常抛出,JVM会认为只是一个普通的JVM对象
        NumberFormatException nfe = new NumberFormatException("数字格式化异常");
        String str1 = nfe.getMessage();//获取简单的描述信息
        System.out.println(str1);
        /*
        throw nfe;//将异常抛出,JVM会中断程序
        */
        nfe.printStackTrace();//打印异常堆栈信息,异常追踪信息,捕捉异常后通常写这个
    }
}

  • 关于try…catch中的finally子句:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class TestException02 {
    public static void main(String[] args) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream("C:\\important.txt");
            String str = null;
            str.toString();//这里会出现空指针异常,导致下面代码不会执行
//            fileInputStream.close();//流使用完需要关闭,因为流是占用资源的
        } catch (FileNotFoundException e) {//编译时异常
            e.printStackTrace();
        } catch (NullPointerException e) {//运行时异常
            e.printStackTrace();
        } finally {//一定会执行,通常完成资源的释放/关闭
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        /*
        try...finally
        try不能单独使用*/
        try {
            System.out.println("");
            return;//程序执行到这里之后,先执行finally语句块,再return结束方法
        } finally {
            System.out.println("就算try中有return语句,finally里的语句一样会执行");
        }
    }
}

有一个语句除外:

public class TestException03 {
    public static void main(String[] args) {
        try {
            System.out.println("HelloWord");
            System.exit(0);
        } finally {
            System.out.println("不会执行了");
        }
    }
}

  • 试分析以下代码的执行结果:
public class TestException03 {
    public static void main(String[] args) {
        int result = m1();
        System.out.println(result);
    }
    public static int m1() {
        int i = 100;
        try {
            return i;
        } finally {
            i++;
        }
    }
}

结果是100;java中遵循方法体中的代码是自上而下依次执行的,return语句一旦执行,整个方法必须结束,也就是说return语句一定是方法中执行的最后一个语句,但finally里面的代码也一定会执行,而且先于return语句,为了遵循自上而下的执行原则,return返回的是没有经过++的i值。反编译效果如下:

public static int m1() {
        int i = 100;
        int j = i;
        i++;
        return j;
    }
  • java中自定义异常
    1.编写一个类继承Exception或RuntimeException
    2.提供两个构造方法,一个无参的,一个带有String参数的
public class MyException extends Exception {//编译时异常(继承RuntimeException为运行时异常)
    public MyException() {
        super();
    }
    public MyException(String string) {
        super(string);
    }
}
  • 重写之后的方法不能比重写之前的方法抛出更多(更广)的异常(编译时异常),可以更少

  • 总结
    方法对程序执行过程中可能会出现的不正常情况,或者是超出意愿的事,对其视作异常处理,new出异常对象,将其上抛,如果创建的是编译时异常对象,则调用者必须对其进行处理,上抛或者捕捉,如果创建的是运行时异常对象,则调用者可以先不处理。

  • 异常的应用场景

LengthException为自定义的异常类,如下代码为创建用户的方法,规定用户名的字符应在6到15之间,否则抛出异常。

public static User register(String str1,String str2) throws LengthException {
        if (str1 == null || str1.length() > 14 || str1.length() < 6) {
            throw new LengthException("用户名长度不规范,应在[6,15]个字符之间");
        }
        return new User(str1,str2);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值