异常的抛出与捕获思路以及异常种类的理解(不谈具体解决办法,明天看其他文章了再说)

异常不处理会怎么办(必须处理,要么抛出,要么捕获,最终必须得 捕获,那么程序才能正常运行,但是有时我们为了,能够发现异常,不捕获,等出现了异常,我们知道了是什么异常,然后做相应的处理,可能是改代码,也可能是其他优化,但是异常最好 log下来,而不是随便的使用 print e.stackTrace )

	1.异常不处理,出现异常,会调用e.printStack(),意味着,不处理异常,我们也能在控制台
	  看到异常日志,即异常类型和异常的堆栈跟踪

异常抛出:

	1.为什么要抛出异常
		1.异常抛出与不处理,出现异常了都会在控制台打印日志,可以定位到异常位置
		
		2.首先异常是必须得处理的,要么抛出,要么捕获,你不处理,那么出现异常了,
		  代表我们程序出现了问题,我们定位到问题,然后排查问题,保证程序正常运行
		  
		3.那抛出异常,代表这里出现的异常,我们不能在这处捕获,当前作用域没有能力处理这一异常的能力
		
			例如:我们写了一个String readFile(String filename) 这个方法
			readFile这个方法可能会在不同的场景下,被不同的代码调用
			那么出现了异常后,我们可能要 用不同的方式处理这个异常
			通俗点说(try catch 里面的内容都不一定是一样的),所以我们在这个方法里面
			将异常捕获了,那么其他调用处,无法在对此异常做针对性处理
		4.当前作用域没有能力处理这一异常的能力的定义:
			其他位置会调用这个方法,并且对这个方法出现的异常做针对性处理
			所以这个方法不能捕获 它 里面出现的异常,得由能处理 它的 调用处 处理
	2.异常的throws,最好能细化异常类型,这样程序员可以知道具体这个方法可能出现什么异常类型
	  但是,这与Exception可以接收所有异常类型么有关系,即使用Exception接收了所有异常,exception
	  打印异常信息的时候,也会调用子类的方法

try catch

	1.什么时候能捕获异常:
		1.当前方法(作用域)有能力处理这一异常
	2.当前方法(作用域)有能力处理这一异常的定义:
		1.当前方法就是最后处理这个异常的 最终位置,其他调用处调用这个方法不会再进行特别的处理
		2.通俗的说:这个方法 try catch里面的异常,就是写死的,没有其他写法了,其他调用处
		  调用这个方法出现异常了,也用这个方法的try catch
		3.try catch要就近捕获:只要这个方法可以做最后的捕获,那么就不要向上抛了,虽然抛了也能处理
		 但是这大大加大了,我们排查异常的难度,可能要debug深入很多次
	3.异常出现,抛了,最后都要捕获的,最重要的不能吞没异常,要log异常信息
	4.try catch的目的:
		1.如果异常改代码无法避免,而且需要执行下面的代码,就用try catch做暂时的捕获

异常的三大信息

	什么出了错?(异常类型)
	在哪出的错?(异常堆栈跟踪)e.printStack 异常的类型和异常的位置
	为什么出错?(异常信息)e.getMessage 异常的类型

mvc框架的自定义 异常处理的原理

	1.出现异常,如果在mvc中有自定义此异常的类型,包括父类型,
	  那么直接将异常throws到controler层调用处,相当于将此调用处 try起来
	  然后 mvc框架里面的 @ExceptionHandler(Exception.class),的方法就是catch处,
	  这样return后,此栈线程到栈底的栈帧退出,线程结束,返回给前台

以下是异常处理细则:

	1.如果你不能处理异常,不要捕获该异常。
	
	2.如果要捕获,应在离异常源近的地方捕获它。
	
	3.不要吞没你捕获的异常。(就是捕获的异常,但是什么也不做)
	4.除非你要重新抛出异常,否则把它log起来。
	
	5.当一个异常被重新包装,然后重新抛出的时候,不要打印statck trace。
	
	6.用自定义的异常类,不要每次需要抛出异常的时候都抛出java.lang.Exception。
	  方法的调用者可以通过throws知道有哪些异常需要处理–所以它是自我描述的。
	
	7.如果你编写业务逻辑,对于终端用户无法修复的错误,系统应该抛出非检查的异常(unchecked exception);
	  如果你编写一个第三方的包给其他的开发人员用,对于不可修复的错误要用需要检查的异常(checked exception)。
	  
	8.绝对不要因为写throws语句会让你用起来不舒服,而不声明需要检查的异常。
	
	9.应用级别的错误或不可修复的系统异常用非检查的异常(unchecked exception)抛出。*(注意是错误,意味着不可修复,比如配置文件错误)
	
	10.根据异常的粒度组织你的方法

首先得明白一个道理,异常只有出现了,才谈解决问题,才谈编译时异常的出现,编译能不能通过,也就是说,如果这段代码可能出现编译时异常,但是最后没有出现,那么编译器照样可以通过,而异常的出现有2种方式,手动抛出,代码出现异常JVM自己抛出,而异常的种类有2种,编译时异常和运行时异常

编译时异常和运行时异常都是异常,异常出现后都是一样的,如果不处理,就会退出jvm,只是,编译时异常只要出现我们必须得处理不处理编译都通不过,并且java提供一个机制,叫预防编译时异常的出现

运行时异常,不用管,编译也可以通过,也就是说,不管是我们手动抛出异常,或者代码可能出错jvm抛出异常,这些我们都可以不用管,java编译器也可以通过

编译时异常和运行时异常都是异常,只是java为了 提前预防,编译时异常(特别严重的异常)的出现,在这个异常出现之前我们就得做相应的处理throws or trycatch(即使是throws了,如果出现了异常,还是得try catch,如果不,那么还是会出现比较严重的异常,预防效果也是没达到的,但是throws了起码编译不会报错,java会认为你起码尝试处理过),那么怎么预防呢,我们之前谈论了,异常的出现只有2种方式,代码出错或手动抛异常,那代码出错我们是无法界定的我们不知道是否会出错,java底层编码人员也不知道,所以他们就采取了一个办法,那就是直接 手动抛处异常(if 可能导致异常出现的因素 存在 例如 if file == null,那么手动抛出异常,如果if file !=null,执行下面的代码,这样,他们总之是 抛出了异常了的,那么编译时异常出现,我们throws了,就可以预防了,这样就达到了我们的目的,不管出不出现编译时异常,我们都相应的抛出了编译时异常,那么既然出现了 编译时异常,那么必须处理(一般 throws),那么这样就达到了预防的效果,编译也能通过了,

结论:
1.只要是可能出现 编译时异常的 地方,java底层人员全部做了,if分支(如果有 引起编译时异常出现的因素)手动抛出异常的处理,那么既然(if 分支手动抛出了 编译时异常),不管最后走不走这条分支(或者说 异常会不会出现),我们都得 处理 编译时异常(因为有一条分支 以及写了 throw new 编译时异常这段代码),一般就是 throws

2.所以一般我们 调用java底层代码,或者其他人写的方法,只要出现了红杠,那么底层一定 有 手动抛出了编译时异常,并且没有 try catch(因为 throws向上抛,只能解决当前方法编译通过,没有真正处理编译时异常,到了上一个栈,还是得处理,不处理,java编译器就当做你没有 处理编译时异常,编译不让你通过)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值