难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJ IDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.throw抛出一个异常
在上一章《“全栈2019”Java异常第八章:throw关键字详解》中我们学会了使用throw关键字抛出一个异常。
当你使用了throw关键字之后,即意味着此处抛出了一个异常,那么,对于throw抛出的异常处理方式有两种:
第一种,使用try-catch捕获异常:
![918b75e969e175c6539b33cc889ea03b.png](https://i-blog.csdnimg.cn/blog_migrate/78e6b188f9663a160a9ff876cab7837c.jpeg)
第二种,使用throws关键字将其声明在方法上,让调用者去处理:
![a7a0154f957dbdb1373a85edf836a981.png](https://i-blog.csdnimg.cn/blog_migrate/5ddde093f4ac0690cf9c0f735e69faa6.jpeg)
throws关键字就是本章的内容。兄弟们,接下来就让我们开始认识throws关键字。
2.什么是throws关键字?
throws关键字用于声明在当前定义的成员方法中所有需要抛出的异常。
下面我们分词来看throws的定义。
第一个词,声明:
“throws关键字用于声明在当前定义的成员方法中所有需要抛出的异常。”
声明就是告诉的意思,告诉谁呢?告诉调用者,谁调用我这个方法,谁就处理我声明的异常。
换言之就是,“喂,调用我方法的人,我告诉你,你调用我这个方法时,我方法里面有可能会产生异常,我不方便处理,你处理更合适,你记得处理一下。”
第二个词,成员方法:
“throws关键字用于声明在当前定义的成员方法中所有需要抛出的异常。”
成员方法只可能出现在类(抽象类也是类)和接口中。
好,这就好办了,也就是说我们throws关键字只可能用在类和接口中的方法上。讲道理,是这么个意思。
下面我们来演示看看。
类:
![2cd354375a160cbc9eef0153b2f4f111.png](https://i-blog.csdnimg.cn/blog_migrate/e426cd8d483914a3d82b0811bd65c833.jpeg)
接口:
![0d5044c22d3dea91df3a4a66d3fca2a4.png](https://i-blog.csdnimg.cn/blog_migrate/e030862067e0f9377c5e8dc31f751c98.jpeg)
第三个词,需要抛出的异常:
“throws关键字用于声明在当前定义的成员方法中所有需要抛出的异常。”
需求抛出的异常你就抛,不需要抛出的异常你就别抛。
这个需要结合例子来说明,并且呢这个例子在之前文章里面出现过,有详细讲解,如果需要回顾的同学请点击下面文章来进行查看:
《“全栈2019”Java异常第五章:一定会被执行的finally代码块》
温馨提示:
例子有点长,请耐心看完,谢谢!
![c29f47c236a539b08231ba838007a613.png](https://i-blog.csdnimg.cn/blog_migrate/8cbc80ff6053f0bf1b9e43cb18355f74.jpeg)
代码看起来很多,但是一点都不难,下面我们一步一步来分析看看。
首先,我们先来看看目标方法printTxtContent(英文翻译过来就是“打印txt文本内容”):
![17cbb56ba3bfa7f6193338562b1c4d6c.png](https://i-blog.csdnimg.cn/blog_migrate/711931bd7b1a5b3ab9d0513d1f6884a8.jpeg)
不要看它里面代码很多,其实很简单,方法接收一个txt文本文件的路径:
![04ab710963c3a3513882bfc608a61e72.png](https://i-blog.csdnimg.cn/blog_migrate/28ea3d611a8ee366cb6d76c78c75fe93.jpeg)
然后声明一个FileReader对象,用来读取文件的:
![c3987f9f4c073dbd185d54bdec751f65.png](https://i-blog.csdnimg.cn/blog_migrate/0be8cff76d1c224553ad50fa0aef7fc3.jpeg)
将FileReader对象单独声明在最上面,是因为它需要在finally代码块里面进行关流操作:
![45680ed17abe60deea668cce6de59cf8.png](https://i-blog.csdnimg.cn/blog_migrate/b0aab887d2cb435d257cea05f0d0e683.jpeg)
我们使用了try-catch对有可能产生的异常进行处理:
![e6cd21ea29f2bf5afb95e815eab7dce7.png](https://i-blog.csdnimg.cn/blog_migrate/84b3e35caf0ce4ad06632261b8538b26.jpeg)
try代码块里面开始对FileReader对象进行初始化:
![ef550571c670702dab185e373c6fb8c5.png](https://i-blog.csdnimg.cn/blog_migrate/7946676c413d2357b22feae16144781e.jpeg)
创建FileReader的时候有可能产生找不到文件异常FileNotFoundException,我们对其进行catch操作:
![035fe803b5f6bede8e1fd6205278e853.png](https://i-blog.csdnimg.cn/blog_migrate/a262589edb186be26a4a900bd82ab2a2.jpeg)
继续,往下来,是对文件进行遍历读取:
![4e3925ed6ac452389b50ac62c3784de2.png](https://i-blog.csdnimg.cn/blog_migrate/b7df57298fbf8e1e97214f3ab1b3cd6e.jpeg)
具体读取操作是调用其FileReader的read()方法:
![d4948998b8bc0f3d35534f5ca3d82819.png](https://i-blog.csdnimg.cn/blog_migrate/f774b9d7e95a4eac193de4a2c8bff73c.jpeg)
但是,在读取的过程中有可能产生IOException,我们将其执行catch操作:
![b98e24ed2f0a6efa9884778ca07838f9.png](https://i-blog.csdnimg.cn/blog_migrate/3bd263e4bfe522ec5d9b843560ee55f8.jpeg)
再接下来就是判断是否文本文件已经读取完毕,根据当前字符值是否为-1来判断:
![497449d90d9c5bec0582701d9361b485.png](https://i-blog.csdnimg.cn/blog_migrate/5438fb0857811fcfcbd3d86a44c01898.jpeg)
好了,最后就是打印字符:
![b57b99b4283ede402ba3de1818930a31.png](https://i-blog.csdnimg.cn/blog_migrate/365bad1905a88d296d5b1e6c4c6e4b6e.jpeg)
至此,方法是写好了,再来看看调用者,我们在main()方法中调用了printTxtContent()方法:
![cf990fb7979f58cc0479cd64335aa91f.png](https://i-blog.csdnimg.cn/blog_migrate/756ad81b5cfdcc7d66d8ac76598d8819.jpeg)
传入了文本文件路径:
![265b9979f46dd1692479137a267ca601.png](https://i-blog.csdnimg.cn/blog_migrate/ceb0992c944fdde4293be83605bdc5b3.jpeg)
好,整个程序代码讲解了一遍,如果有地方我没有讲解清楚的地方,请大家在评论区留言。
接下来,进入正题,上面这个例子整个程序代码写得有问题吗?
有问题。
哪里有问题?
该抛出的异常,没有抛出。在printTxtContent()方法里面的第29行。该行代码执行的是初始化FileReader对象,同时会产生一个找不到文件异常FileNotFoundException。
这里有什么问题?
上述异常该抛出,应告知调用者,而不是自行处理。
为什么呢?
因为调用者传给你的文件路径有可能是不存在的或者写错了,这个错误应该告诉我,而不是你自己处理了,更何况你不知道怎么处理,而调用者知道。
好,根据上述描述来更改程序代码:
![6a78aa696faed18c3decb527e45fad9a.png](https://i-blog.csdnimg.cn/blog_migrate/07823ac1fbf0ed55a95c585180fadd22.jpeg)
我们有三处改动,第一处是创建FileReader对象:
![c1bf1fb6734c4594f1bfdf898a6a96f5.png](https://i-blog.csdnimg.cn/blog_migrate/e1d949826ac79027c36bc5a4f5375740.jpeg)
第二处是声明FileNotFoundException:
![adda41febc72611457cc41d6ed2cc3a7.png](https://i-blog.csdnimg.cn/blog_migrate/5dfffaa4a620919c2fcef8ae355b4f72.jpeg)
第三处是调用者处理FileNotFoundException:
![f46addc827689b9cacfb97bde023eaed.png](https://i-blog.csdnimg.cn/blog_migrate/2ed43ca1e1ff22e27052c950ac6fbe08.jpeg)
另外,我们可以看到catch只剩下一个,原来是有两个:
![00c03b665f32c23f418ec72196591ed7.png](https://i-blog.csdnimg.cn/blog_migrate/f5d50c488f85ee5a2fec9f7eac3b1069.jpeg)
而且finally里面FileReader对象也不用判断是否为Null:
![3b4c2e67da64e6f033f7ef062b78f653.png](https://i-blog.csdnimg.cn/blog_migrate/d57cb4a2f000927aeb7fe51d1f8081b3.jpeg)
至此,我们将需要抛出的异常声明在方法上了,那么不需要抛出异常就别抛出了,也别声明在方法上,比如下面这两处产生的IOException:
![09826859235cffedb3b6d61291497751.png](https://i-blog.csdnimg.cn/blog_migrate/3c0634011f1358da2a280d4b61efe5a8.jpeg)
这两处产生的异常只能自行处理,因为你抛出去,调用者也不知道该如何处理,所以大家在写方法时,特别是方法内产生异常时,一定要考虑什么异常该抛,什么异常不该抛。
3.throws关键字用在何处?
throws关键字用在方法上:
![cedb8721175b896ee5ac37112d1f81be.png](https://i-blog.csdnimg.cn/blog_migrate/fefa02ec4764692b870c4d124c313487.jpeg)
上节例子已经描述的很清楚了,这里就不再赘述。
4.为什么要使用throws关键字?
当我们遇到一些不知如何处理的异常,但调用方法的人知道怎么处理时,我们就可以将异常在方法上声明此异常。
![e8d713db54a140c46eb5782888810228.png](https://i-blog.csdnimg.cn/blog_migrate/778e78f0e6bfc071ea1132e6a1358dd2.jpeg)
5.什么时候使用throws关键字?
当我们遇到自己不知怎么处理的异常或需要调用者处理的时候,则可以使用throws关键字将其在方法上声明出去。
6.怎么使用throws关键字?
throws关键字跟在方法参数列表的后面,方法左大括号的前面。
throws关键字后面跟的是异常类型。
![4410fce094aa1e804839b0d2dfd3943e.png](https://i-blog.csdnimg.cn/blog_migrate/470b945932d42343bc2d0df4339b7bf9.jpeg)
注意:
throw后面跟的是new关键字和异常对象。
![92430492f2e1c2f0e85f710e8fd2fdce.png](https://i-blog.csdnimg.cn/blog_migrate/fcb9fa13227eb4372619a65c483a0497.jpeg)
throws后面跟的是异常类型。
![a5bf00489bcf0c9aefb68682c5eeede2.png](https://i-blog.csdnimg.cn/blog_migrate/f8c99a9e4c92fd05e30035e0d06223c7.jpeg)
它们是不同的,千万别搞错了。一个是对象,一个类型。
7.非运行时异常与运行时异常
上一章讲解过什么是非运行异常和运行时异常,这里就直接拿出结论。
什么是非运行时异常?
继承自Exception的异常。
什么是运行时异常?
继承自RuntimeException的异常。
RuntimeException和Exception之间有什么关系?
RuntimeException是Exception的子类。
抛出一个非运行时异常有什么特点?
当我们抛出一个非运行时异常时,我们要么对其try-catch,要么使用throws声明出去。(上面几个小节已经演示的很清楚了)
抛出一个运行时异常有什么特点?
当我们抛出一个运行时异常时,我们可以不对其try-catch,也不必使用thorws声明出去。
从上一章我们了解到算术异常ArithmeticException是一个运行时异常。这里我们来演示一下使用throws声明此异常。
演示:
请抛出一个算术异常ArithmeticException。
请观察程序运行结果。
代码:
Main类:
![b2320689fedad1062c5b4da34d07a1d9.png](https://i-blog.csdnimg.cn/blog_migrate/4ab08479d7e377e751e0454ad6e2a56a.jpeg)
结果:
![1fe3d559f6aefef3312f9ef6511dc2d6.png](https://i-blog.csdnimg.cn/blog_migrate/47fe7778a1f63846f016054f3b13398f.jpeg)
从运行结果来看,结果是我们想要的,这里程序没有写错。
程序演示了运行时异常不必try-catch和throws。我们明明知道这里有可能发生异常,编译器却没有提醒我们对其try-catch或thorws,仍然编译通过,因为它是一个运行时异常,不强制你try-catch或thorws。
总结
- throws关键字用于声明在当前定义的成员方法中所有需要抛出的异常。
至此,Java中throws关键字相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
“全栈2019”Java异常第八章:throw关键字详解
下一章
“全栈2019”Java异常第十章:throw与throws区别详解
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
![32d3e012238b62ece7de8dca2602a056.png](https://i-blog.csdnimg.cn/blog_migrate/01752b2f2832604bce055553e3886547.jpeg)
版权声明
原创不易,未经允许不得转载!