Java两种异常处理的方式、原理、如何选择

1、异常的两种处理方式

1、异常上抛

在方法声明的位置上,使用throws关键字,抛给上一级

谁调用我,我就抛给谁,抛给上一级。

2、异常捕捉

使用try..catch语句进行异常的捕捉

这件事发生了,谁也不知,因为我给抓住了。

举例:

我是某集团的一个销售员,因为我的失误,导致公司损失了1000块钱。"损失1000块"这可以看做一个异常发生了。我有两种处理方式。

  • 第一种方式:我把这件事告诉我的领导。【异常上抛
  • 第二种方式:我把自己的掏腰包把这个钱补上。【异常的捕捉

同样的异常发生之后,如果选择上抛,抛给了调用者,调用者需要对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式

注意:

Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常的发生,只有只有一个结果。终止java程序的执行。

2、运行时异常编写程序时可以不处理

public class ExceptionTest01 {
	public static void main(String[] args) {
		int a = 10;
		int b = 0;
		int c=a/b;
		/*
		程序执行到此处发生了ArithmeticException异常
		底层new一个ArithmeticException异常对象
		然后抛出了,由于是main方法调用了c=a/b
		所以这个异常ArithmeticException抛给main方法
		main方法没有处理,将这个异常自动抛给JVM
		JVM最终终止程序的执行

		ArithmeticException 继承 RuntimeException,属于运行时异常。
		在编写程序阶段不需要对这种异常进行预先的处理。
		
		*/
		System. out.println(a + "/”+ b + "="+ c);

		//这里的HelloWorld没有输出,没有执行。
		System.out.println("Hello World!");//
	}
}

3、方法声明上使用throws

以下代码报错的原因是什么?

因为doSome()方法声明位置上使用了:throws ClassNotFoundException
而ClassNotFoundException是编译时异常。必须编写代码时处理,没有处理编译器报错。

public class ExceptionText1 {
    public static void main(String[] args) {
        //main方法中调用doSome()方法
        //因为doSome()方法声明位置上有:throws ClassNotFoundException
        //我们在调用doSome()方法的时候必须对这种异常进行预先的处理。
        //如果不处理,编译器就报错
        //报错信息: 未报告的异常错误java.lang.ClassNotFoundException
        doSome();
    }

    /**
     * doSome方法在方法声明的位置上使用了:throws ClassNotFoundException
     * 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常。
     * 叫做类没找到异常。这个异常直接父类是: Exception,所以ClassNotFoundException属于编译异常。
     * @throws ClassNotFoundException
     */
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!");
    }
}

在这里插入图片描述

4、异常处理的具体方式

第一种处理方式:在方法声明的位置上继续使用:throws,来完成异常的继续上抛。抛给调用者
上抛类似于推卸责任。(继续把异常传递给调用者)
这种处理异常的态度:上报

public class ExceptionText1 {
    public static void main(String[] args) throws ClassNotFoundException {
        doSome();
    }

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

第二种方式:try ... catch进行异常捕捉
捕捉等于把异常拦下了,异常真正的解决了。(调用者不知道的)

public class ExceptionText1 {
    public static void main(String[] args) throws ClassNotFoundException {
        try {
        //尝试
        	doSome();
        }catch (ClassNotFoundException e){
        //catch是捕捉异常之后走的分支
			e.printStackTrace;
		}
    }

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

一般不建议在main方法上使用throws,因为这个异常如果真正发生了,一定会抛给JVM。JVM只有终止。一般采用try...catch进行捕捉。

5、异常捕捉和上报的联合使用

import java.io.FileInputStream;

public class ExceptionText2 {
    public static void main(String[] args) {
        System.out.println("main begin ");
        m1();
        System.out.println("main over");
    }

    private static void m1(){
        System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }

    private static void m2(){
        System.out.println("m2 begin");
        m3();
        System.out.println("m3 over");
    }
    private static void m3(){
        //调用SUN jdk中某个类的构造方法
        //这个类是IO流的
        //创建一个输入流对象,该流指向一个文件。
        new FileInputStream("C:\\Users\\Administrator\\Desktop\\Java自学\\学习.txt");
    }
}

在这里插入图片描述
编译报错的原因:

  • 第一:这里调用了一个构造方法:FileInputStream(String name)
  • 第二:这个构造方法的声明位置上有:throws FileNotFoundException
  • 第三:通过类的继承结构看到:FileNotFoundException父类是IOException,IOException的父类是Exception。

最终得知,FileNotFoundException是编译时异常。编译时异常要求程序员编写阶段必须对它进行处理,不处理编译器就报错

进行异常处理后

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ExceptionText2 {
    public static void main(String[] args) {
        System.out.println("main begin ");
        m1();
        System.out.println("main over");
    }

    private static void m1(){
        System.out.println("m1 begin");
        try {
            m2();
        } catch (FileNotFoundException e) {
        //这个分支中可以使用e引用,e引用保存的内存地址是new出来异常对象的内存地址
        //catch是捕捉异常之后走的分支
            System.out.println("文件不存在,可能路径错误,也可能文件被删除了!");
        }
        System.out.println("m1 over");
    }

   //也可以    throws Exception
    private static void m2() throws FileNotFoundException {
        System.out.println("m2 begin");
        //编译器报错的原因是:m3()方法声明位置上有:throws FileNotFoundException
        //我们这里调用m3()没有对异常进行预处理,所以编译报错
        m3();
        System.out.println("m3 over");
    }
    private static void m3() throws FileNotFoundException {
        //调用SUN jdk中某个类的构造方法
        //这个类是IO流的
        //创建一个输入流对象,该流指向一个文件。
        new FileInputStream("C:\\Users\\Administrator\\Desktop\\Java自学\\学习.txt");
    }
}

上抛异常也可以 throws Exception

注意:只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。
另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行。

6、上报和捕捉怎么选择?

  • 如果希望调用者来处理,选择throws上报。
  • 其他情况可以使用捕捉的方式
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值