1 异常抛出机制
public static void main(String[] args) {
//定义数组
int [] arr = new int[]{100,20,50,40};
//调用方法
int num = getElements(arr,4);
System.out.println(num);
}
/*
* 需求:对给定的数组的下标获取元素
* 参数:传入数组,下标
* 返回结果:元素
*/
public static int getElements(int [] arr,int index){
int element = arr[index];
return element;
}
(1)没有找到下标为4的元素,运行时发生了问题,这个问题java是认识的,并且是可以处理的。java就对这个问题的描述信息有:
问题的名称(下标越界异常),问题的内容(下标4),问题的位置(第18行,第9行)。java就将这些信息直接封装到了对象中,通过这些对象获取这些描述信息。
(2)这个异常对象指的就是new ArrayIndexOutOfBoundsException,是用来描述异常问题的对象。程序执行到第18行时,发现异常问题。Java中解决异常问题的方法是:将问题向上抛给调用者。
throw new ArrayIndexOutOfBoundsException(index))
(3)调用者此时指的就是main主方法。main方法中第9行接收到了异常问题,但main方法也没有能力进行处理。main方法将问题抛给了jvm,jvm进行处理后,就在控制台上将异常问题相关信息告诉我们。
简单总结:异常对象抛出异常返回给调用者,调用者不进行处理,向上返回jvm,Jvm将异常信息反馈到控制台上。
2 调用API文件运行时期异常
java虽然有抛出异常机制,但其抛出的信息并不能完全清晰告诉我们。因此可以使用API来直接调用java封装好的异常对象。
步骤:
(1)先在API中找到适当的异常对象
(2)创建异常对象调用构造方法,封装一些自定义信息
(3)java对异常对象的处理需要暴露出来,反馈(抛)给调用者。
Throw关键字:
用在方法内,抛出异常对象,并结束方法;
public class ExceptionDemo2 {
public static void main(String[] args) {
//定义数组
int [] arr = new int[]{100,20,50,40};
//调用方法
int num = getElements(arr,4);
System.out.println(num);
}
/*
* 为了提高程序的健全性,需要考虑各种情况并作出有效反馈。
* (1)传入的数组对象有可能是null
* (2)传入的index参数小于0或者超过下标
* (3)传入的index在正常范围内
*/
public static int getElements(int [] arr,int index){
if(arr == null){
//调用空指针异常(String s)构造方法
throw new NullPointerException("arr指向为null");
}
if(index<0 || index > arr.length-1 ){
System.out.println("下标错误,请重新输入下标");
//调用数组下标越界异常()
throw new ArrayIndexOutOfBoundsException("下标越界:"+index+",该下标在数组中不存在");
}
int element = arr[index];
return element;
}
3 自定义异常
3.1 自定义异常步骤
类比于API对异常类的封装方法来自定义异常。
(1)编写源码类,根据可能发生的异常,抛出异常对象
throw new 自定义异常类();
若想初始化异常对象内容,异常对象调用有参构造函数。因为有继承,所以有参构造里面要显示定义super(message)。
(2)自定义创建异常类,并提供无参和有参构造方法。
Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是Throwable类(或其Throwable的子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。即自定义类要和Throwable类产生关联。
(3)根据需求选择继承Throwable的哪一个子类
异常有编译时期的异常和运行时期的异常
RuntimeException 是指可能在 Java 虚拟机正常运行期间抛出的异常的超类。继承的子类无需进行声明。
Exception是指那些在编译时期就出现了异常,必须要声明或捕获
(4)编写测试类。
3.2 自定义运行时期异常
(1)自定义异常类(继承运行时期异常类)
// 自定义异常要和Throwable产生关系,调用RuntimeException无需声明。
public class AgeFalseException extends RuntimeException{
public AgeFalseException(){
}
public AgeFalseException(String message){
//super(message);
}
}
(2)类(抛出异常对象,不需要进行声明)
public class Person2 {
// 成员变量
String name;
int age;
// 构造方法
public Person2(String name,int age){
super();
//由于人的年龄是有限制的,因此要进行判断
if(age<=0 || age>150){
// 使用自定义异常,年龄有误,对用户提示年龄有误并停止程序运行
throw new AgeFalseException("对不起,您输入的年龄是"+age+",年龄是非法的参数");
}
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person[name=" + name + "age=" + age + "]";
}
}
(3)测试类
public static void main(String[] args) {
Person2 p = new Person2("coco",-18);
String details = p.toString();
System.out.println(details);
/*控制台输出结果:
* Exception in thread "main" section_01.
* AgeFalseException: 对不起,您输入的年龄是-18,年龄是非法的参数
*/
}
继承RuntimeException类或其子类的运行时期异常,可以不进行声明。因为程序在编译时期正确,只有运行的时候才发生异常,在我们编译时期是不知道异常的,无法提前进行声明。
4 声明和捕获
(1)声明是把问题标识出来告诉调用者
声明是为了让调用者进行处理以及让程序停止,让调用者看到控制台异常信息并进行修改代码。
所有异常(包括运行时期异常)都是可以进行声明的,目的是为了让调用者给出处理方式。声明就相当于给坏面包贴标签,降价处理后告诉消费者。在API中运行时异常如果在方法上throws了异常,说明这个异常是可以捕获进行处理的。
(2)捕获是直接对异常进行处理
Java中对异常有针对性的语句进行捕获。捕获语句后面的代码仍可以继续向下执行。
5 自定义编译时期异常
如果方法内通过throw抛出了编译时期异常,调用者必须要进行声明或者捕获(处理)异常。
5.1 声明的体现
如果定义方法时,有问题发生需要给调用者,可以通过throws关键字进行声明,调用者继续向上声明给jvm虚拟机,虚拟机就可以在控制台反馈异常信息。
/*
* 声明异常
*/
public class ExceptionDemo01 {
//调用者声明异常给jvm虚拟机
public static void main(String[] args) throws Exception {
Demo d = new Demo();
d.show();
}
}
class Demo{
//在方法上定义声明异常
public void show() throws Exception{
throw new Exception("编译时期异常");
}
}
throws关键字必须写到方法的后面,如果有多个异常需要抛出,那么异常之间用逗号分隔。
5.2 异常的捕获
格式:
try{
尝试检测代码
}catch(异常类 变量){
进行处理
}
try{}用来对代码进行检测:
(1)如果代码没有异常发生,就不执行catch语句。
(2)如果代码异常发生才会去执行catch,执行完捕获处理后程序会继续往下执行。
catch(){}用来对异常进行处理。
小括号里面是对方抛出了什么异常,在括号中就定义什么异常类型的引用。
如果一个程序有多个异常需要处理:
(1)多个异常的处理方法也需要对应多个catch(){}语句与之对应,
(2) catch语句也可传入父类型异常类,使用多态的思想可减少catch语句的书写。
(3)如果异常类之间有子父类异常关系,则子类异常类catch语句要在父类异常类前面。因为异常类型的父类,所有异常都可以接收到。
/*
* 捕获异常
*/
public class ExceptionDemo02 {
/* java中提出了针对性的捕获异常语句。程序执行到show()方法时,发生异常。
* throw抛出异常给调用者main主方法中的d.show();
* 因此,我们就对d.show();进行捕获。
*/
public static void main(String[] args) {
//创建对象
Demo2 d = new Demo2();
//调用者捕获异常
try{
d.show();
// Exception e = new Exception
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
class Demo2{
//在方法上声明异常给调用者
public void show( ) throws Exception{
throw new Exception("你好");
}
}
声明和捕获的输出效果:
(1)声明是持续向上抛出给JVM,JVM在控制台上反馈异常信息。
(2)捕获是对异常进行处理,不消用特点的方法不会再控制台上反馈异常信息。