详述throw与throws
一、关键字throw
1、作用
throw用于抛出具体异常类的对象,一般用于方法体中。
throws用于声明方法可能抛出的异常,其后为异常类,可以有多个,异常类之间用英文逗号间隔。
2、什么时候使用?
当所写的代码因不满足某些条件致使程序无法运行时可以借助throw抛出一个异常对象提醒程序员。
public class Student {
public int age;
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.age = 150;
System.out.println(student.age);
}
}
如果该变量为public级别的变量,则定义Student类的程序员无法对该变量的范围进行有效的约束。为了防止调用Student类的程序员对age随意赋值,则可利用封装即用公共方法操作私有变量的方式给一个对象的属性赋值。
public class Student {
private int age;
public void setAge(int age) {
if (age>=1 && age<=20) {
this.age = age;
}else {
System.out.println("年龄无效");
}
}
public int getAge() {
return age;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setAge(100);
System.out.println(student.getAge());
}
}
这种提示错误的方式对于调用该方法的程序员没有什么过多的直接的帮助,因为该程序员根本就不知道哪行代码错了,错在哪里这时候,关键字throw就派上了用场,可以利用throw 异常对象的方式找到异常代码,如下例:
public class Student {
private int age;
public void setAge(int age) {
if (age>=1 && age<=20) {
this.age = age;
}else {
System.out.println("年龄无效");
throw new NullPointerException("年龄无效");
}
}
public int getAge() {
return age;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setAge(100);
System.out.println(student.getAge());
}
}
“throw new NullPointerException("年龄无效");”程序中抛出一个空指针异常对象,虽然可以指出异常的位置但会出现词不达意的现象,因为程序明明是年龄异常,但却抛出了空指针异常。可以利用自定义异常类的方式解决这个问题,如何创建自定义异常类见下文。
3、如何使用throw
①自定义类是运行时异常
package com.baidu;
import com.jd.AgeException;
public class Student {
private int age;
public void setAge(int age) {
if (age>=1 && age<=20) {
this.age = age;
}else {
System.out.println("年龄无效");
throw new AgeException("年龄无效");
}
}
public int getAge() {
return age;
}
}
package com.jd;
public class AgeException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
package com.baidu;
import com.jd.AgeException;
public class Test {
public static void main(String[] args) {
Student student = new Student();
try {
student.setAge(100);
} catch (AgeException e) {
System.out.println("AAAAAAAA");
e.printStackTrace();
}
System.out.println(student.getAge());
}
}
该程序中Student类将AgeException异常抛给方法调用者,同样你也可以利用try-catch语句抛给自己,见下例:
package com.baidu;
import com.jd.AgeException;
public class Student {
private int age;
public void setAge(int age) {
if (age>=1 && age<=20) {
this.age = age;
}else {
System.out.println("年龄无效");
try {
throw new AgeException("年龄无效");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
public int getAge() {
return age;
}
}
package com.jd;
public class AgeException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
package com.baidu;
import com.jd.AgeException;
public class Test {
public static void main(String[] args) {
Student student = new Student();
try {
student.setAge(100);
} catch (AgeException e) {
System.out.println("AAAAAAAA");
e.printStackTrace();
}
System.out.println(student.getAge());
}
}
这时,因为这个异常在Student类的setage方法中已经被捕获所以该异常不会再往上抛,方法调用者中try-catch语句不会执行。
②自定义类时检查时异常
package com.baidu;
import com.jd.AgeException;
public class Student {
private int age;
public void setAge(int age) throws AgeException {
if (age>=1 && age<=20) {
this.age = age;
}else {
throw new AgeException("年龄无效");
}
}
public int getAge() {
return age;
}
}
package com.jd;
public class AgeException extends Exception{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
import com.jd.AgeException;
public class Test {
public static void main(String[] args) {
Student student = new Student();
try {
student.setAge(100);
} catch (AgeException e) {
System.out.println("AAAAAAAA");
e.printStackTrace();
}
System.out.println(student.getAge());
}
}
AgeException异常类是检查时异常,当Student类将该异常抛给方法调用者时,需要在该方法参数列表后面加上关键字throws,throws后面写该异常类类名。
你也同样可以利用try-catch语句将该异常抛给自己
package com.baidu;
import com.jd.AgeException;
public class Student {
private int age;
public void setAge(int age) throws AgeException {
if (age>=1 && age<=20) {
this.age = age;
}else {
try {
throw new AgeException("年龄无效");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
public int getAge() {
return age;
}
}
package com.jd;
public class AgeException extends Exception{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
import com.jd.AgeException;
public class Test {
public static void main(String[] args) {
Student student = new Student();
try {
student.setAge(100);
} catch (AgeException e) {
System.out.println("AAAAAAAA");
e.printStackTrace();
}
System.out.println(student.getAge());
}
}
同样,这时,因为这个异常在Student类的setage方法中已经被捕获所以方法调用者中try-catch语句不会执行。
二、自定义异常类
•为什么?
ØJava API提供的已有异常类无法准确表述当前发生的异常问题,这时就需要创建自定义的异常。
•怎么做?
Ø创建继承Exception 或其子类的自定义类;
Ø自定义异常类调用父类构造函数(通常是含有一个String类型参数的构造函数);
例如为了解决上述问题,我们可以自定义一个AgeException类
public class AgeException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
自定义异常类构造方法中调用父类一个含有String类型的构造方法,使得错误信息能在异常类对象printStackTrace方法和getMessage方法中使用。程序中定义的AgeException异常类是一个运行时异常。
你也可以定义为检查时异常
public class AgeException extends Exception{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
三、关键字throws
1、作用
•throws用于声明方法可能抛出的异常,其后为异常类,可以有多个,异常类之间用英文逗号间隔。
2、什么时候用?
①当方法体中的throw关键字抛出由检查时异常创建的对象时,如果该异常对象在抛出的同时已经通过try-catch进行了处理,则可以不使用throws,否则如果该异常是检查时异常时必须显式使用throws抛出创建该对象的异常类或其父类,如果该异常是运行时异常时,throws可以不写,但默认有。
②所调用的方法抛出了检查时异常时,如果该方法在调用的同时已经通过try-catch进行了处理,则可以不使用throws继续上抛该异常,否则必须使用throws才能上抛该异常,此时上抛的异常类可以是调用方法时方法抛出的异常类也可以是其父类。
例子见上文
四、throw与throws的区别
1、抛出的东西不同:throw抛出的是具体的异常对象,而throws抛出的是抽象的异常类;
2、使用位置不同:throw一般用在方法体中,也可用在代码块中,但是如果抛出的是检查时异常类创建的对象,则必须使用try-catch自行处理因为throws只能用在方法声明括号后面;
如下程序中在Test类非静态代码块中,不能使用throws向上抛出异常,只能利用try-catch语句自己处理异常。
public class Student {
private int age;
public void setAge(int age) throws AgeException {
if (age>=1 && age<=20) {
this.age = age;
}else {
throw new AgeException("年龄无效");
}
}
public int getAge() {
return age;
}
}
package com.jd;
public class AgeException extends Exception{
/**
*
*/
private static final long serialVersionUID = -1005402126688329133L;
public AgeException(String message) {
super(message);
}
}
package com.baidu;
import com.jd.AgeException;
public class Test {
{
int age = 12;
if(age == 12) {
try {
throw new AgeException("");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Student student = new Student();
try {
student.setAge(100);
} catch (AgeException e) {
System.out.println("AAAAAAAA");
e.printStackTrace();
}
System.out.println(student.getAge());
}
}