JavaSE第七十五讲:异常笔试、面试常见问题深度剖析

1. 在上一讲内容中我们讲了异常的两种处理方式,其中用try + catch + finally结构的处理方式中,可以多个catch,每一个catch块捕获着一种特定类型的异常。如下程序所示:

自定义两个异常如下:

package com.ahuier.exception;

public class MyException extends Exception{
	
	/*
	 * 参考ArithmeticException的实现
	 * 使用supe关键字可以保证将字符串的信息一层一层网上传到Throwable类让其维护字符串描述信息
	 */
	public MyException(){
		super();
	}
	
	public MyException(String message){
		super(message);
	}
}
package com.ahuier.exception;

public class MyException2 extends Exception	{
	public MyException2(){
		super();
	}
	public MyException2(String message){
		super(message);
	}

}
写一个测试异常类:

package com.ahuier.exception;

public class ExceptionTest4 {
	public void method(String str) throws MyException, MyException2{
		if(str == null){
			throw new MyException("传入的字符串参数不能为null");
		}
		else if(str.equals("hello")){
			throw new MyException2("传入的字符不能为hello");
		}
		else{
			System.out.println(str);
		}
	}
	
	/*
	 * 根据多态,也可以抛出 Exception类型的异常: 
	 * 1) throws Exception
	 * 2) 捕获也可以这样写 catch(Exception e)
	 */
	public static void main(String[] args) throws MyException{
		
		try{
			ExceptionTest4 test = new ExceptionTest4();
			test.method("hello");
		}catch(MyException e){
			System.out.println("进入到MyException catch块");
			e.printStackTrace();
		}catch(MyException2 e){
			System.out.println("进入到MyException catch块2");
			e.printStackTrace();
		}  //这部有可能会抛出两种异常,有可能抛出的都必须用catch捕获
		finally{
			System.out.println("异常处理完毕");
		}
		System.out.println("程序执行完毕");

	}
}
编译执行
com.ahuier.exception.MyException2: 传入的字符不能为hello
at com.ahuier.exception.ExceptionTest4.method(ExceptionTest4.java:9)
at com.ahuier.exception.ExceptionTest4.main(ExceptionTest4.java:25)
进入到MyException catch块2
异常处理完毕
程序执行完毕

【说明】:这边 test.method("hello");传入的是“hello”,则进入MyException2的catch块,如果是test.method(null);传入的是null,则进入MyException的catch块。通过这个程序可以知道,一个程序有多种抛出异常的可能,都要去捕获这些异常,每一个catch捕获一种异常类型。

分析以上程序ExceptionTest4:

else if(str.equals("hello"))

这种写法是不好的,因为如果不做这个判断的话,一旦str为空,则肯定出现空指针异常了。

所以要修改成 else if("hello".equals(str)) 这样把字符串常量写在前面,这种写法的好处是即便str为空的话,也不会抛出异常,而是直接判断为假了。建议以后把常量写在前面,把变量写在后面。


2. 针对上面的程序,我们再讲一个知识点

可以根据多态,可以将几种异常写成一个他们的父类异常Excption,因为这个异常涵盖了他们

package com.ahuier.exception;

public class ExceptionTest4 {
	public void method(String str) throws Exception{
		if(str == null){
			throw new MyException("传入的字符串参数不能为null");
		}
		else if("hello".equals(str)){
			throw new MyException2("传入的字符不能为hello");
		}
		else{ 
			System.out.println(str);
		}
	}	
	/*
	 * 根据多态,也可以抛出 Exception类型的异常: 
	 * 1) throws Exception
	 * 2) 捕获也可以这样写 catch(Exception e)
	 */
	public static void main(String[] args) throws MyException{
		
		try{
			ExceptionTest4 test = new ExceptionTest4();
			test.method("hello");
		}catch(MyException e){
			System.out.println("进入到MyException catch块");
			e.printStackTrace();
		}catch(MyException2 e){
			System.out.println("进入到MyException2 catch块");
			e.printStackTrace();
		}  //这部有可能会抛出两种异常,有可能抛出的都必须用catch捕获
		catch(Exception e){
			System.out.println("进入到Exception catch块");
		}
		finally{
			System.out.println("异常处理完毕");
		}
		System.out.println("程序执行完毕");

	}
}
【说明】: 我们可以使用多个catch块来捕获异常,这时需要将父类型的catch块放到子类型的catch块之后,这样才能保证后续的catch可能被执行,否则子类型的catch将永远无法到达,Java编译器会报编译错误;如果多个catch块的异常类型是独立的(MyException, MyException2), 那么谁前谁后都是可以的。 


3. 如果try块中存在return语句,那么首先也需要将finally块中的代码执行完毕,然后方法再返回。 

package com.ahuier.exception;

public class ExceptionTest5 {
	public void method(){
		
		try{
			System.out.println("进入到catch块");
			return;
		}catch(Exception e){
			System.out.println("异常发生了");
		}finally{
			System.out.println("进入到finally块");
		}
		System.out.println("异常处理后续代码");
	}
	public static void main(String[] args) {
		ExceptionTest5 test = new ExceptionTest5();
		test.method();
	}
}
编译执行结果:

进入到catch块
进入到finally块


4. 如果try块中存在System.exit(0)语句,那么就不会执行finally块中的代码,因为System.exit(0)会终止当前运行的Java虚拟机,程序会在虚拟机终止前结束执行。 

package com.ahuier.exception;

public class ExceptionTest5 {
	public void method(){
		
		try{
			System.out.println("进入到catch块");
			System.exit(0);  //如果里面传的参数是0 则正常退出Java虚拟机,程序是在虚拟机上运行的,虚拟机停止,则程序退出不执行了
		}catch(Exception e){
			System.out.println("异常发生了");
		}finally{
			System.out.println("进入到finally块");
		}
		System.out.println("异常处理后续代码");
	}
	public static void main(String[] args) {
		ExceptionTest5 test = new ExceptionTest5();
		test.method();
	}
}
编译执行结果:

进入到catch块


5. 到此为止我们异常全部讲解完毕,在异常中关键的部分是自定义异常,自定义异常是项目中一个重要的组成部分,需要定义自己一个完善的异常体系。

同时也要学习对异常的处理。

异常的处理有三种方式:

1. 捕获异常

2. 抛出异常

3. 捕获到异常加入自己的信息再抛出,供调用这个方法的那个方法来处理这一个异常。



你可能感兴趣的:(JavaSE,Java异常,自定义异常)