【JAVA SE】—— 异常(下)

简介: 【JAVA SE】—— 异常(下)

四、异常的体系结构

Java 内置了丰富的异常体系, 用来表示不同情况下的异常.
下图表示 Java 内置的异常类之间的继承关系

【JAVA SE】—— 异常 _异常体系、_07

顶层类 Throwable 派生出两个重要的子类, ErrorException

其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,
除了告知用户并使程序终止之外, 再无能为力. 这种情况很少出现.

Exception 是我们程序猿所使用的异常类的父类.

其中 Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常类
NullPointerException , IndexOutOfBoundsException 等.

Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为 非受查异常, 所有的其他异常称为 受查异常.

如果一段代码可能抛出受查异常,必须显式处理


受查异常与非受查异常

【JAVA SE】—— 异常 _自定义异常_08

Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查异常, 所有的其他异常称为受查异常。如果一段代码可能抛出 受查异常, 那么必须显式进行处理

public static void main(String[] args) { 
 System.out.println(readFile()); 
} 
public static String readFile() { 
 // 尝试打开文件, 并读其中的一行. 
 File file = new File("d:/test.txt"); 
 // 使用文件对象构造 Scanner 对象. 
 Scanner sc = new Scanner(file); 
 return sc.nextLine(); 
}
// 编译出错
Error:(13, 22) java: 未报告的异常错误java.io.FileNotFoundException; 必须对其进行捕获或声明以便抛出

如 FileNotFoundException 这样的异常就是受查异常,如果不显式处理, 编译无法通过,显式处理的方式有两种:


1.使用 try catch 包裹起来

因为在输入给sc时可能会出错,因此可以用try catch捕捉,此处虽然运行时可能会报错,但是会编译通过。这就是处理异常的好处。

public static void main(String[] args) { 
 System.out.println(readFile()); 
} 
public static String readFile() { 
 File file = new File("d:/test.txt"); 
 Scanner sc = null; 
 try { 
 sc = new Scanner(file); 
 } catch (FileNotFoundException e) { 
 e.printStackTrace(); 
 } 
 return sc.nextLine(); 
}

2.在方法上加上异常说明, 相当于将处理动作交给上级调用者

使用throws说明异常,则不需要在readFile方法内部使用try catch捕捉异常。如果main方法没有使用try catch捕捉异常则交给JVM处理,否则是自己捕捉异常。

public static void main(String[] args) { 
 try { 
 System.out.println(readFile()); 
 } catch (FileNotFoundException e) { 
 e.printStackTrace(); 
 } 
} 
public static String readFile() throws FileNotFoundException { 
 File file = new File("d:/test.txt"); 
 Scanner sc = new Scanner(file); 
 return sc.nextLine(); 
}

【JAVA SE】—— 异常 _java_09


五、自定义异常类

Java 中虽然已经内置了丰富的异常类, 但是我们实际场景中可能还有一些情况需要我们对异常类进行扩展, 创建符合我们实际情况的异常

注意:

  1. 自定义异常类继承Exception类默认是受查异常
  2. 继承RuntimeException类默认是非受查异常。

用户登录代码实例

public class Test {
    private static final String userName = "author";
    private static final String password = "12138";

    public static void login(String userName, String password) {
        if(!Test.userName.equals(userName)){// 用户名不相同,进入if语句
            System.out.println("用户名输入错误!");
        }
        if (!Test.password.equals(password)){
            System.out.println("password输入错误!");
        }
    }

    public static void main(String[] args) {
        login("author","12138");
    }
 }

我们的想法是将自定义一个用户登录错误异常

此处一个异常类继承Exception还是RuntimeException的意义:
我们来举个例子:
假设自定义异常类继承的都是RuntimeException,则此处编译时不会报错,因为继承RuntimeException是非受查异常,则在运行时才会报错。
代码1:

class NameException extends RuntimeException {
    public NameException(String name) {
        super(name);
    }
}
class PassWordException extends RuntimeException {
    public PassWordException(String message) {
        super(message);
    }
}
public class Test {
    private static String name = "hhh";
    private static String password = "1234";

    public static void login(String name, String password) throws NameException, PassWordException {
        if (!Test.name.equals(name)) {
            throw new NameException("名字错误");
        }
        if (!Test.password.equals(password)) {
            throw new PassWordException("密码错误");
        }
    }

    public static void main(String[] args) {
        login("hhh", "123");
    }
}

【JAVA SE】—— 异常 _异常捕捉_10

假设自定义异常类继承的都是Exception,则默认自定义异常类为受查异常,再用上面的代码,只将自定义继承改为Exception。则编译时期就会报错。

class NameException extends Exception {
    public NameException(String name) {
        super(name);
    }
}
class PassWordException extends Exception {
    public PassWordException(String message) {
        super(message);
    }
}
public class Test {
    private static String name = "bit";
    private static String password = "1234";

    public static void login(String name, String password) throws NameException, PassWordException {
        if (!Test.name.equals(name)) {
            throw new NameException("名字错误");
        }
        if (!Test.password.equals(password)) {
            throw new PassWordException("密码错误");
        }
    }

    public static void main(String[] args) {
        login("bit", "123");
    }
}

因为受查异常要用两种显示的方式进行处理,要不用try catch语句处理,要不抛出异常用throw和throws成对处理。

对于为何自定义一个异常类需要在构造方法中调用父类的构造方法。是因为我们可以在throw new NameException();时能够在括号中说明错的原因。而输入错的原因时又是一个字符串。我们在看Exception异常类的源码时,可以看到它也是继承了Throwable类。而其中也调用了构造方法。我们也已经知道了一个子类的构造方法是默认一个不带参数的调用父类的构造方法的。因此一切都能说通了。

【JAVA SE】—— 异常 _自定义异常_11


【JAVA SE】—— 异常 _异常_12


注意事项:

自定义异常通常会继承自 Exception 或者 RuntimeException
继承自 Exception 的异常默认是受查异常
继承自 RuntimeException 的异常默认是非受查异常.


目录
相关文章
|
2月前
|
Java
java自定义Service的异常
java自定义Service的异常
15 0
|
8天前
|
Java 程序员 编译器
|
10天前
Swagger2异常:java.lang.NumberFormatException: For input string: ““
Swagger2异常:java.lang.NumberFormatException: For input string: ““
17 1
|
11天前
|
存储 Java 程序员
JavaSE&Java的异常
JavaSE&Java的异常
23 0
|
22天前
|
Java 开发者
Java中的受检异常和非受检异常的区别
Java中的受检异常和非受检异常的区别
|
27天前
|
Java
Java中的异常类总结
Java中的异常类总结
|
2月前
|
SQL Java
java中的异常
java中的异常
10 1
|
2月前
|
Java 程序员 编译器
Java中异常
Java中异常
12 0
|
2月前
|
Java 程序员 编译器
Java中的异常
Java中的异常
9 0
|
2月前
|
Java
Java异常的抛出
Java异常的抛出
10 0