-
方法封装
在编写代码时,如果我们对一个属性使用public访问控制符,那么这个属性会对后来的使用者完全公开,可以随意对其赋值,可能违背了我们的初衷。这时我们就需要进行封装。
public class Student {
private int age; //使用private限制外部随意更改age属性
public void setAge(int age) { //创建age的赋值方法
if(age>1&&age<20) { //设置age的范围
this.age=age; //范围内,成功赋值
}else {
System.out.println("年龄无效"); //范围外,输出“年龄无效”
}
}
public int getAge() { //创建age值获取方法
return age; //返回age值
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setAge(40); //使用者用setAge方法赋值
System.out.println(student.getAge()); //使用者利用getAge方法输出age
}
}
在这段代码中,使用者赋值超出age的限定范围,编译器会报错
按照我们的想法告诉了使用者年龄无效,虽然能让使用者明白他的赋值出了错,但是缺少具体的原因,对于帮助他更好地赋值并没有很大的作用,因此我们需要使用异常的另一种解决方式:抛出异常。
-
抛出异常
throw用于抛出具体异常类的对象,一般用于方法体中。
什么时候使用:当所写的代码因不满足某些条件致使程序无法运行时可以借助throw抛出一个异常对象提醒程序员。
例如
public class Student {
private int age;
public void setAge(int age) {
if(age>1&&age<20){
this.age=age;
}else{
throw new NullPointerException("年龄无效"); //使用throw关键字抛出异常
}
}
public int getAge() {
return age;
}
}
我们可以使用throw+new+异常类型名("想要提示的话“)来抛出异常来提醒使用者异常原因。
使用者视角
显然,这样就可以直观地找到问题所在,方便使用者改正。
但是有一点需要注意的就是我们所抛出的异常类型NullPointerException并不是准确的异常类型,使用者仍然可能感到迷惑,为此,我们需要自定义异常类型。
-
自定义异常类型
为什么?
Java API提供的已有异常类无法准确表述当前发生的异常问题,这时就需要创建自定义的异常。
怎么做?
创建继承Exception 或其子类的自定义类;
自定义异常类调用父类构造函数(通常是含有一个String类型参数的构造函数);
public class AgeException extends Exception { //创建自定义类继承异常类型
/**
*
*/
private static final long serialVersionUID = -4363028028031330605L;
//编译器会提示缺少UID,此时我们只要点击其展开选项中第二个就会自动生成UID
public AgeException(String message) { //创建自定义异常处理方法
super(message);
}
}
相应的,我们需要更改原有代码来应用这个自定义异常类型
使用者视角
-
throw关键字
throw关键字既可以将异常抛给对象也可以抛给自己:
抛给自己:
用try catch语句将异常抛给自己,将异常内部消化。
抛给对象:
如果我们将异常抛给方法调用者的话,那么方法调用者可以使用try catch语句自行处理异常,当然也可以继续上抛异常,而上抛异常需要使用到throws关键字(有别于throw关键字)
-
throws关键字
throws用于声明方法可能抛出的异常,其后为异常类,可以有多个,异常类之间用英文逗号间隔。
什么时候使用:
当方法体中的throw关键字抛出由检查时异常创建的对象时,如果该异常对象在抛出的同时已经通过try-catch进行了处理,则可以不使用throws,否则必须使用throws抛出创建该对象的异常类或其父类。
所调用的方法抛出了检查时异常时,如果该方法在调用的同时已经通过try-catch进行了处理,则可以不使用throws继续上抛该异常,否则必须使用throws才能上抛该异常,此时上抛的异常类可以是调用方法时方法抛出的异常类也可以是其父类。
例如
这段代码中我们使用throw抛出异常,但并没有使用try catch语句捕获这个异常,那么实际上这个异常并没有得到解决,此时我们就需要在方法的参数列表后使用throws关键字将异常抛出
相对的,如果异常已经被try catch捕获,那么我们没有必要再使用throws关键字上抛异常。
-
throw和throws的区别
抛出的东西不同:throw抛出的是具体的异常对象,而throws抛出的是抽象的异常类;
使用位置不同:throw一般用在方法体中,也可用在代码块中,但是如果抛出的是检查时异常类创建的对象,则必须使用try-catch自行处理;throws只能用在方法声明括号后面;
-
注意事项
①如果异常对象为运行时,则方法参数列表后面可以不使用throws,也可以将异常抛给方法调用者或者try-catch内部消化
这是由于异常类型本身所决定的,由于其是运行时异常,那么可以正常编译,可以说,如果没有方法调用者来非法运行,这个异常永远不会发生。所以我们可以单单使用throw关键字将异常抛给方法调用者,待其自己解决。
②如果异常对象为检查时,则方法参数列表后面必须使用throws抛出创建该对象的类;如果没有使用throws抛出那么必须try-catch内部消化。
这是由于检查时异常发生在方法调用者非法运行之前,编译时就会报错,那么我们必须在编写的时候就将异常抛出或者捕获。