JAVA初步学习——第九章 异常

一、异常

  • 程序在运行过程中,由于意外情况导致程序发生异常事件,默认情况下发生的异常会中断程序的运行。
  • 在Java中,把常见的异常情况,都抽象成了对应的异常类型,那么每种异常类型都代表了一种特定的异常情况。
  • 当程序中出现一种异常情况时,也会创建[默认情况是JVM自动创建]并抛出一个异常类型对象,这个对象就表示当前程序所出现的问题。

1.异常体系

  • 异常体系中的根类是: java.lang.Throwable
    • Throwable 表示可以被抛出的
  • 根类下面有俩个子类型:
    • java.lang.Error
      • Error ,表示错误情况,一般是程序中出现了比较严重的问题,并且程序自身并无法进行处理。
    • java.lang.Exception
      • Exception ,表示异常情况,程序中出了这种异常,大多是可以通过特定的方式进行处理和纠正的,并且处理完了之后,程序还可以继续往下正常运行。
      • Exception 中并没有定义方法,它的方法都是从 Throwable 中继承过来的,

Exception常用的方式有:

  • printStackTrace()打印输出当前发送异常的详细信息(重要)
  • getMessage()返回异常对象被抛出的时候,所携带的信息,一般是异常的发生原因(重要)
  • printStackTrace(PrintWriter s),方法重载,可以指定字符输出流,对异常信息进行输出
  • printStackTrace(PrintStream s),方法重载,可以指定字节输出流,对异常信息进行输出

2. 异常的种类和传播

(1)异常的种类
我们平时使用的异常类型,都是 Exception 类的子类型,它们把异常划分成了俩种:

  • 编译时异常(受检异常),继承自 Exception 类,也称为checked exception,编译器在编译期间,会主动检查这种异常,发现后会报错,并提示我们要对这种异常进行处理。
  • 运行时异常(非受检异常),继承自 RuntimeException 类,也称为unchecked exception,编译器在编译期间,不会检查这种异常,也不要求我们去处理,但是在运行期间,代码中可能会抛出这种类型的异常。

(2)异常传播

  • 如果一个方法中抛出了异常,并且一直没有进行处理,那么这个异常将会抛给当前方法的调用者,并一直向上抛出,直到抛给JVM,最后JVM将这个异常信息打印输出,同时程序运行的停止。
  • 如果,在异常传播的过程中,任何一个地方对异常进行了处理,那么JVM不会停止,程序还会正常往下运行!

二、异常处理——抛出

1.自动抛出异常

当前java代码中,出现了提前指定好的异常情况的时候,代码会自动创建异常对象,并且将该异常对象抛出。

  • 算术异常
    • 当代码中执行int a = 1/0; 的时候,代码会自动创建并抛出ArithmeticException类型的异常对象,来表示当前的这种异常情况。
  • 空指针异常
    • 当前代码中执行String str = null; str.toString();的时候,代码会自动创建并抛出NullPointerException类型的异常对象,来表示当前这种异常情况。

2.手动抛出异常

(1)运行时异常
方法中抛出的是一个运行时异常,编译器不会做出检查,所以代码可以正常的编译运行,但是运行的时候,name的值不是tom的时候,代码会报错,这个错误信息是我们自己抛出的

public void test(String name){ 
	if(!"tom".equals(name)){ 
		throw new RuntimeException("用户名和预期不符!"); 
	} 
}

(2)编译异常

  • 方法中抛出的异常是编译异常,编译器会做检查,所以代码编译会报错,提示我们需要在test方法上声明出方法内抛出异常的类型,或者在方法内对这个异常进行处理!
public void test(String name){ 
	if(!"tom".equals(name)){ 
		throw new Exception("用户名和预期不符!"); 
	} 
}
  • ClassNotFoundException 属于编译异常,所以我们调用 forName 方法时候就要处理这个异常,或者将异常继续抛出!
public final class Class{ 
	public static Class<?> forName(String className)throws ClassNotFoundException{ //... } 
}

(3)使用throws关键字,声明方法所抛出的异常类型
这个声明的目的,就是告诉test方法的调用者,你调用我的这个test方法的时候要小心啦,方法在运行的时候可能会抛出Exception类型的异常.。
方法内抛出异常对象使用关键字throw,方法上声明异常使用的是throws

public void test(String name)throws Exception{ 
	if(!"tom".equals(name)){ 
		throw new Exception("用户名和预期不符!"); 
	} 
}

三、异常处理——捕获

1.概述

当一个方法内,抛出了编译异常的时候,编译器在编译期间检查到,就会报错,提示我们有俩种修改方案:

  • 把这个异常在方法上进行声明抛出
public void test(String className)throws ClassNotFoundException{ 
	Class.forName(className); 
}
  • 把这个异常在方法内进行捕获处理
public void test(String className){ 
	try {
		Class.forName(className); 
	} catch (ClassNotFoundException e) { 
		e.printStackTrace(); 
	} 
}

2. try-catch

  • try-catch 语句块,就是用来对指定代码,进行异常捕获处理,并且处理完成后,JVM不会停止运行,代码还可以正常的往下运行!
  • try:该代码块中编写可能产生异常的代码。
  • catch:用来进行某种异常的捕获,并对捕获到的异常进行处理。
try{
	编写可能会出现异常的代码 
}catch(异常类型 e){ 
	//处理异常的代码,可以是简单的输出异常信息,也可以使用日志进行了记录,也可以对数据进行修改纠正等操作 
}

3.捕获多种异常

如果try语句块中的多句代码,都会抛出异常,并且是不同类型的异常,那么catch语句块就有不同的写法,来处理这几个不同类型的异常。
(1)使用一个catch语句,里面使用|来表示捕获多种不同的异常类型

public static void main(String[] args) { 
	String className = "com.briup.demo.Student"; 
	String methodName = "sayHello"; 
	
	try {
		//forName声明抛出ClassNotFoundException 
		Class c = Class.forName(className); 
		
		//getMethod方法声明抛出NoSuchMethodException 
		Method m = c.getMethod(methodName); 
		
		//invoke方法声明抛出IllegalAccessException和InvocationTargetException 
		m.invoke(null); 
	
	} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 
		e.printStackTrace(); 
	} 
}

(2)使用了四个catch语句,分别对四种不同的异常类型进行捕获处理

  • 这种异常处理方式,要求多个catch中的异常不能相同,并且如果catch中的多个异常之间有子父类异常的关系的话,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。
  • 因为如果父类型异常再最上面的话,下面catch语句代码,永远不会被执行
public static void main(String[] args) { 
	String className = "com.briup.demo.Student"; 
	String methodName = "sayHello"; 
	
	try {
		//forName声明抛出ClassNotFoundException 
		Class c = Class.forName(className); 
		
		//getMethod方法声明抛出NoSuchMethodException
		Method m = c.getMethod(methodName); 
		
		//invoke方法声明抛出IllegalAccessException和InvocationTargetException 
		m.invoke(null); 
	} catch (ClassNotFoundException e) { 
		e.printStackTrace(); 
	} catch (NoSuchMethodException e) { 
		e.printStackTrace(); 
	} catch (IllegalAccessException e) { 
		e.printStackTrace(); 
	} catch (InvocationTargetException e) { 
		e.printStackTrace(); 
	} 
}

(3)使用了一个catch语句,但是捕获的异常类型是Exception,它最大的异常类型,由于多态的原因,Exception类型的引用e,可以捕获接收到任意类型的异常对象

public static void main(String[] args) { 
	String className = "com.briup.demo.Student"; 
	String methodName = "sayHello"; 
	
	try {
		//forName声明抛出ClassNotFoundException 
		Class c = Class.forName(className); 
		
		//getMethod方法声明抛出NoSuchMethodException 
		Method m = c.getMethod(methodName); 
		
		//invoke方法声明抛出IllegalAccessException和InvocationTargetException 
		m.invoke(null); 
	} catch (Exception e) { 
		e.printStackTrace(); 
	} 
}

4.finally语句

(1)try-catch语句块,虽然可以捕获并处理异常情况,但是它也会改变代码的执行流程

public class Test { 
	public static void main(String[] args) { 
		System.out.println("hello"); 
		Test t = new Test(); 
		
		try {
			t.test("zs"); 
			System.out.println("briup");    //注意观察,这句代码是否执行 
		} catch (Exception e) { 
			e.printStackTrace(); 
		}
		
		System.out.println("world"); 
		
	}
	
	public void test(String name)throws Exception{ 
		if(!"tom".equals(name)){ 
			throw new Exception("用户名不正确"); 
		} 
	} 
}

//运行结果: 
		hello 
		world 
		java.lang.Exception: 用户名不正确 
			at com.briup.demo.Test.test(Test.java:20) 
			at com.briup.demo.Test.main(Test.java:9)

(2)只要使用 finally 关键,就可以保证指定代码一定会执行,无论是否发生异常!

public class Test { 
	public static void main(String[] args) { 
		System.out.println("hello"); 
		Test t = new Test(); 
		
		try {
			t.test("zs"); 
		} catch (Exception e) { 
			e.printStackTrace(); 
		}finally { 
			System.out.println("briup");
			//这句代码一定会被执行 
		}
		
		System.out.println("world"); 
	}
	
	public void test(String name)throws Exception{ 
		if(!"tom".equals(name)){ 
			throw new Exception("用户名不正确"); 
		} 
	} 
}

//执行结果: 
		hello 
		briup 
		world 
		java.lang.Exception: 用户名不正确 
			at com.briup.demo.Test.test(Test.java:21) 
			at com.briup.demo.Test.main(Test.java:6)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值