Java异常处理

异常处理

1.java的异常处理机制

1.1 异常在Java中是以对象的形式存在的

1.1.1 异常的继承结构
  • 继承结构可以用画UML(Unified Modeling Language 统一建模语言)图的形式来表示
    • 一般是架构师或者系统分析师使用
    • 相当于盖楼之前的设计图
  • Java中的异常继承结构
    • Object
    • Trowable
    • Exception
      • Exception 的直接子类:编译时异常 (要求程序员务必在编写程序的时候预先处理这些异常)
        • 编译时异常只是提醒程序员,如果不处理这段代码非常非常大的概率出现错误
        • 编译时异常其实不是异常,只是警告程序员,这样写运行的时候大概率报错。
        • 只有运行阶段才会发生异常,发生异常就是new一个异常对象
        • 就像有一条马路和一根钢丝,提示程序员把钢丝换成马路,不然编译不给过,因为走钢丝99%出事(大概率)
      • RuntimeException : 运行时异常 (在编写程序阶段处理不处理都可以)
        • 运行时异常是程序运行时发生的异常
1.1.2 编译时异常和运行时异常的比较
  • 编译时异常发生的概率非常高,如果不在编写时处理,运行大概率报错
  • 运行时异常发生概率很小,因为大概率的错误在编写的时候避免了
1.1.3 编译时异常的其他名字
  • 受检异常:CheckedException
  • 受控异常
1.1.5 运行时异常的其他名字
  • 未受控异常 UnCheckedException
  • 非受控异常
1.1.6 处理异常的两种方式
  • 在方法声明的位置上使用throws关键字
    • 如果在该方法处不方便处理,就使用throws关键字抛给上一级,给上一级处理
  • 使用try…catch语句进行一次的捕捉
    • 在这里就直接处理掉,不继续抛给调用者,真正解决这个异常

注意:

  • Java发生异常如果一直上抛给调用者,最终抛给了main方法,main方法继续上抛则抛给了调用者JVM,JVM会终止程序

2.异常的发生过程

//例一
class Draft01{
    public static void main(String[] args) {
        /*
            程序执行到这里发生了ArithmaticException
            底层new了一个ArithmaticException异常对象,然后抛给main方法(抛给调用者)
            main方法没有对这个异常进行预先处理,将这个异常抛给了JVM
            JVM终止了程序的运行
         */
        System.out.println(100/0);
        //由于程序在上面终止了,所以没有输出Hello World!
        System.out.println("Hello World!");
    }
}
//例二
class Main{
    public static void main(String[] args) {
        NumberFormatException nfe=new NumberFormatException("数字格式化异常!");
        System.out.println(nfe);
        NullPointerException npe=new NullPointerException("空指针异常!");
        System.out.println(npe);
       //doSome();报错
        /*
            doSome()抛出了ClassNotFoundException异常
            main方法调用 doSome() 的时候需要处理这个异常
            而main方法中没有处理
         */
        System.out.println("Hello");//doSome()方法的异常没有捕捉,后面的代码不执行
    }

    /*
        这里在方法的声明处使用throws ClassNotFoundException说明该方法很呢能出现
        ClassNotFoundException异常,需要调用者对这个异常进行处理
        如果没人调用,则程序正常运行
     */

    public static void doSome() throws ClassNotFoundException{
        System.out.println("dosome");
    }

}

2.1 代码什么时候不执行

  • 异常没有捕捉,采用上报的方式,后面的代码不执行
  • try语句块中某句出现异常,后面的代码不执行,直接进入catch语句块

2.2 try…catch深入

  • catch()括号中可以写父类异常类型也可以写确切的异常类型
  • catch可以写多个,建议精确写出,一个个处理,这样利于调试
  • catch写多个的时候必须遵循从小到大(子类到父类)
    • 因为catch是从上到下依次捕捉
    • 如果父类在上面,下面的子类异常都被上面的父类捕捉,后面的子类catch语句不会执行,编译器会报错
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            FileInputStream fis=new FileInputStream("");
            fis.read();
        }catch (FileNotFoundException | NullPointerException e){//Java8新写法,或的方式写多个异常
            //子类异常,如果出现FileNotFoundException异常,就执行里面的语句
            System.out.println("文件不存在!!");
        }catch (IOException e){//父类异常
            System.out.println("读文件报错了!!");
        }
    }
}

3. 异常对象的常用方法

  • 获取异常的简单描述信息(异常的构造方法中传入的信息)

    • String msg=e.getMessage();
      
  • 打印异常追踪的堆栈信息(更详细的异常信息,方便找出具体错误,建议开发中使用该方法)

    • e.printStackTrace();
      
public class Main {
    public static void main(String[] args) {
        NullPointerException e=new NullPointerException("空指针异常!");
        //throw e; 这样才算抛出异常,上面只是创建异常对象,没有抛出之前是一个普通的Java对象

        //获取异常的简单描述信息
        String msg=e.getMessage();//上面空指针异常的构造方法中传入的信息
        System.out.println(msg);

        //打印异常追踪的堆栈信息
        e.printStackTrace();
    }
}

4. finally子句的使用

  1. finally子句中的代码是最后执行的,并且一定会执行,即使try语句块中出现了异常
  2. finally子句常用情况
  • 完成资源的释放/关闭

  • 如果在别的情况下关闭,可能在关闭前出现异常,导致关闭语句不执行,非常不安全

  • try不能单独使用,可以和catch或者finally联用

public class Main {
    public static void main(String[] args) {
        /*
            try和finally可以联合使用
            执行顺序:
            try...
            finally...
            return
         */
        try {
            System.out.println("try...");
            return;
        }finally {
            //finally中的语句会执行
            System.out.println("finally...");
        }
 
        //System.out.println("hello"); 报错,这里无法执行到,finally执行完执行return
    }
}
  • 不执行finally子句的特殊情况
public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("try...");
            //退出JVM,此时不再执行finally中的语句
            System.exit(0);
        }finally {
            System.out.println("finally...");
        }
    }
}

5. final,finally,finalize的区别

  • final
    • final修饰的类无法继承
    • final修饰的方法无法覆盖
//final修饰的类无法继承
final class A{
    //常量
    public static final double PI=3.1415926;
    
    public final void doSome(){
        //final修饰的方法无法继承
    }
}
  • finally

    • 一个关键字,和try联用,用于异常处理
  • finalize

    • 一个标识符
    • Object类中的一个方法
    • 垃圾回收前执行该方法中的代码(遗言),该方法已经过时

6. 自定义异常

  • Java中自带的异常是不够用的,实际开发中需要自己自定义一些异常

6.1 自定义异常的步骤

  • 第一步
    • 编写一个Exception或者RuntimeException
  • 第二步
    • 提供两个构造方法,一个无参,一个有参
public class MyException extends Exception{//编译时异常
    //无参构造
    public MyException() {
    }

    //有参构造
    public MyException(String message) {
        super(message);
    }
}
/*
    public class MyException extends Exception{//运行时异常

    }
 */
public class Main {
    public static void main(String[] args) {
        //创建一个异常对象(还没抛出)
        MyException e=new MyException("用户名不能为空!");

        //打印异常堆栈信息
        e.printStackTrace();
    }
}

6.2 异常在开发中的使用

public class Main {
    public static void main(String[] args) {
       try {
           doSome();
       }catch (Exception e){
           //打印异常的简单信息
           System.out.println(e.getMessage());
           
           //打印异常堆栈信息(更详细,定位到出错的行数)
           e.printStackTrace();
       }
    }

    public static void doSome() throws MyException{
        //抛出编译时异常,需要解决,(上抛或try catch捕捉)
        //如果在这里捕捉相当于没抛,不如直接打印一行信息
        //所以采用上抛的方式,调用的时候按具体情况来捕捉,既可以终止程序,又可以打印异常信息
        throw new MyException("这里出现了异常!");
    }

}

6.3 重写之后的方法只能抛出比原来相同或更少的异常

  • 父类方法没有抛出异常,子类不能抛出
class Animal{
    public void doSome(){
        
    }
}

class Cat extends Animal{
    /*
    父类中的方法没有抛出异常,子类不能抛出
    public void doSome() throws Exception{
        
    }*/
}
  • 父类方法抛出异常,子类可以抛出相同,范围更小异常,或者不抛出
class Animal{
    public void doSome() throws Exception{

    }

    public void doOther() throws Exception{
        
    }
    
    public void m() throws Exception {
        
    }
}

class Cat extends Animal{

    //父类方法抛出异常,子类可以抛出相同或范围更小的异常,也可以不抛出
    
    //不抛出
    public void doSome(){

    }
    //相同
    public void doOther() throws Exception {
        
    }
    //更小
    public void m() throws NullPointerException {

    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值