简单的封装:
在类中的成员变量,如果是public修饰的,则不容易限制其他类中对其操作的范围,此时为了限制一个与需求相对应的合理范围,就可以用封装。
//例:
public class Student {
private int age;//声明一个私有成员属性age
public void setAge(int age){
if(age>0 && age<28){
this.age=age;
}else{
System.out.println("无效");
}
}//定义一个公共方法对age进行赋值,且限定范围
public int getAge(){
return age;
}//定义一个公共方法得到age的值
}
public class Test{
public static void main(String [] args){
Student student=new Student();
student.setAge(40);//对age进行不符合要求操作
System.out.println(student.getAge());//得到当前age值
}
}
/*运行结果:
无效
0*/
- 通过上述实例,我们发现封装可以有效的对操作进行规范。
- 但是,在其他人得到“失效”后,不知道原因,不知道源代码在哪里
这时我们可以使用throw抛出一个异常
throw(抛出异常对象)
public void setAge(int age){
if(age>0 && age<28){
this.age=age;
}else{
throw new NullPointerException("无效");//抛出一个空指针异常对象
}
}//改写原Student类中的setAge方法
/*Test类不变运行结果:
Exception in thread "main" java.lang.NullPointerException: 无效
at Student.setAge(Student.java:10)
at Test.main(Test.java:7)*/
- throw关键字可以抛出一个异常对象,这时我们可以在控制台看到,所在语句的位置。
- 但是,很明显这种限制方式并不是产生了空指针异常,而是为了抛出一个异常而选择空指针。
为了使这个过程更符合情理且更容易准确辨别,我们可以构造一个自定义异常类。
自定义异常类
- 延续上例,我们自定义一个AgeException类
public class AgeException extends RuntimeException{
private static final long serialVersionUID = -1337582885342407212L;
public AgeException(String message) {
super(message);
}//调用父类有参构造方法(本例这一个就够,如果需要可以多选或定义)
}//AgeException继承运行时异常类,可用父类方法
- 这时候,我们就有一个自定义的异常,AgeException(年龄异常)。此时,我们再去改写Student类setAge方法
public void setAge(int age){
if(age>0 && age<28){
this.age=age;
}else{
throw new AgeException("无效");//抛出一个年龄异常对象(通常异常类独在一个包中,这时这里需要引包)
}
}
/*Test类不变运行结果:
Exception in thread "main" exception.AgeException: 无效
at Student.setAge(Student.java:12)
at Test.main(Test.java:7)*/
- 这时,进行错误操作时,就能清楚是什么错,在哪,该怎么做。
那么,如果需要一个检查时异常呢?
throws
我们可以将AgeException该为检查时异常类,我们知道,Exception下非运行时异常都为检查时异常,所以我们只需要让AgeException继承Exception即可,此时AgeException和RuntimeException为Exception的同级子类。
public class AgeException extends Exception{ //继承Exception类
private static final long serialVersionUID = -1337582885342407212L;
public AgeException(String message) {
super(message);
}
}// AgeException类改为检查时异常类
此时我们会发现,Student类中,抛出异常语句已经报错,因为检查时异常只有两种处理方式:
①一直上抛(将异常抛给方法调用者)到Jvm;
②在Jvm前,程序通过try、catch解决掉。
- 如何上抛:
改写Student类setAge方法
public void setAge(int age){
if(age>0 && age<28) throws AgeException{//抛出检查时异常类
this.age=age;
}else{
throw new AgeException("无效");
}
}
-
如果方法要上抛出一个异常类,则:
在方法参数列表()后,方法体{}前写:throws 异常类名1,异常类名2,… -
此处我们也可以直接在抛出后,直接解决异常,即在setAge方法中,直接使用try、catch:
public void setAge(int age){
if(age>0 && age<28) throws AgeException{//抛出检查时异常类
this.age=age;
}else{
try {
throw new AgeException("无效");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
这种情况下,异常已经解决。
- 如果选择将异常上抛到Test类main函数中,则要么继续抛出异常类给Jvm(例1)、或者将异常在main函数中解决掉(例二)。
//例一
public class Test{
public static void main(String [] args) throws AgeException {//抛出存在检查时异常类
Student student=new Student();
student.setAge(40);//检查时异常
System.out.println(student.getAge());
}
}
//例二
public class Test{
public static void main(String [] args){
Student student=new Student();
try {
student.setAge(40);
} catch (AgeException e) {
e.printStackTrace();
}//使用try、catch解决异常
System.out.println(student.getAge());
}
}
throw与throws的区别:
- throw用于抛出异常对象:
1、如果异常对象为运行时,则方法参数列表后面可以不是使用throws,也可以将异常抛给方法调用者;try、catch
2、如果异常对象为检查时,则方法参数列表后面必须使用throws抛出创建该对象的类;如果没有throws 必须try-catch - 抛出的东西不同:throw抛出的是具体的异常对象,而throws抛出的是抽象的异常类;
- 使用位置不同:throw一般用在方法体中,也可用在代码块中,但是如果抛出的是检查时异常类创建的对象,则必须使用try-catch自行处理;throws只能用在方法声明括号后面;