黑马程序员_JavaSE基础知识总结十:异常处理

------ android培训java培训、期待与您交流! ----------


一、异常的基本概念

什么是异常,在程序运行过程中出现的错误,称为异常

<span style="font-size:18px;">public class ExceptionTest01 {
	public static void main(String[] args) {
		int i1 = 100;
		int i2 = 0;
		int i3 = i1 / i2;
		System.out.println(i3);
	}
}</span>

没有正确输出,抛出了被除异常

通过以上示例,我们看到java 给我们提供了这样一个体系结构,当出现问题的时候,它会告诉我们,并且把错误的详细信息也告诉我们了,这就是异常的体系结构,这样我们的程序更健壮,我们可以把这个信息,再进行处理以下告诉用户。从上面大家还可以看到,java异常都是类,在异常对象中会携带一些信息给我们,我们可以通过这个异常对象把信息取出


二、异常的分类

1、异常分类

异常主要分为:错误、一般性异常(受控异常)、运行期异常(非受控异常)

①错误:如果应用程序出现了Error,那么将无法恢复,只能重新启动应用程序,最典型的Error 的异常是:OutOfMemoryError。

②受控异常:出现了这种异常必须显示的处理,不显示处理java 程序将无法编译通过。

③非受控异常:此种异常可以不用显示的处理,例如被0 除异常,java 没有要求我们一定

要处理。

2、try、catch和finally

异常的捕获和处理需要采用try catch 来处理,具体格式如下:

try {

}catch(OneException e) {

}catch(TwoException e) {

}finally {

}

①try 中包含了可能产生异常的代码, try 后面是catch,catch 可以有一个或多个,catch 中是需要捕获的异常;

②当try 中的代码出现异常时,出现异常下面的代码不会执行,马上会跳转到相应的catch

语句块中,如果没有异常不会跳转到catch 中;

③finally 表示,不管是出现异常,还是没有出现异常,finally 里的代码都执行,finally 和catch 可以分开使用,但finally 必须和try 一块使用,如下格式使用finally 也是正确的。

<span style="font-size:18px;">public class ExceptionTest02 {
	public static void main(String[] args) {
		int i1 = 100;
		int i2 = 0;
//try 里是出现异常的代码
//不出现异常的代码最好不要放到try 作用
try {
//当出现被0 除异常,程序流程会执行到“catch(ArithmeticException ae)”语句
//被0 除表达式以下的语句永远不会执行
int i3 = i1/i2;
//永远不会执行
	System.out.println(i3);
//采用catch 可以拦截异常
//ae 代表了一个ArithmeticException 类型的局部变量
//采用ae 主要是来接收java 异常体系给我们new 的ArithmeticException 对象
//采用ae 可以拿到更详细的异常信息
	}catch(ArithmeticException ae) {
		System.out.println("被0 除了");
	}
}</span>

3、getMessageprintStackTrace()

如何取得异常对象的具体信息,常用的方法主要有两种:

取得异常描述信息:getMessage( )

取得异常的堆栈信息(比较适合于程序调试阶段)printStackTrace( )

<span style="font-size:18px;">public class ExceptionTest03 {
	public static void main(String[] args) {
		int i1 = 100;
		int i2 = 0;
		try {
			int i3 = i1/i2;
			System.out.println(i3);
		}catch(ArithmeticException ae) {
			//ae 是一个引用,它指向了堆中的ArithmeticException
			//通过getMessage 可以得到异常的描述信息
			System.out.println(ae.getMessage());
		}
	}
}</span>
<span style="font-size:18px;">public class ExceptionTest04 {
	public static void main(String[] args) {
		method1();
	}
	private static void method1() {
		method2();
	}
	private static void method2() {
		int i1 = 100;
		int i2 = 0;
		try {
			int i3 = i1/i2;
			System.out.println(i3);
		}catch(ArithmeticException ae) {
			//ae 是一个引用,它指向了堆中的ArithmeticException
			//通过printStackTrace 可以打印栈结构
			ae.printStackTrace();
		}
	}
}</span>

4、受控异常

<span style="font-size:18px;">import java.io.FileInputStream;
	public class ExceptionTest05 {
		public static void main(String[] args) {
			FileInputStream fis = new FileInputStream("test.txt");
		}
}</span>


从上面输出可以看到,无法编译,它抛出了一个异常, 这个异常叫做“受控异常”FileNotFoundException,也就是说在调用的时候必须处理文件不能找到

处理FileNotFoundException

<span style="font-size:18px;">/*
import java.io.FileInputStream;
import java.io.FileNotFoundException;
*/
import java.io.*;
	public class ExceptionTest06 {
		public static void main(String[] args) {
			try {
				FileInputStream fis = new FileInputStream("test.txt");
			}catch(FileNotFoundException ffe) { //此异常为受控异常,必须处理
				ffe.printStackTrace();
			}
		}
}</span>

5、finally关键字

finally 在任何情况下都会执行,通常在finally 里关闭资源

<span style="font-size:18px;">import java.io.*;
public class ExceptionTest07 {
	public static void main(String[] args) {
		try {
			FileInputStream fis = new FileInputStream("test.txt");
			System.out.println("-------before fis.close--------");
			//close 是需要拦截IOException 异常
			//在此位置关闭存在问题,当出现异常
			//那么会执行到catch 语句,以下fis.close 永远不会执行
			//这样个对象永远不会得到释放,所以必须提供一种机制
			//当出现任何问题,都会释放相应的资源(恢复到最初状态)
			//那么就要使用finally 语句块
			fis.close();
			System.out.println("-------after fis.close--------");
		}catch(FileNotFoundException e) {
			e.printStackTrace();
			}catch(IOException e) {
			e.printStackTrace();
		}
	}
}</span>

采用finally 来释放资源

<span style="font-size:18px;">import java.io.*;

public class ExceptionTest08 {
	public static void main(String[] args) {
		// 因为fis 的作用域问题,必须放到try 语句块外,局部变量必须给初始值
		// 因为是对象赋值为null
		FileInputStream fis = null;
		try {
			// FileInputStream fis = new FileInputStream("test.txt");
			fis = new FileInputStream("test.txt");
			/*
			 * System.out.println("-------before fis.close--------");
			 * fis.close();
			 * System.out.println("-------after fis.close--------");
			 */
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				System.out.println("-------before fis.close--------");
				// 放到finally 中的语句,程序出现任何问题都会被执行
				// 所以finally 中一般放置一些需要及时释放的资源
				fis.close();
				System.out.println("-------after fis.close--------");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}</span>

深入finally

<span style="font-size:18px;">import java.io.*;

public class ExceptionTest08 {
	public static void main(String[] args) {
		// 因为fis 的作用域问题,必须放到try 语句块外,局部变量必须给初始值
		// 因为是对象赋值为null
		FileInputStream fis = null;
		try {
			// FileInputStream fis = new FileInputStream("test.txt");
			fis = new FileInputStream("test.txt");
			/*
			 * System.out.println("-------before fis.close--------");
			 * fis.close();
			 * System.out.println("-------after fis.close--------");
			 */
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				System.out.println("-------before fis.close--------");
				// 放到finally 中的语句,程序出现任何问题都会被执行
				// 所以finally 中一般放置一些需要及时释放的资源
				fis.close();
				System.out.println("-------after fis.close--------");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}</span>

深入finally

<span style="font-size:18px;">public class ExceptionTest10 {
	public static void main(String[] args) {
		int i1 = 100;
		int i2 = 10;
		try {
			int i3 = i1 / i2;
			System.out.println(i3);
			// return;
			System.exit(-1); // java 虚拟机退出
		} catch (ArithmeticException ae) {
			ae.printStackTrace();
		} finally {
			// 只有java 虚拟机退出不会执行finally
			// 其他任何情况下都会执行finally
			System.out.println("----------finally---------");
		}
	}
}</span>

深入finally

<span style="font-size:18px;">public class ExceptionTest11 {
	public static void main(String[] args) {
		int r = method1();
		// 输出为:10
		System.out.println(r);
	}

	/*
	 * private static int method1() { byte byte0 = 10; byte byte3 = byte0;
	 * //将原始值进行了保存 byte byte1 = 100; return byte3; Exception exception;
	 * exception; byte byte2 = 100; throw exception; }
	 */
	private static int method1() {
		int a = 10;
		try {
			return a;
		} finally {
			a = 100;
		}
	}
}</span>

深入finally

<span style="font-size:18px;">public class ExceptionTest12 {
	public static void main(String[] args) {
		int r = method1();
		// 输出为:100
		System.out.println(r);
	}

	/*
	 * private static int method1() { byte byte0 = 10; byte0 = 50; byte0 = 100;
	 * break MISSING_BLOCK_LABEL_18; Exception exception; exception; byte0 =
	 * 100; throw exception; return byte0; }
	 */
	private static int method1() {
		int a = 10;
		try {
			a = 50;
		} finally {
			a = 100;
		}
		return a;
	}
}</span>


6、如何声明异常

方法定义处采用throws 声明异常,如果声明的异常为受控异常,那么调用方法必须处理

此异常

声明受控异常

<span style="font-size:18px;">import java.io.*;

public class ExceptionTest13 {
	public static void main(String[] args)
	// throws FileNotFoundException, IOException {
	// //可以在此声明异常,这样就交给java虚拟机处理了,不建议这样使用
			throws Exception { // 可以采用此种方式声明异常,因为Exception 是两个异常的父类
	/*
	 * //分别处理各个异常 try { readFile(); }catch(FileNotFoundException e) {
	 * e.printStackTrace(); }catch(IOException e) { e.printStackTrace(); }
	 */
		// 可以采用如下方式处理异常
		// 因为Exception 是FileNotFoundException 和IOException 的父类
		// 但是一般不建议采用如下方案处理异常,粒度太粗了,异常信息
		// 不明确
		/*
		 * try { readFile(); }catch(Exception e) { e.printStackTrace(); }
		 */
		readFile();
	}

	private static void readFile() throws FileNotFoundException, IOException { // 声明异常,声明后调用者必须处理
		FileInputStream fis = null;
		try {
			fis = new FileInputStream("test.txt");
			// }catch(FileNotFoundException e) {
			// e.printStackTrace();
		} finally {
			// try {
			fis.close();
			// }catch(IOException e) {
			// e.printStackTrace();
			// }
		}
	}
}</span>

②声明非受控异常

<span style="font-size:18px;">public class ExceptionTest14 {
	public static void main(String[] args) {
		// 不需要使用try...catch..,因为声明的是非受控异常
		// method1();
		// 也可以拦截非受控异常
		try {
			method1();
		} catch (ArithmeticException e) {
			e.printStackTrace();
		}
	}

	// 可以声明非受控异常
	private static void method1() throws ArithmeticException {
		int i1 = 100;
		int i2 = 0;
		// try {
		int i3 = i1 / i2;
		System.out.println(i3);
		/*
		 * }catch(ArithmeticException ae) { ae.printStackTrace(); }
		 */
	}
}</span>


<div><span style="font-size:18px;">public class ExceptionTest15 {
 	public static void main(String[] args) {
  	int ret = method1(1000, 10);</span></div><div><span style="font-size:18px;"></span>
</div><div><span style="font-size:18px;"> 	 if (ret == -1) {
   	System.out.println("除数为0");
  	}
  	if (ret == -2) {
  	 System.out.println("被除数必须为1~100 之间的数据");
  	}
  	if (ret == 1) {
  	 System.out.println("正确");
  	}
 	 // 此种方式的异常处理,完全依赖于程序的返回
  	// 另外异常处理和程序逻辑混在一起,不好管理
  	// 异常是非常,程序语句应该具有一套完成的异常处理体系
 	}</span></div><div><span style="font-size:18px;"></span>
</div><div><span style="font-size:18px;">	 private static int method1(int value1, int value2) {
	  if (value2 == 0) {
  	 return -1;
 }
  if (!(value1 > 0 && value1 <= 100)) {
   return -2;
  }
  int value3 = value1 / value2;
  System.out.println("value3=" + value3);
  return 1;
 }
}</span></div>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值