这一篇内容比较长,超过限制了,另附一小段,接上篇。
09-面向对象(自定义异常)
因为项目中会出现特有的问题,而这些问题并未被Java所描述并封装对象。
所以,对于这些特有的问题可以按照Java的对问题封装的思想,将特有的问题,进行自定义的异常封装。这就是自定义异常。
还是以刚刚的程序为例:
![](https://img.haomeiwen.com/i14399848/eac604e3896ddb83.png)
现在自己封装一个异常,注意命名方式都是按规范的来的哦:
![](https://img.haomeiwen.com/i14399848/8ade190704622301.png)
先不用给里面写什么,我们现在建立它的目的只是为了生成对象。
我们自定义的异常,Java不认识,这个时候就需要我们手动建立对象,并进行抛出。(之前都是自动抛出,现在是手动抛出)
注意是throw不是throws哦:
![](https://img.haomeiwen.com/i14399848/164e2015bfee14c2.png)
试一下运行:
![](https://img.haomeiwen.com/i14399848/e8a3292e5e4c3519.png)
一个小技巧:但凡在编译的时候出现这个错误提示的时候,恭喜你,你已经解决到了语法错误的最后环节啦!在编译的时候,它先报的是最基本的语法错误,如果没有语法错误,有异常的问题,它会最后报告。所以,当出现这个问题的时候,说明你的编译问题已经解决到最后了,只要把这个问题解决掉,编译就通过啦!
继续我们的问题。
当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
要么在内部try catch处理,要么在函数上声明让调用者处理。
一般情况下,在函数内出现异常,函数上需要声明。
所以我们声明一下异常:
![](https://img.haomeiwen.com/i14399848/75586738ebf11f93.png)
再运行,继续报错:
![](https://img.haomeiwen.com/i14399848/ec850137c4252ffc.png)
继续写try-catch语句进行处理:
![](https://img.haomeiwen.com/i14399848/25dbb4fbe271412d.png)
给里面传一个负数,运行,成功啦:
![](https://img.haomeiwen.com/i14399848/67b357879e501ac1.png)
我们发现,这个异常木有信息。因为我们没有定义信息哦,刚刚那些Java已经封装好的异常有具体的信息,是因为它们已经定义好信息啦。
那么如何定义异常信息呢?
给自定义的异常添加一下内容:
![](https://img.haomeiwen.com/i14399848/556c1a595b83b787.png)
然后在Demo类中传一个异常信息:
![](https://img.haomeiwen.com/i14399848/204e2c4e840e9f43.png)
编译,运行,这下就有信息了:
![](https://img.haomeiwen.com/i14399848/18a555c1a34219e7.png)
但是我们翻一下手册,发现父类Throwable中已经定义了这些功能啦,把它简单还原一下大概这样:
![](https://img.haomeiwen.com/i14399848/dcc58ab4e9c090e0.png)
我们再看看它的子类Exception:
![](https://img.haomeiwen.com/i14399848/0d314d2b13fd66dc.png)
我们发现,Exception中没有方法。但是它有一个带有String message参数的构造函数。
再次还原一下:
![](https://img.haomeiwen.com/i14399848/f0cae476a00f1c3a.png)
既然父类已经定义了这个方法,子类就不用重新写啦,直接将它传给父类处理就OK啦。
所以,刚刚我们写的那些都很多余,这样写就行啦:
![](https://img.haomeiwen.com/i14399848/2c7b84e02ab703f3.png)
试一试,成功啦:
![](https://img.haomeiwen.com/i14399848/bb423d25d64117bb.png)
因为父类中已经把异常信息的操作都完成了。所以子类只要在构造时,将异常信息通过super语句传递给父类。那么就可以直接通过getMessage方法获取自定义的异常信息。
接下来,我们对于自己定义的问题,想有自己特有的信息,比如,想拿到到底是哪个负数值出现了问题。
这样写:
![](https://img.haomeiwen.com/i14399848/b388edc0051bb0ac.png)
在Demo中将这个错误的b传进去:
![](https://img.haomeiwen.com/i14399848/74cb96ee6e431d85.png)
用catch输出一下b的值:
![](https://img.haomeiwen.com/i14399848/d97c0e8dcea99d16.png)
运行:
![](https://img.haomeiwen.com/i14399848/f502509c4f6c641a.png)
这就是我们的自定义异常。
注意,在自定义异常的时候:
自定义异常类必须继承Exception。
继承Exception的原因:
异常体系有一个特点:异常类和异常对象都需要被抛出。它们都具备可抛性,这个可抛性是Throwable这个体系中的独有特点。只有这个体系中的类和对象才可以被throws和throw操作。不是随便定义一个类就能抛的 。
10-面向对象(throw和throws的区别)
throw和throws的区别:
1,throws使用在函数上,throw使用在函数内。
2,throws后面跟的是异常类,可以跟多个,用逗号隔开。throw后面跟的是异常对象。
什么是函数上?
要写在小括号和大括号之间的这里:
![](https://img.haomeiwen.com/i14399848/4e5707613bb93207.png)
11-面向对象(RuntimeException)
刚刚我们自定义了一个异常,抛出的是我们自定义的内容,现在能不能在这个自定义的异常里面,手动的来抛出一下算数异常呢?
算数异常中有两个构造方法摘要:
![](https://img.haomeiwen.com/i14399848/28a4cead4442328b.png)
我们在Demo中throw一个算数异常对象:
![](https://img.haomeiwen.com/i14399848/323cfca9681c6dd1.png)
编译运行:
![](https://img.haomeiwen.com/i14399848/5d16c4325092f6ab.png)
抛一下Exception试试:
![](https://img.haomeiwen.com/i14399848/a0560dc0a90a417b.png)
编译失败了:
![](https://img.haomeiwen.com/i14399848/e1b864d21c064061.png)
为啥ArithmeticException就没事呢?刚刚不是说函数内抛一定要标识吗?
这是一个非常特殊的地方。
![](https://img.haomeiwen.com/i14399848/95311e3690db813d.png)
ArithmeticException往上看,它有一个父类:RuntimeException,就是这个异常类,它非常的特殊。如果在函数内抛出了,函数上不用声明。
还有一个就是:
![](https://img.haomeiwen.com/i14399848/675fd71bc65f2eba.png)
按理说,声明了一个抛出异常的方法,主函数需要写try-catch语句进行处理,但是现在我们试试主函数什么都不写编译一下,图略,发现编译并没有报错。
Exception中有一个特殊的子类异常:RuntimeException(运行时异常)
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过。
为什么它这么特殊呢?
之所以不用在函数上声明,是因为不需要让调用者处理。当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,由程序员对代码进行修改。
我们看看Runtime都有哪些子类:
![](https://img.haomeiwen.com/i14399848/85711654b30abd21.png)
它里面有很多我们常见的异常,比如空指针异常。
一个空指针异常的例子:
![](https://img.haomeiwen.com/i14399848/d887047e680ef125.png)
name都没有值,根本没办法继续运行,只能让程序停下来,我们修正一下自己的代码,才能让它继续运行。
怎么修正才能避免这种情况的发生呢?
![](https://img.haomeiwen.com/i14399848/974befbcd0e1ccb8.png)
写成这样就好啦。
在上面的例子中,我们并没有抛出异常,最后程序停掉了,我们才能发现了这个问题并修正它呢。
自定义异常时,如果该异常的发生,无法再继续进行运算,就让自定义异常继承RuntimeException。
试一下:
![](https://img.haomeiwen.com/i14399848/4d08a36957f405da.png)
因为没有声明异常,所以注意主函数中也没有处理它哦,运行:
![](https://img.haomeiwen.com/i14399848/8023a646a8db3142.png)
这时候程序停下来了,程序员就会进行对自己的代码进行反思:符合条件的值往进传,不符合条件的值就不传啦。
接着看。
Object类中有一个void wai方法:
![](https://img.haomeiwen.com/i14399848/914b82274a36fecd.png)
这个方法什么作用我们这里先不用管~
我们点进这个方法看一下:
![](https://img.haomeiwen.com/i14399848/3a1275b1989ebc1f.png)
我们发现,这个方法会抛出三个异常,可是我们又发现,在函数声明的时候,只抛出了一个异常:
![](https://img.haomeiwen.com/i14399848/24b4cd6b688c757b.png)
还有两个,它没有声明。因为它们都是RuntimeException的异常。(你敢做这件事情,它就敢让程序停下来,哼!)
所以抛出的异常说明它对程序的影响不大,不抛出的异常对程序运行影响很大,我们必须让程序停下来好好反思一下,修正一下。
所以下回在自定义异常的时候,我们有两种选择:继承RuntimeException,或者继承Exception。
面试的时候也经常会考这里,会问它没有抛出能不能编译通过呀?(不要傻傻说不行哦)
对于异常分两种:
1,编译时被检测的异常。(比如Exception异常,这个时候要抛出,让调用者去处理,因为它是可处理的。而声明的异常,调用者也必须写try-catch语句进行处理,或者进行抛出)
2,编译时不被检测的异常(运行时异常。RuntimeException以及其子类)
所以在自定义异常的时候,我们要考虑,这个问题是否可以被处理,如果可以,就继承Exception异常,让调用者去处理。如果不可以,就继承RuntimeException异常,让程序停下来,我们好好修正。
12-面向对象(异常练习)
接下来,通过一个示例,来讲一下异常的应用。
需求:
![](https://img.haomeiwen.com/i14399848/7f32a610541024d9.png)
Teacher类:
![](https://img.haomeiwen.com/i14399848/a3b95c4a150b9b6e.png)
Computer类:
![](https://img.haomeiwen.com/i14399848/05e1472fd4917d0d.png)
走一遍:
![](https://img.haomeiwen.com/i14399848/b22748457a0d4d0e.png)
![](https://img.haomeiwen.com/i14399848/ff3af49fae6d91f2.png)
接下来开始分析问题。
我们讲课的过程中,会出现各种各样的问题。比如:电脑蓝屏,电脑冒烟。
这个时候对问题进行描述:
1,蓝屏发生后,可以进行处理,所以需要标识出来异常。
![](https://img.haomeiwen.com/i14399848/348d636e44ae46e8.png)
2,冒烟发生后,我们分两种情况分析一下。
先继承Exception。
![](https://img.haomeiwen.com/i14399848/0914d3ec7043d045.png)
我们定义一个值state,如果它为1,表示正常。如果它为其它值,表示出问题了。
![](https://img.haomeiwen.com/i14399848/d2a113f0401ae285.png)
如果蓝屏,我们就让它重启:
![](https://img.haomeiwen.com/i14399848/c8b3f88c986a9e8e.png)
重启就让它的状态恢复到1了,这时候给重启函数中加一句:
![](https://img.haomeiwen.com/i14399848/efe8f51431cd9d92.png)
如果冒烟了,会出现讲课进度无法继续,这个时候,出现了讲师的问题:课时计划无法完成。这时候需要定义一下讲师的异常:
![](https://img.haomeiwen.com/i14399848/e424a14fcba3887e.png)
所以冒烟时,抛出讲师的异常:
![](https://img.haomeiwen.com/i14399848/294f36e07e102828.png)
注意test的调用要放在throw前面哦,放在后面就不会被执行到。(return语句也是这样,放到它后面就不会被执行到了)
主函数中:
![](https://img.haomeiwen.com/i14399848/393f09f40763fa05.png)
编译运行:
![](https://img.haomeiwen.com/i14399848/92bbbf6637febd6b.png)
到这里问题基本解决啦,但还有一个可以完善的地方。换老师或者放假总得有个理由吧,我们改成这样:
![](https://img.haomeiwen.com/i14399848/d8c300273e378ff8.png)
主函数中加一句这个:
![](https://img.haomeiwen.com/i14399848/f3227f84b583f6da.png)
编译运行:
![](https://img.haomeiwen.com/i14399848/a692eca292a874ea.png)
心好累。
网友评论