------ 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>
没有正确输出,抛出了被0 除异常
通过以上示例,我们看到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、getMessage和printStackTrace()
如何取得异常对象的具体信息,常用的方法主要有两种:
①取得异常描述信息: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>