1、什么是异常?
异常就是程序在运行时出现的意外情况,而导致程序无法继续执行。异常是一种信号,用于向调用者传递信息,表示程序发生了意外情况。在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
程序运行时一旦出现了异常,将会导致程序立即终止,异常之后的代码将无法继续执行,所以需要对异常进行处理。
2、常见的异常情况
ArithmeticException--------------------------算术异常
ArrayIndexOutOfBoundsException-------数组下标越界异常
NullPointerException -----------------------空指针异常
ClassCastException-------------------------类型转换异常
NumberFormatException-------------------数字格式异常
ClassNotFoundException------------------类找不到异常
ParseException-------------------------------解析异常-----字符串格式不正确
3、为什么需要异常处理
异常处理的目的就是为了让程序继续执行下去,而不是遇见异常时终止程序
4、如何处理异常
JAVA中提供了两张异常处理的方式,分别是用try-catch-finally方法和异常抛出方法throws
4.1 try-catch方法
语法格式:
try{
可能发生异常的代码
}catch(异常类型 对象){
捕获异常
}finally{
异常的出口
}
示例代码
public class Test {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.print("请输入一个数字:");
String c1=scanner.next();
System.out.print("请输入二个数字:");
String c2=scanner.next();
System.out.println("开始计算===============");
try {
int a=Integer.parseInt(c1);
int b=Integer.parseInt(c2);
int result = a / b;
}catch (ArithmeticException e){
System.out.println("捕获算术异常");
}catch (NumberFormatException e){
System.out.println("格式化转化异常");
}
System.out.println("结束计算==============");
}
}
try后面可以跟多个catch捕获,不同的catch捕获不同的异常,但是这样较为麻烦,一般可以把异常类型写为Exception,这样就可以捕获所有可能发生的异常。如果使用多个catch,异常范围大的必须放在范围小的下面。
finally关键字
在使用异常处理时,finally作为最终执行的代码,无论有没有异常,finally中的代码都会执行
try{}可以finally单独使用。但是try{}finally{}//没有捕获异常
public class Test02 {
public static void main(String[] args) {
int c = fun();
System.out.println("c========" + c);
}
public static int fun() {
int a = 10;
int b = 2;
int c = a / b;
try {
return c;
} catch (Exception e) {
System.out.println("异常");
} finally {
c = 15;
System.out.println("finally~~~~~~~");
// return c;
}
return 0;
}
}
异常捕获的原理
这些异常有没有一个公共的父类,异常的根类是Throwable. Throwable下有两个子类.
Exception: 异常类,我们程序员可以处理的异常。一般使用该异常就了。
Error: 错误类。这种异常程序员无法处理。比如内存溢出。
根据多态,再异常捕获时可以使用Exception异常来捕获。
Exception下常用的api方法
getMessage():获取异常信息
toString():获取异常信息以及异常种类
printStackTrace():打印异常信息以及异常种类和异常发生的位置
4.2 抛出异常throw
在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。
语法格式:
throw new 异常类名(参数);
//例如:
throw new NullPointerException("要访问的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
示例代码
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抛出异常对象后,方法已经无法继续运算。
这时就会结束当前方法的执行,并将异常告知给调用者。这时就需要通过异常来解决。
*/
throw new ArrayIndexOutOfBoundsException("哥们,角标越界了```");
}
int element = arr[index];
return element;
}
}
如果产生了问题,我们就会throw将问题描述类即异常进行抛出,也就是将问题返回给该方法的调用者。
那么对于调用者来说,有两种处理方式,一种是进行捕获处理,另一种就是继续讲问题声明出去,使用throws声明处理。
声明异常throws
声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
声明异常的格式
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
声明异常的示例代码:
public class ThrowsDemo2 {
public static void main(String[] args) throws IOException {
read("a.txt");
}
// 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明
public static void read(String path)throws FileNotFoundException, IOException {
if (!path.equals("a.txt")) {//如果不是 a.txt这个文件
// 我假设 如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常 throw
throw new FileNotFoundException("文件不存在");
}
if (!path.equals("b.txt")) {
throw new IOException();
}
}
}
注意:throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开。
5、异常注意事项
-
运行时异常被抛出可以不处理。即不捕获也不声明抛出。
-
如果父类抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集。
-
父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
-
当多异常处理时,捕获处理,前边的类不能是后边类的父类
-
在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收。
6、自定义异常
当系统提供的异常类型无法满足客户需求时,程序员可以在开发中根据自己业务的异常情况来定义异常类.。目的可以达到见名知意
异常类如何定义?
-
自定义一个编译期异常: 自定义类 并继承于
java.lang.Exception
。 -
自定义一个运行时期的异常类:自定义类 并继承于
java.lang.RuntimeException
。
示例代码
模拟登陆操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。
首先定义一个登录异常类LoginException
// 业务逻辑异常
public class LoginException extends Exception {
// 空参构造
public LoginException() {
}
//表示异常提示
public LoginException(String message) {
super(message);
}
}
模拟登陆操作,使用数组模拟数据库中存储的数据,并提供当前注册账号是否存在方法用于判断。
public class Demo {
// 模拟数据库中已存在账号
private static String[] names = {"bill","hill","jill"};
public static void main(String[] args) {
//调用方法
try{
// 可能出现异常的代码
checkUsername("nill");
System.out.println("注册成功");//如果没有异常就是注册成功
} catch(LoginException e) {
//处理异常
e.printStackTrace();
}
}
//判断当前注册账号是否存在
//因为是编译期异常,又想调用者去处理 所以声明该异常
public static boolean checkUsername(String uname) throws LoginException {
for (String name : names) {
if(name.equals(uname)){//如果名字在这里面 就抛出登陆异常
throw new LoginException("亲"+name+"已经被注册了!");
}
}
return true;
}
}