异常--异常的使用及异常内部原理

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)捕获是对异常进行处理,不消用特点的方法不会再控制台上反馈异常信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值