一,异常
异常 :指的是程序在运行过程中报错,然后停止运行,控制台显示错误。
注意事项:异常本身是一个类,出现异常会创建一个异常类的对象并抛出,
public class DemoTest {
public static void main(String[] args) {
System.out.println("开始");
System.out.println(1/0);
System.out.println("结束");
}
}
在测试类中,打印1/0会报错,java.lang.ArithmeticException: / by zero 大概意思就是不能除以0;
1.2 异常体系
对于异常体系来说,帮助我们寻找问题 java.lang.Throwable
java.lang.Throwable有两个子类
java.lang.Error
与
java.lang.Exception
平常所说的异常指
java.lang.Exception
。
Throwable
:
- Error:严重的错误,无法解决,只能避免。
- Exception:异常,产生后我们可以解决,让程序运行正常。
1.3 异常分类
我们经常遇见的异常指Exception,出现就要解决。
Exception的分类:
写代码时的异常(编译时期异常):没改就一直提示报错。
运行异常(运行时期异常):运行后,控制台显示有异常。
public class DemoTest {
public static void main(String[] args) {
//编译异常
//FileInputStream fis=new FileInputStream("D:\\1.txt");
//运行异常
System.out.println(1/0);
}
}
1.4 异常的产生过程解析
public class Test {
public static void main(String[] args) {
int[] arr = { 34, 12, 67 };
int num = getElement(arr, 4);
System.out.println("num=" + num);
System.out.println("over");
}
// 对给定的数组通过给定的角标获取元素
public static int getElement(int[] arr, int index) {
int element = arr[index];
return element;
}
}
二.异常的产生
throw关键字可以抛出一个异常对象,
throw用在方法内,抛出一个异常对象的同时告诉我们错误,然后停止方法运行。
语法
[ throw new
异常类名
(
参数
);
]
具体操作:
- 创建一个异常类,
- 通过throw将这个异常对象在控制台打印出来。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
// 在给年龄赋值时,先判断
if (age < 0 || age > 120){
// 产生异常 运行异常
throw new RuntimeException("年龄数据不合法");
}else {this. Age = age;}
}
public Person() {}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { // 在给年龄赋值时,先判断 this. Age = age; } }
public class DemoTest {
public static void main(String[] args) {
/* 案例演示:给Person对象年龄赋值,如果年龄数据不合法,就产生 一个异常 */
// 创建Person类对象
Person p1 = new Person("张三",18);
System.out.println(p1.getName()+"..."+p1.getAge());
Person p2 = new Person("李四",-18);
System.out.println(p2.getName()+"..."+p2.getAge());
}
}
三.处理异常
3.1 声明处理异常
声明处理异常:不处理异常,提醒我们有异常,控制台打印异常信息
语法
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ // 可 以抛出一个,也可以多个 }
public class DemoTest {
public static void main(String[] args) throws Exception {
//method01();
//method02(1);
method03(1);
System.out.println("结束");
}
// 处理多个异常 抛最大的一个异常
public static void method03(int num) throws Exception {
if (num == 1) {
throw new ParseException("解析异常",10);
} else {
throw new IOException("IO异常");
}
}
// 处理多个异常 分别抛出多个异常
public static void method02(int num) throws ParseException,IOException{
if (num == 1) {
throw new ParseException("解析异常",10);
} else {
throw new IOException("IO异常");
}
}
// 处理单个异常
public static void method01() throws ParseException{
// 将异常标识出来,表示当前方法不处理异常
// 产生一个异常
throw new ParseException("解析异常",10);// 编译异常
// throw new ArrayIndexOutOfBoundsException("索引越 界异常");// 运行异常
}
}
3.2 捕获处理异常
捕获处理异常语法:
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
执行
:
- 如果try中出现了异常,那么会执行行catch的代码,再向下
- 如果try没有出现,那就不会执行。
注意 :
- try和catch不能单独出现
public class DemoTest {
public static void main(String[] args){
try{
System.out.println("try开始");
FileInputStream fis=new FileInputStream("D:\\2.txt");
//创建异常对象并抛出 throw new FileNotFoundException("");
System.out.println("try结束");
}catch (IOException e){
// 打印信息
//System.out.println("出现了异常");
//System.out.println(e.getMessage());
//System.out.println(e.toString());
e.printStackTrace();// 打印异常的跟踪栈信息
}
}
Throwable
类中定义了一些查看方法
:
-
public String getMessage(): 获取异常的描述信息 , 原因 ( 提示给用户的时候 , 就提示错误原因。
-
public String toString(): 获取异常的类型和异常描述信息 ( 不用 ) 。
-
public void printStackTrace(): 打印异常的跟踪栈信息并输出到控制台。
3.3 finally 代码块
finally
:有一些特定的代码无论异常是否发生,都需要执行。另外,因为
异常会引发程序跳转,导致有些语句执行不到。
而
finally
就是解决这个问题的,在
finally
代码块中存放的代码都是一定会被
执行的。
语法:
try{
可能会出现异常的代码
}catch(异常的类型 变量名){
处理异常的代码或者打印异常的信息
}finally{
无论异常是否发生,都会执行这里的代码(正常情况,都会执行finally中的 代码,一般用来释放资源)
}
执行步骤:
1.首先执行try中的代码,如果try中的代码出现了异常,那么就直接执行 catch()里面的代码,执行完后会执行finally中的代码,然后程序继续往下执行
2.如果try中的代码没有出现异常,那么就不会执行catch()里面的代码,但是 还是会执行finally中的代码,然后程序继续往下执行
3.即使catch中有return,finally中的代码还是会执行
public class DemoTest {
public static void main(String[] args){
Scanner sc = null;
try{sc = new Scanner(System.in);
String s = sc.nextLine();
System.out.println(1/0);// 出现异常,throw new ArithmeticException("");
}catch (Exception e){
System.out.println("出现了异常");
//return;// 结束方法 finally会执行
//System.exit(0);// 系统退出 finally不会执行
}finally{
sc.close();// 不会执行
System.out.println("关闭...");
}
System.out.println("结束");
}
}
五.自定义异常
- 异常类的定义
-
自定义一个编译期异常 : 自定义类 并继承于 java.lang.Exception 。
-
自定义一个运行时期的异常类 : 自定义类 并继承于 java.lang.RuntimeException 。
下面我们看一道题目
要求:我们模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。
- 首先定义一个注册异常类RegisterException:
public class RegisterException extends RuntimeException { public RegisterException() {} public RegisterException(String message) { super(message); } }
-
模拟登陆操作,使用数组模拟数据库中存储的数据,并提供当前注册账号是否存在方法用于判断。
public class DemoTest { public static void main(String[] args){ // 1.定义一个字符串,表示已经注册的用户名 String username = "admin"; // 2.创建Scanner对象,获取用户输入的用户名 Scanner sc = new Scanner(System.in); System.out.println("请输入您要注册的用户名:"); String name = sc.next(); // 3.判断 if (username. Equals(name)){ // 产生注册异常 try { throw new RegisterException("亲,该用户名已经 被注册。"); } catch (RegisterException e) { System.out.println(e.getMessage()); } }else{ System.out.println("恭喜您,注册成功"); } System.out.println("结束"); } }