异常
异常:Exception:在程序的运行过程中,发生了不正常的现象,阻止了程序的运行,我们称之为发生异常。
示例
public class Test {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//实现一个功能:键盘录入两个数,求商:
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
int num2 = sc.nextInt();
System.out.println("商:"+num1/num2);
}
}
if-else解决异常
示例
package com.msb.test01;
import java.util.Scanner;
/**
* @Auther: msb-zhaoss
*/
public class Test {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//实现一个功能:键盘录入两个数,求商:
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
if(sc.hasNextInt()){
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
if(sc.hasNextInt()){
int num2 = sc.nextInt();
if(num2 == 0){
System.out.println("对不起,除数不能为0");
}else{
System.out.println("商:"+num1/num2);
}
}else{
System.out.println("对不起,你录入的不是int类型的数据!");
}
}else{
System.out.println("对不起,你录入的不是int类型的数据!");
}
}
}
缺点:
- 代码臃肿,业务代码和处理异常的代码混在一起。
- 可读性差
- 程序员需要花费大量的经历来维护这个漏洞
- 程序员很难堵住所有的漏洞。
try-catch
示例
public class Test2 {
public static void main(String[] args) {
//实现一个功能:键盘录入两个数,求商:
try{
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
int num2 = sc.nextInt();
System.out.println("商:"+num1/num2);
}catch(Exception ex){
System.out.println("对不起,程序出现异常!");
}
System.out.println("----谢谢你使用计算器111");
System.out.println("----谢谢你使用计算器222");
System.out.println("----谢谢你使用计算器333");
System.out.println("----谢谢你使用计算器444");
System.out.println("----谢谢你使用计算器555");
System.out.println("----谢谢你使用计算器666");
}
}
原理:
把可能出现异常的代码放入try代码块中,然后将异常封装为对象,被catch后面的()中的那个异常对象接收,接收以后:执行catch后面的{}里面的代码,然后try-catch后面的代码,该怎么执行就怎么执行。
总结
-
try中没有异常,catch中代码不执行。
-
try中有异常,catch进行捕获:
如果catch中异常类型和你出的异常类型匹配的话:走catch中的代码–》进行捕获
如果catch中异常类型和你出的异常类型不匹配的话:不走catch中的代码–》没有捕获成功,程序相当于遇到异常了,中断了,后续代码不执行
注意:
- try中如果出现异常,然后用catch捕获成功的话,那么try中后续的代码是不会执行的。
- 如果catch捕获异常成功,那么try-catch后面的代码该执行还是执行没有影响。
代码示例
package com.msb.test01;
import java.util.Scanner;
/**
* @Auther: lianzihao
*/
public class Test3 {
public static void main(String[] args) {
//实现一个功能:键盘录入两个数,求商:
try{
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
int num2 = sc.nextInt();
System.out.println("商:"+num1/num2);
}catch(Exception ex){
//第一种处理:什么都不写,什么都不做
//第二种处理:输出自定义异常信息
//System.out.println("对不起,你的代码有问题!");
//第三种处理:打印异常信息:
/*(1)调用toString方法,显示异常的类名(全限定路径)*/
/*System.out.println(ex);
System.out.println(ex.toString());*/
/*(2)显示异常描述信息对应的字符串,如果没有就显示null
System.out.println(ex.getMessage());*/
/*(3)显示异常的堆栈信息:将异常信息捕获以后,在控制台将异常的效果给我 们展示出来,方便我们查看异常*/
/* ex.printStackTrace();*/
//第四种处理:抛出异常:
throw ex;
}
System.out.println("----谢谢你使用计算器111");
}
}
try-catch-finally
什么情况下,try-catch后面的代码不执行?
- throw抛出异常的情况
- catch中没有正常的进行异常捕获
- 在try中遇到return
如何将 try-catch后面的代码 必须执行?
将必须执行的代码放入finally中,那么这个代码无论如何一定执行。
return和finally执行顺序?
先执行finally最后执行return
示例
package com.msb.test01;
import java.util.Scanner;
/**
* @Auther: lianzihao
*/
public class Test3 {
public static void main(String[] args) {
//实现一个功能:键盘录入两个数,求商:
try{
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
int num2 = sc.nextInt();
System.out.println("商:"+num1/num2);
System.exit(0);//终止当前的虚拟机执行
return;
}catch(ArithmeticException ex){
//throw ex;
}finally {
System.out.println("----谢谢你使用计算器111");
}
}
}
多重catch
- try中出现异常以后,将异常类型跟catch后面的类型依次比较,按照代码的顺序进行比对,执行第一个与异常类型匹配的catch语句
- 一旦执行其中一条catch语句之后,后面的catch语句就会被忽略了!
- 在安排catch语句的顺序的时候,一般会将特殊异常放在前面(并列),一般化的异常放在后面。
- 先写子类异常,再写父类异常。
示例
package com.msb.test01;
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* @Auther: lianzihao
*/
public class Test4 {
public static void main(String[] args) {
Integer
//实现一个功能:键盘录入两个数,求商:
try{
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
int num2 = sc.nextInt();
System.out.println("商:"+num1/num2);
}catch(ArithmeticException ex){
System.out.println("对不起,除数不可以为0");
}catch(InputMismatchException ex){
System.out.println("对不起,你录入的数据不是int类型的数据");
}catch(Exception ex){
System.out.println("对不起,你的程序出现异常");
}finally {
System.out.println("----谢谢你使用计算器111");
}
}
}
异常的分类
运行时异常示例
public class Test5 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//运行时异常:
int[] arr = {1,2,3};
System.out.println(arr.length);
/*int[] arr2 = null;
System.out.println(arr2.length);*/
System.out.println(arr[10]);
}
}
检查异常示例
处理方式1:try-catch嵌套try-catch
public class Test6 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//检查异常:
try {
try {
Class.forName("com.msb.test01.Test").newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
处理方式2:多重catch
public class Test6 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//检查异常:
try {
Class.forName("com.msb.test01.Test").newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
处理方式3:throws
public class Test6 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//检查异常:
Class.forName("com.msb.test01.Test").newInstance();
}
}
throw和throws的区别
示例
package com.msb.test01;
import java.util.Scanner;
/**
* @Auther: lianzihao
*/
public class Test7 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws Exception {
//实现一个功能:两个数相除,当除数为0的时候,程序出现异常。
/*try {
devide();
} catch (Exception e) {
e.printStackTrace();
}*/
devide();
}
public static void devide() throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("请录入第一个数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个数:");
int num2 = sc.nextInt();
if(num2 == 0 ){//除数为0 ,制造异常。
//制造运行时异常:
/*throw new RuntimeException();*/
//制造检查异常:
/*try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}*/
throw new Exception();
}else{
System.out.println("商:"+num1/num2);
}
}
}
总结
- 位置不同:throw:方法内部 throws: 方法的签名处,方法的声明处
- 内容不同:throw+异常对象(检查异常,运行时异常)throws+异常的类型(可以多个类型,用,拼接)
- 作用不同:throw:异常出现的源头,制造异常 throws:在方法的声明处,告诉方法的调用者,这个方法中可能会出现我声明的这些异常。然后调用者对这个异常进行处理:要么自己处理要么再继续向外抛出异常
自定义异常
重载重写异常
英文 | 位置 | 修饰符 | 返回值 | 方法名 | 参数 | 抛出异常 | 方法体 | |
---|---|---|---|---|---|---|---|---|
重载 | overload | 同一个类中 | 无关 | 无关 | 必须相同 | 必须不同 | 无关 | 不同 |
重写 | override | 子父类中 | 父类权限修饰符低于子类 | 父类返回值类型大于子类 | 必须相同 | 必须相同 | 小于等于 | 不同 |
重写
子类 <= 父类
自定义的异常可以继承:运行时异常
public class MyException extends RuntimeException {
static final long serialVersionUID = -70348971907L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
继承检查异常
public class MyException extends Exception {
static final long serialVersionUID = -70348971907L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
**如果继承的是运行时异常,那么在使用的时候无需额外处理
nUID = -70348971907L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
**继承检查异常**
```java
public class MyException extends Exception {
static final long serialVersionUID = -70348971907L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
如果继承的是运行时异常,那么在使用的时候无需额外处理
如果继承的是检查异常,那么使用的时候需要try-catch捕获或者throws向上抛