1.public class Test {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) {
4. //实现一个功能:键盘录入两个数,求商:
5. Scanner sc = new Scanner(System.in);
6. System.out.println("请录入第一个数:");
7. int num1 = sc.nextInt();
8. System.out.println("请录入第二个数:");
9. int num2 = sc.nextInt();
10. System.out.println("商:"+num1/num2);
11.
12. }
13.}
运行结果:
测试过程发现问题:
录入的数据应为int类型,但是录入非int类型数据的时候,出异常:
除数为0的时候:
异常:Exception:在程序的运行过程中,发生了不正常的现象,阻止了程序的运行,我们称之为发生异常。
1.package com.msb.test01;
2.
3.import java.util.Scanner;
4.
5./**
6. * @Auther: msb-zhaoss
7. */
8.public class Test {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) {
11. //实现一个功能:键盘录入两个数,求商:
12. Scanner sc = new Scanner(System.in);
13. System.out.println("请录入第一个数:");
14. if(sc.hasNextInt()){
15. int num1 = sc.nextInt();
16. System.out.println("请录入第二个数:");
17. if(sc.hasNextInt()){
18. int num2 = sc.nextInt();
19. if(num2 == 0){
20. System.out.println("对不起,除数不能为0");
21. }else{
22. System.out.println("商:"+num1/num2);
23. }
24. }else{
25. System.out.println("对不起,你录入的不是int类型的数据!");
26. }
27. }else{
28. System.out.println("对不起,你录入的不是int类型的数据!");
29. }
30. }
31.}
用if-else堵漏洞的缺点:
(1)代码臃肿,业务代码和处理异常的代码混在一起。
(2)可读性差
(3)程序员需要花费大量的经历来维护这个漏洞
(4)程序员很难堵住所有的漏洞。
【1】基于if-else处理异常缺点太多,所以java中专门出了一个异常处理机制:
“异常三连” try-catch-finally
【2】异常出现了以后怎么看:
【3】捕获异常: try-catch
对应代码:
1.public class Test2 {
2. public static void main(String[] args) {
3. //实现一个功能:键盘录入两个数,求商:
4. try{
5. Scanner sc = new Scanner(System.in);
6. System.out.println("请录入第一个数:");
7. int num1 = sc.nextInt();
8. System.out.println("请录入第二个数:");
9. int num2 = sc.nextInt();
10. System.out.println("商:"+num1/num2);
11. }catch(Exception ex){
12. System.out.println("对不起,程序出现异常!");
13. }
14.
15. System.out.println("----谢谢你使用计算器111");
16. System.out.println("----谢谢你使用计算器222");
17. System.out.println("----谢谢你使用计算器333");
18. System.out.println("----谢谢你使用计算器444");
19. System.out.println("----谢谢你使用计算器555");
20. System.out.println("----谢谢你使用计算器666");
21. }
22.}
原理:
把可能出现异常的代码放入try代码块中,然后将异常封装为对象,被catch后面的()中的那个异常对象接收,接收以后:执行catch后面的{}里面的代码,然后try-catch后面的代码,该怎么执行就怎么执行。
详细说一下:
(1)try中没有异常,catch中代码不执行。
(2)try中有异常,catch进行捕获:
如果catch中异常类型和你出的异常类型匹配的话:走catch中的代码--》进行捕获
如果catch中异常类型和你出的异常类型不匹配的话:不走catch中的代码--》没有捕获成功,程序相当于遇到异常了,中断了,后续代码不执行
注意:
(1)try中如果出现异常,然后用catch捕获成功的话,那么try中后续的代码是不会执行的。
(2)如果catch捕获异常成功,那么try-catch后面的代码该执行还是执行没有影响。
1.package com.msb.test01;
2.
3.import java.util.Scanner;
4.
5./**
6. * @Auther: msb-zhaoss
7. */
8.public class Test3 {
9. public static void main(String[] args) {
10. //实现一个功能:键盘录入两个数,求商:
11. try{
12. Scanner sc = new Scanner(System.in);
13. System.out.println("请录入第一个数:");
14. int num1 = sc.nextInt();
15. System.out.println("请录入第二个数:");
16. int num2 = sc.nextInt();
17. System.out.println("商:"+num1/num2);
18. }catch(Exception ex){
19. //第一种处理:什么都不写,什么都不做
20.
21. //第二种处理:输出自定义异常信息
22. //System.out.println("对不起,你的代码有问题!");
23.
24. //第三种处理:打印异常信息:
25. /*(1)调用toString方法,显示异常的类名(全限定路径)*/
26. /*System.out.println(ex);
27. System.out.println(ex.toString());*/
28. /*(2)显示异常描述信息对应的字符串,如果没有就显示null
29. System.out.println(ex.getMessage());*/
30. /*(3)显示异常的堆栈信息:将异常信息捕获以后,在控制台将异常的效果给我们展示出来,方便我们查看异常*/
31. /* ex.printStackTrace();*/
32.
33. //第四种处理:抛出异常:
34. throw ex;
35. }
36.
37. System.out.println("----谢谢你使用计算器111");
38. }
39.}
【1】在什么情况下,try-catch后面的代码不执行?
(1)throw抛出异常的情况
(2)catch中没有正常的进行异常捕获
(3)在try中遇到return
【2】怎么样才可以将 try-catch后面的代码 必须执行?
只要将必须执行的代码放入finally中,那么这个代码无论如何一定执行。
【3】return和finally执行顺序?
先执行finally最后执行return
【4】什么代码会放在finally中呢?
关闭数据库资源,关闭IO流资源,关闭socket资源。
【5】有一句话代码很厉害,它可以让finally中代码不执行!
System.exit(0);//终止当前的虚拟机执行
1.package com.msb.test01;
2.
3.import java.util.Scanner;
4.
5./**
6. * @Auther: msb-zhaoss
7. */
8.public class Test3 {
9. public static void main(String[] args) {
10. //实现一个功能:键盘录入两个数,求商:
11. try{
12. Scanner sc = new Scanner(System.in);
13. System.out.println("请录入第一个数:");
14. int num1 = sc.nextInt();
15. System.out.println("请录入第二个数:");
16. int num2 = sc.nextInt();
17. System.out.println("商:"+num1/num2);
18. System.exit(0);//终止当前的虚拟机执行
19. return;
20. }catch(ArithmeticException ex){
21. //throw ex;
22. }finally {
23. System.out.println("----谢谢你使用计算器111");
24. }
25.
26.
27. }
28.}
【1】try中出现异常以后,将异常类型跟catch后面的类型依次比较,按照代码的顺序进行比对,执行第一个与异常类型匹配的catch语句
【2】一旦执行其中一条catch语句之后,后面的catch语句就会被忽略了!
【3】在安排catch语句的顺序的时候,一般会将特殊异常放在前面(并列),一般化的异常放在后面。
先写子类异常,再写父类异常。
【4】在JDK1.7以后,异常新处理方式:可以并列用|符号连接:
1.package com.msb.test01;
2.
3.import java.util.InputMismatchException;
4.import java.util.Scanner;
5.
6./**
7. * @Auther: msb-zhaoss
8. */
9.public class Test4 {
10. public static void main(String[] args) {
11. Integer
12. //实现一个功能:键盘录入两个数,求商:
13. try{
14. Scanner sc = new Scanner(System.in);
15. System.out.println("请录入第一个数:");
16. int num1 = sc.nextInt();
17. System.out.println("请录入第二个数:");
18. int num2 = sc.nextInt();
19. System.out.println("商:"+num1/num2);
20. }catch(ArithmeticException ex){
21. System.out.println("对不起,除数不可以为0");
22. }catch(InputMismatchException ex){
23. System.out.println("对不起,你录入的数据不是int类型的数据");
24. }catch(Exception ex){
25. System.out.println("对不起,你的程序出现异常");
26. }finally {
27. System.out.println("----谢谢你使用计算器111");
28. }
29. }
30.}
注意:程序中语法错误,逻辑错误 都不属于上面的Error,Exception
【2】运行时异常:
1.public class Test5 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) {
4. //运行时异常:
5. int[] arr = {1,2,3};
6. System.out.println(arr.length);
7. /*int[] arr2 = null;
8. System.out.println(arr2.length);*/
9. System.out.println(arr[10]);
10. }
11.}
【3】检查异常:
处理方式1:try-catch嵌套try-catch
1.public class Test6 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) {
4. //检查异常:
5. try {
6. try {
7. Class.forName("com.msb.test01.Test").newInstance();
8. } catch (InstantiationException e) {
9. e.printStackTrace();
10. } catch (IllegalAccessException e) {
11. e.printStackTrace();
12. }
13. } catch (ClassNotFoundException e) {
14. e.printStackTrace();
15. }
16. }
17.}
处理方式2:多重catch
1.public class Test6 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) {
4. //检查异常:
5. try {
6. Class.forName("com.msb.test01.Test").newInstance();
7. } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
8. e.printStackTrace();
9. }
10. }
11.}
处理方式3:throws
1.public class Test6 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
4. //检查异常:
5. Class.forName("com.msb.test01.Test").newInstance();
6. }
7.}
1.package com.msb.test01;
2.
3.import java.util.Scanner;
4.
5./**
6. * @Auther: msb-zhaoss
7. */
8.public class Test7 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws Exception {
11. //实现一个功能:两个数相除,当除数为0的时候,程序出现异常。
12. /*try {
13. devide();
14. } catch (Exception e) {
15. e.printStackTrace();
16. }*/
17. devide();
18. }
19. public static void devide() throws Exception {
20. Scanner sc = new Scanner(System.in);
21. System.out.println("请录入第一个数:");
22. int num1 = sc.nextInt();
23. System.out.println("请录入第二个数:");
24. int num2 = sc.nextInt();
25. if(num2 == 0 ){//除数为0 ,制造异常。
26. //制造运行时异常:
27. /*throw new RuntimeException();*/
28. //制造检查异常:
29. /*try {
30. throw new Exception();
31. } catch (Exception e) {
32. e.printStackTrace();
33. }*/
34. throw new Exception();
35. }else{
36. System.out.println("商:"+num1/num2);
37. }
38. }
39.}
总结:
throw和throws的区别:
(1)位置不同:
throw:方法内部
throws: 方法的签名处,方法的声明处
(2)内容不同:
throw+异常对象(检查异常,运行时异常)
throws+异常的类型(可以多个类型,用,拼接)
(3)作用不同:
throw:异常出现的源头,制造异常。
throws:在方法的声明处,告诉方法的调用者,这个方法中可能会出现我声明的这些异常。然后调用者对这个异常进行处理:
要么自己处理要么再继续向外抛出异常
1.package com.msb.test02;
2.
3./**
4. * @Auther: msb-zhaoss
5. */
6.public class Student {
7. private String name;
8. private int age;
9. private String sex;
10.
11. public String getName() {
12. return name;
13. }
14.
15. public void setName(String name) {
16. this.name = name;
17. }
18.
19. public int getAge() {
20. return age;
21. }
22.
23. public void setAge(int age) {
24. this.age = age;
25. }
26.
27. public String getSex() {
28. return sex;
29. }
30.
31. public void setSex(String sex) throws Exception {
32. if(sex.equals("男")||sex.equals("女")){
33. this.sex = sex;
34. }else{//非男非女
35. //解决办法1:
36. /*this.sex = "男";*/
37. //解决办法2:给个友好型提示,但是打印结果为默认的null效果
38. /*System.out.println("对不起,你的性别错误了");*/
39. //解决办法3:
40. //制造运行时异常:
41. /*throw new RuntimeException("性别不对!");*/
42. //制造检查异常
43. /*try {
44. throw new Exception();
45. } catch (Exception e) {
46. e.printStackTrace();
47. }*/
48. throw new Exception();
49. }
50. }
51.
52. @Override
53. public String toString() {
54. return "Student{" +
55. "name='" + name + '\'' +
56. ", age=" + age +
57. ", sex='" + sex + '\'' +
58. '}';
59. }
60.
61. public Student() {
62. }
63.
64. public Student(String name, int age, String sex) {
65. this.name = name;
66. this.age = age;
67. //this.sex = sex;
68. try {
69. this.setSex(sex);
70. } catch (Exception e) {
71. e.printStackTrace();
72. }
73. }
74.}
1.package com.msb.test02;
2.
3./**
4. * @Auther: msb-zhaoss
5. */
6.public class Test {
7. //这是一个main方法,是程序的入口:
8. public static void main(String[] args) {
9. //创建一个Student的对象:
10. /*Student s = new Student();
11. s.setName("菲菲");
12. s.setAge(19);
13. try {
14. s.setSex("asdfasdfasdf");
15. } catch (Exception e) {
16. e.printStackTrace();
17. }
18. System.out.println(s);*/
19.
20. Student s2 = new Student("娜娜",21,"asdfasdfasdf");
21. System.out.println(s2);
22. }
23.}
24.
【1】重载:
1.public class Demo {
2. public void a() throws Exception{
3.
4. }
5. public void a(int age) throws ArithmeticException{
6.
7. }
8.}
【2】重写:
子类 <= 父类
自定义的异常可以继承:运行时异常
1.public class MyException extends RuntimeException {
2.
3. static final long serialVersionUID = -70348971907L;
4.
5. public MyException(){
6.
7. }
8. public MyException(String msg){
9. super(msg);
10. }
11.}
也可以继承检查异常:
1.public class MyException extends Exception {
2.
3. static final long serialVersionUID = -70348971907L;
4.
5. public MyException(){
6.
7. }
8. public MyException(String msg){
9. super(msg);
10. }
11.}
如果继承的是运行时异常,那么在使用的时候无需额外处理
如果继承的是检查异常,那么使用的时候需要try-catch捕获或者throws向上抛