JAVA异常及其异常处理方式

1.什么是异常?

异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。

比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;

如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。

  • 用户输入了非法数据。
  • 要打开的文件不存在。
  • 网络通信时连接中断,或者JVM内存溢出。
  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  • 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

 

2.常见的Exception 类的层次

输入输出异常:IOException

算术异常类:ArithmeticExecption

空指针异常类:NullPointerException

类型强制转换异常:ClassCastException

操作数据库异常:SQLException

文件未找到异常:FileNotFoundException

数组负下标异常:NegativeArrayException

数组下标越界异常:ArrayIndexOutOfBoundsException

违背安全原则异常:SecturityException

文件已结束异常:EOFException

字符串转换为数字异常:NumberFormatException

方法未找到异常:NoSuchMethodException

3.异常处理方式

3.1 通过try、catch捕获异常

try
{
  可能会发生的异常
}catch(异常类型 异常名(变量)){
  针对异常进行处理的代码
}catch(异常类型 异常名(变量)){
  针对异常进行处理的代码
}...
[finally{
  释放资源代码;
}]

package exception;

import java.io.IOException;

/***
 * @ClassName: TestException
 * @Description: TODO
 * @Auther: chujiu
 * @Date: 2020/4/13 7:15
 * @version : V1.0
 */
public class TestException {

    public int method(){
        try {
            int i = 5 / 0;  //算术异常
            System.out.println("无异常");
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("有异常");
            return 2;
        } finally {
            System.out.println("执行fianlly");
            return 3;
        }
    }

    public static void main(String[] args){
        TestException te = new TestException();
        System.out.println(te.method());
    }

}
  • catch 不能独立于 try 存在。
  • 在 try/catch 后面添加 finally 块并非强制性要求的。
  • try 代码后不能既没 catch 块也没 finally 块。
  • try, catch, finally 块之间不能添加任何代码。
  • 首先一个不容易理解的事实:在 try块中即便有return,break,continue等改变执行流的语句,finally也会执行。
  • finally中的return 会覆盖 try 或者catch中的返回值。
  • finally中的return或异常会抑制(消灭)前面try或者catch块中的异常。

3.2 throw关键字抛出异常

指的是在方法中人为抛出一个异常对象(这个异常对象可能是自己实例化或者抛出已存在的);用于抛出异常。

3.3 通过throws抛出异常

用在方法签名中,用于声明该方法可能抛出的异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。

package exception;

import java.io.IOException;

/***
 * @ClassName: TestException1
 * @Description: TODO
 * @Auther: chujiu
 * @Date: 2020/4/13 7:17
 * @version : V1.0
 */
public class TestException1 {

    public static void method2() throws IOException {
        int i = 0;
        if (i == 0) {
            throw new IOException("除以0错误");
        }
        int x = 5 / i;
        System.out.println("无异常");
    }

    public static void method1() {
        try {
            method2();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("有异常");
        } finally {
            System.out.println("执行fianlly");
        }
    }

    public static void main(String[] args) {
        method1();
    }

}

4.自定义异常

自定义的异常应该总是包含如下的构造函数:
一个无参构造函数
一个带有String参数的构造函数,并传递给父类的构造函数。
一个带有String参数和Throwable参数,并都传递给父类构造函数
一个带有Throwable 参数的构造函数,并传递给父类的构造函数。

IOException类的完整源代码:

package java.io;

    public class IOException extends Exception {
        static final long serialVersionUID = 7818375828146090155L;

        public IOException() {
            super();
        }

        public IOException(String message) {
            super(message);
        }

        public IOException(String message, Throwable cause) {
            super(message, cause);
        }

        public IOException(Throwable cause) {
            super(cause);
        }
    }
package exception;

import java.util.Scanner;

/***
 * @ClassName: DemoRegisterException
 * @Description: TODO
 * @Auther: chujiu
 * @Date: 2020/4/13 7:17
 * @version : V1.0
 */
public class DemoRegisterException {
    // 1.使用数组保存已经注册过的用户名(数据库)
    static String[] usernames = {"张三", "李四", "王五"};

    public static void main(String[] args) /*throws RegisterException*/ {
        //2.使用Scanner获取用户输入的注册的用户名(前端,页面)
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您要注册的用户名:");
        String username = sc.next();
        checkUsername(username);

    }

    //3.定义一个方法,对用户输入的中注册的用户名进行判断
    public static void checkUsername(String username) /*throws RegisterException*/ {
        //遍历存储已经注册过用户名的数组,获取每一个用户名
        for (String name : usernames) {
            //使用获取到的用户名和用户输入的用户名比较
            if (name.equals(username)) {
                //true:用户名已经存在,抛出RegisterException异常,告知用户"亲,该用户名已经被注册";
                try {
                    throw new RegisterException("亲,该用户名已经被注册");
                } catch (RegisterException e) {
                    e.printStackTrace();
                    return; //结束方法
                }
            }
        }

        //如果循环结束了,还没有找到重复的用户名,提示用户"恭喜您,注册成功!";
        System.out.println("恭喜您,注册成功!");
    }
}

// 异常类
class RegisterException extends /*Exception*/ RuntimeException {
    //添加一个空参数的构造方法
    public RegisterException() {
        super();
    }

    /*
        添加一个带异常信息的构造方法
        查看源码发现,所有的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理这个异常信息
     */
    public RegisterException(String message) {
        super(message);
    }
}

参考文章:https://www.cnblogs.com/niujifei/p/11452826.html

菜鸟教程传送门

猜你喜欢

转载自www.cnblogs.com/antao/p/12689127.html