java中的异常你真的清楚了吗??

/ 默认分类 / 0 条评论 / 885浏览

java中异常详细分析

1. java中异常的继承实现图

继承关系图

    从图中也可以明显看出,java中的异常(程序运行过程中出现的意料之外或程序没有正常运行的突发情况)包括Error和Exception两个类,他们都是继承自Throwable,下面我们来看一下Throwable,下面是其中的注释信息

* The {@code Throwable} class is the superclass of all errors and
* exceptions in the Java language. Only objects that are instances of this
* class (or one of its subclasses) are thrown by the Java Virtual Machine or
* can be thrown by the Java {@code throw} statement. Similarly, only
* this class or one of its subclasses can be the argument type in a
* {@code catch} clause.

    这里说明了只有Throwable的子类才可以在jvm中被throw语句抛出,才可以作为catch语句的参数,所以无论什么异常,都是需要继承Throwable,因为这样才能使这个异常起作用,毕竟最终都是需要通过抛出或者捕捉的.

2.java中异常的大致分类

    最多的说法就是异常分为检查异常和非检查异常,详细信息如下:

下面是jdk注释中对checked Exception和unchecked Exception进行的解释


/**
 * {@code RuntimeException} is the superclass of those
 * exceptions that can be thrown during the normal operation of the
 * Java Virtual Machine.
 *
 * <p>{@code RuntimeException} and its subclasses are <em>unchecked
 * exceptions</em>.  Unchecked exceptions do <em>not</em> need to be
 * declared in a method or constructor's {@code throws} clause if they
 * can be thrown by the execution of the method or constructor and
 * propagate outside the method or constructor boundary.

 */
public class RuntimeException extends Exception {

/**
 * The class {@code Exception} and its subclasses are a form of
 * {@code Throwable} that indicates conditions that a reasonable
 * application might want to catch.
 *
 * <p>The class {@code Exception} and any subclasses that are not also
 * subclasses of {@link RuntimeException} are <em>checked
 * exceptions</em>.  Checked exceptions need to be declared in a
 * method or constructor's {@code throws} clause if they can be thrown
 * by the execution of the method or constructor and propagate outside
 * the method or constructor boundary.

 */
public class Exception extends Throwable {

也就是说,检查异常抛出的时候,所在方法A一定要声明抛出该异常,所以在其他方法中使用这个方法A就一定要处理异常,否则编译不通过;但是如果是非检查异常,所在方法A就不需要声明抛出该异常,所以在其他方法中使用方法A就不需要强制进行异常处理编译也可以进行,当然在运行时候就可能出现抛出这样的异常的信息;

3.案例分析

先来看一个java中原有的检查异常

 public FileReader(String fileName) throws FileNotFoundException {
        super(new FileInputStream(fileName));
    }
    
    
 public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }


public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
        //就是在这里抛出的
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.attach(this);
        path = name;
        open(name);
    }

我们看一下这个FileNotFoundException

可以发现它不是RuntimeException的子类,所以检查异常都是需要强制处理,否则编译不通过

再来看一个自定义异常

public class ZuoException extends RuntimeException {

    public ZuoException(String msg) {
        super(msg);
    }
}


public class DaHuiUtil {

    public static void sayHello(String word)  {
        if(word.contains("脏话"))
        {
            throw new ZuoException("这不是打招呼的话");
        }
        System.out.println(word);
    }
}


public class Test {
    public static void main(String[] args)  {
        DaHuiUtil.sayHello("脏话");
    }
}

这样是可以编译通过的,并且运行正常抛出:

Exception in thread "main" ws.exception.ZuoException: 这不是打招呼的话
	at ws.test.DaHuiUtil.sayHello(DaHuiUtil.java:14)
	at ws.test.Test.main(Test.java:12)

因为自定义的异常继承自RuntimeException

如果我们改为

public class ZuoException extends Exception {

    public ZuoException(String msg) {
        super(msg);
    }
}

这样我们就必须抛出时,在外部方法声明抛出,这样其他使用该方法的类中就需要处理完这个异常才可以编译通过

如果再改为:

public class ZuoException extends Error {

    public ZuoException(String msg) {
        super(msg);
    }
}

这样就又不需要强制处理这个异常也可以直接变异通过

4.总结