首页 > 编程笔记 > Java笔记 阅读:11

Java throws和throw的区别(附带实例)

Java 程序中,throw 关键字的作用如其名,即抛出异常。如果某个方法的某处被明确认定需要产生某种异常,那么可以在该处通过 throw 关键字来抛出某个异常对象。

在程序中手动抛出某个异常时的代码如下:
throw new XXXException();
throw new xxxException("异常信息")

下面程序展示了如何通过 throw 关键字来抛出异常,我们在 getNameByIndex() 方法中会对传入的索引进行判断,如果索引为负数或者超过最大索引则会抛出 IndexOutOfBoundsException 异常,同时包括相关的异常提示信息。
public class ExceptionTest {
    public static String[] Names = { "Tom", "Lucy", "Sam", "Lily", "Ryan" };

    public static void main(String[] args) {
        System.out.println(getNameByIndex(0));
        System.out.println(getNameByIndex(-3));
        System.out.println(getNameByIndex(5));
    }
    
    public static String getNameByIndex(int index) {
        if (0 > index)
            throw new IndexOutOfBoundsException("index can't be a negative");
        if (index > (Names.length - 1))
            throw new IndexOutOfBoundsException("out of maximum index.");
        return Names[index];
    }
}
输出如下:
Tom
Exception in thread "main" java.lang.IndexOutOfBoundsException: index can't be a negative
at com.java.exception.ExceptionTest15.getNameByIndex(ExceptionTest15.java:14)
at com.java.exception.ExceptionTest15.main(ExceptionTest15.java:8)
注意,当第一个异常抛出后由于程序没有捕获到异常,因此不会继续往下执行,最终终止运行。

Java throws关键字

throws 与 throw 只差了一个字母 s,两者容易混淆。throws 关键字用于声明某个方法可能会抛出某种异常,这样就能提示编程人员在使用该方法时要处理对应的异常,如果不处理则无法通过编译。

throws 的语法如下:
访问修饰符 返回类型 方法名(参数列表) throws 异常类1,异常类2,...{
    方法体
}
其实就是在定义方法时在参数列表后面加上“throws 异常类”,如果有多个异常类则使用逗号分隔,这样便完成了抛出异常的声明。当别人使用该方法时就必须要处理该异常,否则将无法通过编译。

下面实例在 test() 方法后面声明可能抛出 IOException 异常:
public class ExceptionTest {
    public static void main(String[] args) {
        try {
            test();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void test() throws IOException {
        throw new IOException("IO异常");
    }
}
test() 方法中通过 throw 抛出 IOException 异常,这样在使用 test() 方法时就可以使用 try-catch 组合来捕获异常并对其进行处理。

多个异常的声明也类似,在方法后面使用 throws 声明多个异常类,异常类之间通过逗号进行分隔:
public class ExceptionTest {
    public static void main(String[] args) {
        try {
            test(false);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
           e.printStackTrace();
        }
    }

    public static void test(boolean flag) throws IOException, SQLException {
        if (flag == true)
           throw new IOException("IO异常");
        else
           throw new SQLException("SQL异常");
    }
}
当我们调用对应的方法时就可以使用 try-multi-catch 组合来分别处理不同的异常。

我们知道,Java 异常类分为运行时异常和非运行时异常,运行时异常都继承自 RuntimeException 类,而非运行时异常则不继承该类。如果某个方法抛出的是运行时异常,就可以不必使用 throws 来声明异常,编译时也不会报错。而非运行时异常则必须通过 throws 来声明,否则将导致编译时报错。

看下面的实例:
public class ExceptionTest {
    public static void main(String[] args) {
        divide(3, 1);
        divide(3, 0);
    }
    
    public static float divide(int a, int b) {
        if (b == 0)
            throw new ArithmeticException("除数不能为0!");
       return a / b;
    }
}
执行程序后输出如下报错信息并终止运行:

Exception in thread "main" java.lang.ArithmeticException: 除数不能为0!
at com.java.exception.ExceptionTest.divide(ExceptionTest.java:12)
at com.java.exception.ExceptionTest.main(ExceptionTest.java:7)

实例中,由于 ArithmeticException 是一个运行时异常,因此 divide() 方法可以不使用 throws 声明异常,当 main() 方法调用 divide() 方法时也可以不使用 try-catch 组合来捕获异常,这是因为编译器无法检查运行时异常,无法强制必须处理异常。

但是如果异常属于非运行时异常,就必须要声明且在调用的地方使用 try-catch 组合捕获异常并处理,否则将无法通过编译。回到前面这个例子,因为 IOException 异常是非运行时异常,所以 test() 方法必须通过 throws 来声明异常,而且在 main() 方法中调用 test() 方法时也必须使用 try-catch 组合来捕获异常并处理,如下面的实例所示,编译器会强制要求这样做。
public class ExceptionTest {
    public static void main(String[] args) {
        try {
            test();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   
    public static void test() throws IOException {
       throw new IOException("IO异常");
    }
}

相关文章