异常+异常链

异常:

  1. 在程序运行过程中发生的不正常事件
  2. Java中所有异常都是Exception(父类)
  • 传统处理程序中异常:
  1. System.exit(1);参数必须为非0数,结束/退出JVM(java虚拟机)
  2. System.err.println();控制台输出错误流,为红色字体。
  • 异常处理机制:
  1. 为程序提供错误处理的能力
  • 5个关键字:
  1. try 执行可能产生异常的代码
  2. catch 捕获异常
  3. finally 无论是否发生异常,代码都能执行
  4. throw 声明异常,声明方法可能要抛出的各种异常
  5. thorws 手动抛出异常

语法:

try{
//代码段(此处不会出现异常)
}catch(异常Exception或Exception的子类){
//对异常进行处理的代码段
}
//代码段
}
    public class Test1 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
//        除数为0异常: ArithmeticException
//        输入格式不正确: InputMismathException(子类)
        try{
            //程序中可能出现异常的代码
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
        }catch(ArithmeticException e){
            //在程序出现异常的情况下执行的代码
            System.err.print("出现错误操作"+"
");
            //异常对象 e printStackTrace();打印异常堆栈信息
            e.printStackTrace();
        }
        System.out.println("感谢使用本程序!");

    }
}
  1. 无异常。try->catch直接执行后面代码
  2. 有异常,与cetch后面异常类型匹配 : try->catch里面代码->后面代码
  3. 有异常,与cetch后面异常类型不匹配:try->中断,结束运行
  4. printStackTrace();打印异常堆栈信息
  5. getMessage();获得异常字符串提示信息,打印需使用输出语句

tyr–cetch–finally语法:

try{
//代码块
}cetch(){
//代码块
}finally{
//代码块
}


  public class Test2 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        // 除数为0异常: ArithmeticException
        // 输入格式不正确: InputMismathException(子类)
        try {
            //程序中可能出现异常的代码
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
        } catch (ArithmeticException e) {
            //在程序出现异常的情况下执行的代码
            System.err.print("出现错误操作" + "
");
            // 异常对象 e printStackTrace();打印异常堆栈信息
            e.printStackTrace();
        } finally {
            System.out.println("感谢使用本程序!");
        }
    }
}
  • finally不执行的情况:
  1. 在cetch代码块中结束JVM(如:System.exit(1))运行情况下finally代码块不执行
  2. cetch代码块存在return时,会先执行finally代码块,最后执行return

多重cetch块:

try{
//代码块
}cetch(){
//代码块
}cetch(){
//代码块
}cetch(){
//代码块
}finally{
//代码块
}


public class Test3 {
public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    System.out.print("请输入被除数:");
    // 除数为0异常: ArithmeticException
    // 输入格式不正确: InputMismatchException(子类)
    try {
        int num1 = in.nextInt();
        System.out.print("请输入除数:");
        int num2 = in.nextInt();
        System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
    } catch (ArithmeticException e) {
        System.err.print("除数不能为0" + "
");
        // 异常对象 e printStackTrace();打印异常堆栈信息
        e.printStackTrace();
    } catch (InputMismatchException e) {
        System.err.print("输入格式不正确" + "
");
        e.printStackTrace();
    } catch (Exception e) {
        System.err.print("未知异常" + "
");
        e.printStackTrace();
    }finally {
        System.out.println("感谢使用本程序!");
    }
}

约束条件:越具体的子异常类放在catch首位,越抽象的父异常类越往后写
cetch语句顺序:先子类,后父类
发生异常时按顺序逐个匹配
只执行第一个与异常类型匹配的cetch语句
try块为必须,但不能单独出现。

throws :

  • 声明某个方法可能抛出的各种异常,多个异常用逗号隔开。
  1. 调用者处理异常
  2. 调用者继续声明异常
  • Main()方法声明的异常由JVM处理。
public void 方法名()throws 异常类型{
//代码块
}
public static void main(String[] args){
类名 t = new 类名();
try{
t.方法名();
}
}
 public static void a() throws ArithmeticException{
            int num=5/0;
            throw  new ArithmeticException("除数不能为0");
    }
    
    public static void b(){
    try{
        a();
    }catch(ArithmeticException e){
        e.printStackTrace();
    }
    }

或者继续抛出:

public void 方法名()throws 异常类型{
 //代码块
}
public static void     main(String[] args) throws 异常类型{
类名 t = new 类名();
 t.方法名();
}
    

public static void main(String[] args) {
        try{
            b();
        }catch(ArithmeticException e){
            e.printStackTrace();
        }
    }
    
    public static void a() throws ArithmeticException{
            int num=5/0;
            throw  new ArithmeticException("除数不能为0");
    }
    
    public static void b() throws ArithmeticException{
            a();
    }

throw:

  • 抛出异常。
public void 方法名()throws Exception{
           throw new Exception(“性别只能为男女”);
    }
    throw  new ArithmeticException("除数不能为0");

throw必须处理或者继续抛出异常。

throw 与 throws

  • throw:
  1. 生成并抛出异常
  2. 位于方法体内部,可作为单独语句使用
  3. 抛出一个异常对象,且只能是一个
  • throws
  1. 声明方法内抛出了异常
  2. 必须跟在方法参数列表后面,不能单独使用
  3. 声明抛出异常类型,可以跟多个异常

异常处理原则:

  1. 异常处理与性能
  2. 异常只能用于非正常情况
  3. 不要将过于庞大的代码块放在try中
  4. 在catch中指定具体的异常类型
  5. 需要对捕获的异常做处理
  6. 异常分为Checked异常和运行时异常:
  7. Checked异常必须捕获或者声明抛出
  8. 运行时异常不要求必须捕获或者声明抛出

常见异常类型:

  1. Exception 异常层次结构的父类
  2. ArithmeticException 除数为0异常
  3. InputMismathException 输入格式不正确
  4. ArrayIndexOutOfBoundsException 数组下标越界异常
  5. NullPointerException 空指针异常
  6. ClassNotFoundException 不能加载所需的类
  7. IIIegalArgumentException 方法接收到非法参数
  8. ClassCastException 对象强制类型转换出错
  9. NumberFormatException 数字格式转换异常,如把”abc”转换成数字

异常链:

  • 由一种异常引发另一种异常
  • 异常链创建了新的异常但却包含了原有异常的信息。
    • 自定义一个登录与注册异常类继承父类Exception,重写父类构造方法
public class LoginFaildException extends Exception {
public LoginFaildException() {
        super();
        
    }

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

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

    public LoginFaildException(Throwable cause) {
        super(cause);
        
    }
    • 定义用户类,声明用户名与密码,添加构造方法
public  class User {
    private String userName;
    private String passWord;
    
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    • 声明注册与登录方法
// 注册方法
        public static boolean register(User user) throws RegisterException {     //声明一个返回值为布尔类型的方法
            boolean flag = false;             //声明返回值变量
            if (user.getUserName() == null) {   
                if (!flag) {
                    throw new RegisterException("用户名不能为空,注册失败");    //抛出注册异常
                } else {
                    return true;
                }
            }else if(user.getPassWord().equals(null)){
                return false;
            }
            return true;
        }

// 登录方法
    public static void login(User user) throws LoginFaildException {  
        try {
             boolean register= register(user);    
            
        } catch (RegisterException e) {
            e.printStackTrace();
            throw new LoginFaildException("登录失败",e);    //核心代码,将注册与登录异常抛给登录异常构造方法
        }

    }
    • 在main方法中调用登录方法
public static void main(String[] args) {
        User user = new User();
        try {
            login(user);
        } catch (LoginFaildException e) {
            e.printStackTrace();      //抛出异常
    }
    • 运行结果如下:
exception.RegisterException: 用户名不能为空,注册失败
    at test.Test4.register(Test4.java:23)
    at test.Test4.login(Test4.java:36)
    at test.Test4.main(Test4.java:12)
exception.LoginFaildException: 登录失败
    at test.Test4.login(Test4.java:40)
    at test.Test4.main(Test4.java:12)
Caused by: exception.RegisterException: 用户名不能为空,注册失败
    at test.Test4.register(Test4.java:23)
    at test.Test4.login(Test4.java:36)
    ... 1 more
原文地址:https://www.cnblogs.com/big-data-sky/p/10981726.html