且长凌风翮,乘春自有期
异常概念
异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是:
- 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.
异常体系
异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Error与java.lang.Exception,平常所说的异常指java.lang.Exception。




异常的处理方式
JVM默认处理方式
把异常的名称,异常的原因以及异常出现的位置等信息输出在了控制台
程序停止执行,下面的代码不会再执行了
自己处理
捕获异常try…catch
如果异常出现的话,会立刻终止程序,所以我们得处理异常:
- 该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
- 在方法中使用try-catch的语句块来处理异常。
try-catch的方式就是捕获异常。
- 捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。
捕获异常语法如下:
1 2 3 4 5 6
| try{ 编写可能会出现异常的代码 }catch(异常类型 e){ 处理异常的代码 }
|
try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
注意:try和catch都不能单独使用,必须连用。

演示如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class TryCatchDemo { public static void main(String[] args) { try { read("b.txt"); } catch (FileNotFoundException e) { System.out.println(e); } System.out.println("over"); }
public static void read(String path) throws FileNotFoundException { if (!path.equals("a.txt")) { throw new FileNotFoundException("文件不存在"); } } }
|
如何获取异常信息:
Throwable类中定义了一些查看方法:
public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。
public String toString():获取异常的类型和异常描述信息(不用)。
public void printStackTrace():打印异常的跟踪栈信息并输出到控制台。 包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。
在开发中呢也可以在catch将编译期异常转换成运行期异常处理。
多个异常使用捕获又该如何处理呢?
- 多个异常分别处理。
- 多个异常一次捕获,多次处理。
- 多个异常一次捕获一次处理。
一般我们是使用一次捕获多次处理方式,格式如下:
1 2 3 4 5 6 7 8 9
| try{ 编写可能会出现异常的代码 }catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获. 处理异常的代码 }catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获. 处理异常的代码 }
|
注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

抛出异常
声明异常throws
声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
声明异常格式:
1
| 修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
|
声明异常的代码演示:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class ThrowsDemo { public static void main(String[] args) throws FileNotFoundException { read("a.txt"); }
public static void read(String path) throws FileNotFoundException { if (!path.equals("a.txt")) { throw new FileNotFoundException("文件不存在"); } } }
|
throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class ThrowsDemo2 { public static void main(String[] args) throws IOException { read("a.txt"); }
public static void read(String path)throws FileNotFoundException, IOException { if (!path.equals("a.txt")) { throw new FileNotFoundException("文件不存在"); } if (!path.equals("b.txt")) { throw new IOException(); } } }
|
抛出异常throw
在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。
在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢?
- 创建一个异常对象。封装一些提示信息(信息可以自己编写)。
- 需要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?通过关键字throw就可以完成。throw 异常对象。
throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
使用格式:
例如:
1 2 3
| throw new NullPointerException("要访问的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class ThrowDemo { public static void main(String[] args) { int[] arr = {2,4,52,2}; int index = 4; int element = getElement(arr, index);
System.out.println(element); System.out.println("over"); }
public static int getElement(int[] arr,int index){ if(index<0 || index>arr.length-1){
throw new ArrayIndexOutOfBoundsException("哥们,角标越界了```"); } int element = arr[index]; return element; } }
|
注意:如果产生了问题,我们就会throw将问题描述类即异常进行抛出,也就是将问题返回给该方法的调用者。
那么对于调用者来说,该怎么处理呢?一种是进行捕获处理,另一种就是继续讲问题声明出去,使用throws声明处
异常练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| package exception;
import java.util.Scanner;
public class ExceptionDemo1 { public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend();
while (true) { try { System.out.println("请输入姓名:"); Scanner scanner = new Scanner(System.in); girlFriend.setName(scanner.nextLine());
System.out.println("请输入年龄"); String ageStr = scanner.nextLine(); int age = Integer.parseInt(ageStr); girlFriend.setAge(age);
break; } catch (NumberFormatException e) { System.out.println("年龄格式有误"); } catch (RuntimeException e) { System.out.println("名字长度 或 年龄范围 不符合要求"); } }
System.out.println(girlFriend); } }
package exception;
public class GirlFriend { private String name; private int age;
public GirlFriend() {
}
public GirlFriend(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { if (name.length()>10||name.length()<2){ throw new RuntimeException(); } this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { if (age<18||age>24){ throw new RuntimeException(); } this.age = age; }
@Override public String toString() { return "GirlFriend{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
自定义异常

将练习改为自定义异常
自定义异常 名字格式化异常

自定义异常 年龄超出范围

改写Girlfriend类中的异常信息

调用方法时,捕获异常
