目录
异常概述
- 异常:就是程序执行报错或者出现了不正常现象
- 如果程序出现了问题,我们没有做任何处理,jvm 最终会做默认处理,将异常的名称,异常的原因及异常出现的位置等信息输出在控制台
异常处理
如果程序出现了问题,我们需要自己来处理。
1.try…catch…
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
执行流程:
- 程序从try里面的代码开始执行,出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统
- 当Java运行时系统接收到异常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理
- 执行完毕之后,程序还可以继续往下执行
2.throws
Java 允许在方法后面使用 throws 关键字对外声明该方法有可能发生异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过。
示例代码:try-catch
package com.abnormal.Demo01;
public class Test01 {
public static void main(String[] args) {
System.out.println("开始");
// try {
// //将可能发生异常的代码 包裹起来
// a1(); //new ArrayIndexOutOfBoundsException()
// } catch (ArrayIndexOutOfBoundsException e) {
// //程序在运行时 如果发生了报错 查找到ArrayIndexOutOfBoundsException——捕获成功
// System.out.println("数组下标越界了");
// e.printStackTrace();//输出异常信息
// } catch (NumberFormatException e) {
// System.out.println("类型转换异常");
// } catch (NullPointerException e) {
// System.out.println("空指针异常");
// }
/**
* 程序报错之后 会在catch 里面查找匹配异常对象
* 可以多个catch,但是异常类型太多,如果需要处理的异常 可以单独写一个catch,其他的异常 统一处理,Exception
* Throwable类是Java语言中所有错误和异常的超类
* Exception 类异常 及其子类是Throwable一种形式,它指示合理的应用程序可能想要捕获的条件
*/
try {
a1();
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界了,单独捕获的异常,可能需要特殊处理");
e.printStackTrace();
} catch (Exception e) {
System.out.println("非其他catch的所有捕获的异常,集中处理");
System.out.println("Exception捕获所有异常 只能放在其他子异常的下面");
}
//jvm默认的情况下,如果程序执行报错,则会直接中断jvm,后面代码不会执行
System.out.println("结束");
}
/**
* 多个异常
*/
public static void a1() {
int[] arrs = {1, 6, 8};
System.out.println(arrs[3]);//ArrayIndexOutOfBoundsException 数组下标越界
String str = "123m";
int i = Integer.parseInt(str);//NumberFormatException 类型转换
System.out.println(i);
Integer intA1 = null;
System.out.println(intA1.intValue());//NullPointerException 空指针
}
}
方法名 | 说明 |
public String getMessage | 返回此 throwable 的详细消息字符串 |
public String toString | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的信息输出在控制台 |
示例代码:Throwable
package com.abnormal.Demo01;
public class Test02 {
public static void main(String[] args) {
try {
System.out.println("开始");
a1();
System.out.println("结束");
} catch (Throwable e) {
// System.out.println("异常内容:" + e.getMessage());//返回 异常错误信息内容
// e.printStackTrace();//把异常的信息输出在控制台
System.out.println(e.toString());//返回此可抛出的简短描述java.lang.NumberFormatException: For input string: "mayikt"
}
}
public static void a1() {
// Integer i = null;
// System.out.println(i.intValue());//空指针异常
String str = "mayikt";
int i = Integer.parseInt(str);//类型转换异常
System.out.println(i);
/**
* 底层 判断 str是否是为数字
* 如果不是数字
* return new NumberFormatException("For input string: \"" + s + "\"");
* 数字类型转换异常
* 传递给我们的 public Throwable(String message) { 构造方法
*/
}
}
编译时异常和运行时异常的区别
Java 中的异常分为两大类:编译时异常和运行是异常,也被称为受检异常所有的RuntimeException类及子类都被称为运行时异常,其他的异常都是编译时异常
- 编译时异常:必须显示处理,否则程序会发生错误,无法通过编译
- 运行时异常:无需显示处理,也可以通过编译时异常一样处理
示例代码:throws
package com.abnormal.Demo01;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class Test03 {
public static void main(String[] args) {//main()如果向上抛异常 就到java虚拟机了
/**
* 如何处理 a1()异常
* 方法1:继续将异常向上throws抛出
* 方法2:try-catch
*/
try {
a1();
} catch (Exception e) {
e.printStackTrace();
}
a4();
/**
* 为什么a4()不需要try-catch或者继续向上抛异常
* ∵ArrayIndexOutOfBoundsException属于运行时异常
*/
}
public static void a1() throws Exception {
int[] arrs = new int[3];
System.out.println(arrs[4]);
}
/**
*谁调用a2(),要么继续向上throws抛出,或者try-catch
* ∵a2() throws Exception,
* 为什么a2() throws Exception?
* ∵a3() throws Exception
*/
public void a2() throws Exception{
a3();
}
public void a3() throws Exception {
}
public static void a4() throws ArrayIndexOutOfBoundsException {
}
public void a5() throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
simpleDateFormat.parse("");
/**
* class ParseException extends Exception {}
*/
}
}
自定义异常
自定义异常,继承Exception类即可。
示例代码:
LoginException.java
package com.abnormal.Demo02;
public class LoginException extends Exception {
/**
*java中自定义异常 编译异常和运行时异常
* - 自定义的异常类 实现编译异常 直接继承 Exception
* - 自定义的异常类 实现运行异常 直接继承 RuntimeException
*/
public LoginException(String message) {
super(message);
}
}
Test01.java
package com.abnormal.Demo02;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入用户名:");
String userName = sc.nextLine();
System.out.print("请输入密码:");
String pwd = sc.nextLine();
try { //如果时运行时异常就不需要try-catch
login(userName, pwd); //如果向上抛出异常,当用户名和密码输入错误,后面的代码就不执行了
} catch (LoginException e) {
System.out.println("发生的异常内容:" + e.getMessage());
e.printStackTrace();
} finally {
System.out.println("无论是否发生异常到执行的代码");
System.out.println("在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。");
}
System.out.println("结束");
}
public static void login(String userName, String pwd) throws LoginException {
if (!("mayikt".equals(userName) && "123456".equals(pwd))) {
//如果用户输入的名称和密码 不是为mayikt 123456 直接抛出异常
throw new LoginException("用户和密码不正确");//
}
System.out.println("用户名和密码输入正确");
}
}
下一篇文章:为什么需要使用集合框架