异常是导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,所以在程序的设计中必须要考虑各种异常的发生,并正确的做好相应的处理,这样才能保证程序的正常执行。
异常分为严重异常-Error 和 一般异常,一般异常又分为运行时异常(RuntimeException)和 编译时异常(除了RuntimeException)。
运行时异常:不需要我们显式处理,我们也可以像编译时异常一样使用try…catch。
编译时异常:我们在执行程序之前,必须要处理的异常,如果不处理,程序将不能运行。
应注意:
案例一:
public class ExceptionDemo1 {
public static void main(String[] args) {
int a = 1;
int b = 0;
System.out.println(a / b);
System.out.println("此处代码不执行");
}
}
运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
程序出现问题后,控制台打印了错误信息,包括Exception的包名+类名,错误的描述,出现的位置。这些异常处理操作是JVM做的。即默认的异常处理方式是:
1、打印错误信息
2、结束程序
两种处理方式:
1、try...catch...finally
2、throws
try…catch处理方式格式:
try{
//有可能出现异常的代码
} catch(异常类 异常对象){
//编写异常的处理语句
} catch(异常类 异常对象){
//编写异常的处理语句
}...finally{
//一定会运行到的程序代码
}
如果在try中出现了异常,则程序会自动跳转到catch语句中找到匹配的异常类型进行相应的处理。最后不管程序是否会出现异常,都会执行到finally语句,finally语句就是异常的统一出口。finally是可以省略的,则在catch()块运行结束后,程序会跳到try-catch块之后继续执行。
案例二:
public class ExceptionDemo2 {
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
System.out.println(a / b);
System.out.println("此处代码不再执行");
} catch (ArithmeticException ae) { //创建一个异常对象,捕获算术异常
System.out.println("出现异常了:" + ae);
System.out.println("除数不能是0");
}
System.out.println("程序结束");
}
}
运行结果:
出现异常了:java.lang.ArithmeticException: / by zero
除数不能是0
程序结束
通过结果我们可以得出:通过try…catch处理异常,不但可以对异常进行一些自定义的处理,而且程序不会被停止,会继续运行。
多个异常的处理:
可以采用多个try-catch语句,也可以一个try,多个catch语句。以第二种方式为例。
案例三:
public class ExceptionDemo3 {
public static void main(String[] args) {
int a = 1;
int b = 0;
int[] c = {1, 2, 3};
try {
System.out.println(a / b);
System.out.println(c[3]);
} catch (ArithmeticException e) {
System.out.println("除数不能为0");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界");
}
System.out.println("程序结束!");
}
}
当采用一个try多个catch时,如果try-catch补货到异常,会立即去catch匹配异常,如果匹配到,整个try-catch结构就会结束,try中剩余的语句将不再执行。
在整个Java的异常结构中,有两个最常用的类,Exception和Error,这两个类都是Throwable
的子类。
当我们不知道代码中的异常具体是哪个时,可以通过所有异常的父类Exception
去匹配。
案例四:
public class ExceptionDemo4 {
public static void main(String[] args) {
method();
}
//多个异常的处理
public static void method() {
int a = 1 ;
int b = 0 ;
int[] c = {1, 2, 3};
try {
System.out.println(a / b);
System.out.println(c[3]);
} catch (Exception e) {
System.out.println("有异常");
}
System.out.println("程序结束!");
}
案例五:
try {
//可能出错的语句
} catch (ArithmeticException e) {
System.out.println("除数不能为0");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界了");
}catch(Exception e){
System.out.println("程序出现异常");
}
ArithmeticException
,ArrayIndexOutOfBoundsException
,都属于Exception
的子类,当try-catch
中有多个异常捕获是,应注意:
JDK7之后的异常处理方式:
格式:
try{
……
}catch(异常类名1 | 异常类名2 | 异常类名3| …… 变量名 ){
……
}
案例六:
public class ExceptionDemo5 {
public static void main(String[] args) {
int a = 1;
int b = 0;
int[] c = {1, 2, 3};
try {
System.out.println(a / b);
System.out.println(c[3]);
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("有异常");
}
System.out.println("程序结束!");
}
}
在使用此方法时应注意:多个异常必须是平级关系,否则会报错。而且对于不同的异常只有统一处理方式,不能区别处理。
异常处理时的注意事项:
在编写代码时,确定代码没有错误,但是被标红,这种情况可能是调用的某个方法存在编译时异常,必须在执行前进行异常处理。例如在格式化日期的parse方法中。
案例七:
public class ExceptionDemo6 {
public static void main(String[] args) {
String s = "2020-8-16 11:12:45";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = sdf.parse(s);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
异常信息的输出方式:
在catch语句输出异常时,可以直接使用System.out.println(异常对象)
;也可以直接使用Exception
类中的printStackTrace()
方法输出异常信息,格式为e.printStackTrace();
,打印出异常类名、异常信息及异常在程序中出现的位置。
Throwable常用方法:
1、public String getMessage()
获取异常信息
2、public String toString()
获取异常信息和异常类名
3、public void printStackTrace
获取出异常类名、异常信息及异常在程序中出现的位置
案例八:
public class ExceptionDemo6 {
public static void main(String[] args) {
String s = "2020-8-16";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = sdf.parse(s);
} catch (ParseException e) {
System.out.println(e.getMessage());//Unparseable date: "2020-8-16"
System.out.println(e.toString());//java.text.ParseException: Unparseable date: "2020-8-16"
e.printStackTrace();
}
}
}
throws关键字
在定义一个方法时可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用处进行处理。
throws 使用格式:
public 返回值类型 方法名称(参数列表...) throws 异常类1, 异常类2...{ }
运行时异常:异常抛出,调用者不用处理。
案例九:
public class ExceptionDemo7 {
public static void main(String[] args) {
method();
//运行时异常
public static void method() throws ArithmeticException {
int a = 1;
int b = 0;
System.out.println(a / b);
}
}
编译时异常:异常抛出,调用者必须处理。还应注意尽量不要在主方法上进行异常的抛出,这样的话,异常会交给JVM处理,即默认处理方式。
案例十:
public class ExceptionDemo8 {
public static void main(String[] args) {
try {
method1();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("程序结束!");
}
//编译时异常
public static void method1() throws ParseException {
String s = "2020-8-16";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(s);
System.out.println(date);
}
}
throw关键字
可以直接使用throw抛出一个异常,抛出时直接抛出异常类的实例化对象。使用位置在方法体内。
public class ExceptionDemo9 {
public static void main(String[] args) {
method();
}
public static void method() {
int a = 1;
int b = 0;
if (b == 0) {
throw new ArithmeticException();
} else {
System.out.println(a / b);
}
}
}
Java中提供的异常类有时很难满足需求,所以用户可以根据自己的需求定义自己的异常类。定义异常类时只需要继承Exception
类即可。
public class StudentDemo {
public static void main(String[] args) {
//创建Scanner对象
Scanner sc = new Scanner(System.in);
//接收用户输入的数据
System.out.println("请输入成绩:");
int score = sc.nextInt();
//校验成绩
Teacher teacher = new Teacher();
try {
teacher.checkScore(score);
} catch (MyException e) {
e.printStackTrace();
}
System.out.println("程序结束");
}
}
class Teacher {
public void checkScore(int score) throws MyException {
if (score < 0 || score > 100) {
throw new MyException("成绩必须在0-100之间");
} else {
System.out.println("您输入的成绩合法!");
}
}
}
class MyException extends Exception {
//构造方法
//无参构造
public MyException() {
}
//指定有参构造
public MyException(String message) {
super(message);//调用Exception类中有一个参数的构造方法,传递错误信息
}
}
我是快斗,欢迎批评指正!