throw和throws关键字
一、throw关键字
throw 用于抛出具体异常类的对象,一般用于方法体中;当所写的代码因不满足某些条件致使程序无法运行时,可以借助throw抛出一个异常对象提醒程序员。
throw关键字也可以用在代码块中,但如果代码块中抛出的异常对象是由检查时异常创建的,则必须使用try-catch进行处理;
使用throw抛出异常对象如果没有try-catch捕获该异常对象,则该抛出异常对象语句执行后其所在方法结束执行。
二、throws关键字
throws用于声明方法可能抛出的异常,其后为异常类,可以有多个,异常类之间用英文逗号间隔
当方法体中的throw关键字抛出由检查时异常创建的对象时,如果该异常对象在抛出的同时已经通过try-catch进行了处理,则可以不使用throws,否则必须使用throws抛出创建该对象的异常类或其父类。
所调用的方法抛出了检查时异常时,如果该方法在调用的同时已经通过try-catch进行了处理,则可以不使用throws继续上抛该异常,否则必须使用throws才能上抛该异常,此时上抛的异常类可以是调用方法时方法抛出的异常类也可以是其父类。
三、throw、throws区别
抛出的东西不同:throw抛出的是具体的异常对象,而throws抛出的是抽象的异常类;
使用位置不同:throw一般用在方法体中,也可用在代码块中,但是如果抛出的是检查时异常类创建的对象,则必须使用try-catch自行处理;throws只能用在方法声明括号后面;
自定义异常类
一、为什么
1、Java API提供的已有异常类无法准确表述当前发生的异常问题
2、由于java封装的特性,多数方法和属性不会直接暴露,查找异常代码的位置会非较为繁琐,通过throws/throw异常,可以直接从控制台上获取到异常的位置
二、怎么做
1、创建继承Exception 或其子类的自定义类;
2、自定义异常类调用父类构造函数(通常是含有一个String类型参数的构造函数);
自定义异常类使用示例
public class Test {
public static void main(String[] args) {
Student stu=new Student();
stu.setAge(10000);
System.out.println(stu.getAge());
}
}
class Student {
private int age;
public int getAge() {
return age;
}
public void setAge(int age)throws AgeException{
if(1<=age&&age<=150) {
this.age=age;
}else {
throw new AgeException("age范围:1~150!");
}
}
}
class AgeException extends RuntimeException{
AgeException (String message){ //定义构造方法
super(message); //使用super关键字调用父类构造方法
}
}
控制台输出结果:
Exception in thread "main" com.bugOpe.AgeException: age范围:1~150!
at com.bugOpe.Student.setAge(Test.java:21)
at com.bugOpe.Test.main(Test.java:6)
如果不使用super关键字,则调用父类无参构造方法,没有参数传入,则最终控制台不会输出throw关键字之后对象的参数内容
控制台输出结果:
Exception in thread "main" com.bugOpe.AgeException
at com.bugOpe.Student.setAge(Test.java:21)
at com.bugOpe.Test.main(Test.java:6)
备注:
如果是运行时异常,自定义异常类直接或间接继承自RuntimeException,可以暂时不处理;如果是直接继承的Exception,则为检查时异常,但需要显式处理,必须使用try-catch捕获或者throws抛出;
抛出的异常时运行时异常可以不使用throws,检查时异常必须显式使用throws;
throw语句不能连续出现,使用eclipse时会发现会提示不可达的错误,原因出现异常时会导致程序终止,类似于return;
如果方法中的异常已经通过try-catch进行了捕获则无需再使用throws上抛该异常了,否则即使上抛也无效,只会做无用功。
代码示例如下
public class Test {
public static void show(int age) throws PrinteException{
if(age<0||age>150){
try {
throw new PrinteException("操作失败:年龄取值范围为0~150");
} catch (PrinteException e) {
System.out.println("show方法");
e.printStackTrace();
}
return;
}
System.out.println(age);
}
public static void main(String[] args) {
try {
show(1000);
} catch (PrinteException e) {
System.out.println("main方法");
e.printStackTrace();
}
}
}
class PrinteException extends RuntimeException{
PrinteException(String e){
super(e);
}
}
控制台输出结果
show方法
com.bugOpe.PrinteException: 操作失败:年龄取值范围为0~150
at com.bugOpe.Test.show(Test.java:7)
at com.bugOpe.Test.main(Test.java:18)
此处异常已经通过try-catch语句进行了处理,所以show方法无需再使用throws抛出异常了,否则即使上抛也无效:
执行代码会发现,即使这里异常被触发了,在main方法中catch依然没有执行,所以此时在通过throws抛出异常类纯属无用功
如果代码量较大使用异常自定义异常类,可以快速的查找出现错误的代码位置,便于错位定位。