一,异常分为Error和Exception
Error是程序运行时出现的严重错误,一般开发人员捕获,也无法解决
Exception是程序本身可以处理的异常,大部分捕获后可以解决,可以分为运行时异常和非运行时异常,非运行异常也叫作检查异常和编辑异常。
常见的运行时异常类(RuntimeException)
运行时异常类 | 说明 |
AnithmeticException | 算数异常如被0除 |
ArrayIndexOutOfBoundsException | 数组下标越界 |
ClassCastException | 非法类型转换 |
IllegalArgumentException | 非法调用方法的参数 |
IndexOutOfBoundsException | 类型索引越界 |
NullPointerException | 非法使用空引用 |
NumberFormatException | 字符串到数字格式非法转换 |
OutOfMemoryException | 内存溢出 |
常见的非运行时异常类
非运行时异常类 | 说明 |
ClassNotFoundException | 找不到类或者接口 |
IllgalAccessException | 访问类被拒绝 |
InstantiationException | 试图创建抽象类或者接口的对象 |
IOException | 一般情况下无法完成I/O操作 |
NoSuchMethodException | 请求的方法不存在 |
TimeoutException | 阻塞操作超时 |
InterruptedException | 线程中断 |
异常常用的方法
getMessage() | 返回一个字符串,表示异常的详细信息,如果该异常对象没有详细信息,则返回null |
printStackTrace() | 将异常和它的跟踪情况打印到标准错误流 |
printStackTrace (PrintStream s) | 将异常和它的跟踪情况打印到指定打印流 |
toString() | 返回一个字符串,表示异常简短描述 |
二,异常的处理方法
捕获异常可以通过try-catch语句,多重catch语句和try-catch-finally语句实现
try{
//可能发生异常的代码块
}catch(异常类型 异常对象名){
//处理异常的代码块
}
catch子句中的异常类型必须是Throwable类的子类,他指明了能够捕获的异常类型,此外,catch子句还给出了异常对象名,以便访问该对象
当使用多个catch子句时,子句中的异常类型是先子类后父类,否则会出现错误,当异常发生时,依次检查每一个并执行第一个异常类型匹配的代码块,当一个catch子句执行时,其他的catch子句将被忽略,程序继续执行try-catch代码块后面的语句。
finally语句必须和try-catch语句配合使用,并出现在try-catch语句之后,不论是否捕获异常,fianlly语句中代码块代码块都会执行
try{
//可能发生异常的代码块
}catch(异常类型 异常对象名){
//处理异常的代码块
......
finally{
//最终处理代码块
}
使用throws声明抛出异常
语法格式:返回值类型 方法名 (<参数列表>) throws 异常列表{//方法体}
当抛出多个异常类型时,中间使用逗号隔开。使用throws抛出异常时,应注意以下几点:
如果方法声明了抛出异常,必须在调用该方法时使用try-catch语句对异常列表中所有异常进行处理 |
如果方法没有声明抛出异常,则无需使用try-catch语句强制处理 |
如果调用抛出异常的方法时,可以选择继续抛出,但是需要在main()方法之前try-catch解决 |
【问题分析】:定义TestIp类,包含ige成员方法pay(),声明方法时抛出ArrayIndexOutOfBoundsException异常,在方法中定义变量price(单价),从输入的字符串中提取商品件数,并计算需要支付的金额。然后再main()方法中,输入商品名和单价后,调用pay()方法,捕获方法产生的异常并输出
public class TestIp { public static void pay(String product){ double price = 18.6; String[] s = product.split(" "); int count = Integer.parseInt(s[2]); double money = round(price*count); System.out.println(money); } public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入商品名称"); String product = scan.nextLine(); try { pay(product); }catch (ArrayIndexOutOfBoundsException e){ System.out.println(e.toString()); }finally { scan.close(); } } }运行结果:
请输入商品名称
大保健 122
java.lang.ArrayIndexOutOfBoundsException: 2
三,throw语句(高手都在用)
语法格式:throw new 异常类型(<异常信息>)
其中,new表示创建一个异常类对象,异常信息表示需要输出的信息
通过throw抛出异常后,如果想由上一级代码来捕获并处理异常,则需要在抛出的方法中使用throws声明,并指明要抛出的异常,除非抛出的异常类型是RuntimeException类或者他的子类,如果想在当前的方法中捕获并处理异常,则必须在方法中使用try-catch语句
public class TestNine { public static void printScore(double score) throws Exception { if (score>100){ throw new Exception("异常信息:分数必须大于100"); }else { System.out.println("该学生的成绩为"+score); } } public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入学生的的成绩"); double score = scan.nextDouble(); try { printScore(score); }catch(Exception e){ System.out.println(e.toString()); } } } 运行结果:
四,自定义异常类(高级用法)
目的:Java提供的异常类可以解决大部分异常情况,但是有时程序会有特殊的要求,系统可能无法识别异常,这时就需要用户创建自定义异常类,使系统能够识别异常并进行处理。
自定义的异常类必须继承Throwable类,通常是继承Exception类或它的子孙类,它在方法中通过throw抛出异常对象。自定义异常类的语法格式:
class 自定义异常类名 extends 父类名{类体};
示例;自定义异常类,检查输入的员工年龄是否符合要求
【问题分析】;自定义异常类AgeException,继承RuntimeException类,包含一个有参构造方法,初始化异常信息;然后定义员工类Employee,包括私有成员变量age(年龄)和设置age的方法setAge(),在方法中判断传入的参数是否符合要求(22<age<65),如果符合,则赋给age,否则使用throw抛出异常,并设置异常信息;最后在公共类EmployeeManage的main()方法中创建Emplayee对象,调用Employee对象,调用setAge()方法,并使用try-catch-finally语句捕获异常和输出异常信息
public class AgeException extends RuntimeException{ public AgeException(String message) { super(message); } }public class Employee { private int age ; public void setAge(int age){ if (22<age || age>65){ throw new AgeException("年龄必须在22到65岁之间"); }else { this.age=age; } } }public class EmployeeManage { public static void main(String[] args) { Employee employee = new Employee(); Scanner scan = new Scanner(System.in); System.out.println("请输入年龄"); int age = scan.nextInt(); try { employee.setAge(age); }catch (AgeException e){ System.out.println(e.getMessage()); }finally { scan.close(); } } }运行结果:
请输入年龄
90
年龄必须在22到65岁之间