zoukankan      html  css  js  c++  java
  • Java入门系列-20-异常

    为什么要进行异常处理

    下面这段代码能否正常执行

    public class DemoCalc {
    	public static void main(String[] args) {
    		int a=0;
    		int b=0;
    		int c=a/b;
    		System.out.println("运算结果为:"+c);
    	}
    }
    

    结果是我们在控制台中看到一段错误提示,那是因为除数不能为0。异常就是在程序运行过程中发生的不正常事件,会中断运行的程序

    Java 使用了异常处理机制为程序提供了错误处理的能力,在程序中预先设置好对付异常的处理办法,待程序发生异常时对异常进行处理,处理完毕后,程序便可以继续运行。

    下面来看一下Java中是如何进行异常处理的

    如何进行异常处理

    Java 的异常处理是通过5个关键字实现的:try、catch、finally、throw、throws

    关键字 作用
    try 执行可能产生异常的代码
    catch 捕获异常
    finally 无论是否发生异常,代码总能执行
    throws 声明方法要抛出的异常
    throw 手动抛出异常

    常见异常及异常分类

    Throwable 是Java 中所有错误和异常的父类

    Error类:Throwable的子类,仅靠程序本身无法恢复的严重的错误。

    Exception类:Throwable的子类,由Java应用程序抛出和处理的非严重错误

    RuntimeException类:Exception的子类,运行时异常,不要求程序必须做出处理。

    Checked异常:Exception的子类,程序必须处理该类异常。

    常见异常类型

    异常类型 说明
    Exception 异常层次结构的父类
    ArithmeticException 算数错误情形,如以零作除数
    ArrayIndexOutOfBoundsException 数组下标越界
    NullPointerException 尝试访问null对象成员
    ClassNotFoundException 不能加载所需的类
    IllegalArgumentException 方法接收到非法参数
    ClassCastException 对象强制类型转换出错
    NumberFormatException 数字格式转换异常,如把"abc"转换成数字

    try-catch

    语法:

    public void method(){
        try{
            //代码段1
            //可能产生异常的代码段
            //代码段2
        }catch(异常类型 ex){
            //对异常进行处理的代码段
        }
        //代码段
    }
    

    try-catch块捕获异常有三种情况:

    1、try块中没有任何异常,try中正常,catch不会执行,正常执行try-catch后的代码。

    2、try块中可能发生异常的代码段发生异常,代码段2不会执行,而是执行catch中异常处理的代码,正常执行try-catch后的代码。

    catch中异常类型的printStackTrace() 方法能进行堆栈跟踪显示出程序运行到当前类的执行流程,异常堆栈信息中包含了异常的类型及异常出现的位置。

    3、异常类型不匹配,程序将中断。比如try产生的异常为ArithmeticException,catch却用了 ClassCastException。

    在控制台中接收数字做除法运算

    import java.util.Scanner;
    
    public class DemoInput {
    	public static void main(String[] args) {
    		Scanner input=new Scanner(System.in);
    		try{
    			System.out.println("请输入被除数(整数):");
    			int a=input.nextInt();
    			System.out.println("请输入除数(整数):");
    			int b=input.nextInt();
    			int c=a/b;
    			System.out.println("结果:"+c);
    		}catch(Exception ex) {
    			ex.printStackTrace();
    		}
    		System.out.println("程序结束");
    	}
    }
    

    try-catch-finally

    语法:

    public void method(){
        try{
            //可能会发生异常的代码
        }catch(异常类型 ex){
            //异常处理
        }finally{
            //无论如何都要执行的代码
        }
    }
    

    finally块:是否发生异常都执行

    finllay块不执行的唯一情况:之前的代码中执行了 System.exit(1); 退出虚拟机

    try-catch-finally的使用

    import java.io.FileNotFoundException;
    import java.util.Scanner;
    
    public class DemoInput {
    	public static void main(String[] args) {
    		Scanner input=new Scanner(System.in);
    		try{
    			System.out.println("请输入被除数(整数):");
    			int a=input.nextInt();
    			System.out.println("请输入除数(整数):");
    			int b=input.nextInt();
    			int c=a/b;
    			System.out.println("结果:"+c);
    		}catch(Exception ex) {
    			ex.printStackTrace();
    		}finally {
    			System.out.println("感谢您的使用");
    		}
    		System.out.println("程序结束");
    	}
    }
    

    如果在try块或catch块中有return语句,finally是否还会执行?运行下面代码断点调试观察结果。

    public class TestReturn {
    
    	public static void main(String[] args) {
    		try {
    			int a=1+1;
    			System.out.println("try执行");
    			return;
    		} catch (Exception e) {
    			System.out.println("catch执行");
    		}finally {
    			System.out.println("finally执行");
    		}
    	}
    }
    

    try块或catch块中可以有return语句,如果有return语句会先执行finally最后再执行return。

    多重catch

    try块中可能会发生多种异常,如果要不同的异常进行不同的处理,需要使用多重catch进行处理。

    语法:

    public void method(){
        try{
            //可能发生异常的代码段
        }catch(异常类型1 e){
            //对异常类型1进行的处理的代码段
        }catch(异常类型2 e){
            //对异常类型2进行的处理的代码段
        }catch(异常类型n e){
            //对异常类型n进行的处理的代码段
        }
    }
    

    当try块中发生异常后,会逐个与catch中的异常类型进行匹配,匹配成功后,进入对应的catch进行异常处理,处理完成后不再进入其他catch,程序继续执行。

    排列catch语句的顺序是:先子类后父类

    发生异常时按顺序逐个匹配

    只执行第一个与异常类型匹配的catch语句

    将之前的代码 DemoInput.java 改造成多重catch

    import java.io.FileNotFoundException;
    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class DemoInput {
    	public static void main(String[] args) {
    		Scanner input=new Scanner(System.in);
    		try{
    			System.out.println("请输入被除数(整数):");
    			int a=input.nextInt();
    			System.out.println("请输入除数(整数):");
    			int b=input.nextInt();
    			int c=a/b;
    			System.out.println("结果:"+c);
    		}catch(InputMismatchException e) {
    			System.out.println("输入的数有误!");
    		}catch(ArithmeticException e) {
    			System.out.println("除数不能为0");
    		}catch(Exception ex) {
    			System.out.println("发生未知异常");
    		}finally {
    			System.out.println("感谢您的使用");
    		}
    		System.out.println("程序结束");
    	}
    }
    

    声明异常 throws

    如果一个方法体内抛出了异常如何通知调用者,可以在方法上声明异常。

    
    public class TestThrows {
    	
    	//声明异常,多个异常可以用逗号隔开
    	public void test()throws Exception,ClassNotFoundException{
    		//可能会发生异常的代码
    	}
    }
    

    处理方式一:调用者处理异常

    public static void main(String[] args) {
    	TestThrows t=new TestThrows();
    	try {
    		t.test();
    	} catch (ClassNotFoundException e) {
    		e.printStackTrace();
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }
    

    处理方式二:调用者继续声明异常

    public static void main(String[] args) throws ClassNotFoundException, Exception {
    	TestThrows t=new TestThrows();
    	t.test();
    }
    

    main方法继续声明异常,调用者就变成虚拟机了,发生异常则按默认方式处理,打印出来。

    抛出异常 throw

    除了系统自动抛出的异常外,有些问题需要程序员自行抛出异常

    public class TestThrow {
    	public void inputAge(int age) throws Exception {
    		if (age<1) {
    			throw new Exception("还有这种年龄?");
    		}
    	}
    	
    	public static void main(String[] args) {
    		TestThrow t=new TestThrow();
    		try {
    			t.inputAge(-1);
    		} catch (Exception e) {
    			System.out.println("年龄有误:"+e.getMessage());
    		}
    	}
    }
    

    自行抛出异常后,还需要在方法上声明异常

  • 相关阅读:
    (1)java设计模式之简单工厂模式
    QuartZ Cron表达式在java定时框架中的应用
    java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得
    https实现安全传输的流程
    liunx上运行mybase
    liux之sed用法
    java并发之CyclicBarrier
    java并发之Semaphore
    关于ConcurrentSkipListMap的理解
    java中Iterator和ListIterator的区别与联系
  • 原文地址:https://www.cnblogs.com/AIThink/p/9846642.html
Copyright © 2011-2022 走看看