什么是异常
在代码里:所谓异常也是程序在编写或者运行过程中出现了出乎意料的事情。
eg:
System.out.println(m / n );//运行期异常, 除数为0的异常
Java的异常体系
- 只有当对象是Throwable(或其子类)的实例时,才能被 Java 虚拟机或者 Java的throw 语句抛出 , 以及被catch 捕获。
- Throwable 包含了错误的详细信息, 包括方法的调用链条。
Error
- Error 是 Throwable 的子类,用于指示程序不应该试图捕获的严重问题。
- Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外
错误例如: 栈溢出错误, 硬盘空间不足, 虚拟机损坏等等!绝大多数错误不是代码原因引起的。
Error示例(栈溢出错误)
public class ErrorDemo {
public static void main(String[] args) {
method();
}
public static void method() {
int x = 10;
int y = 20;
int z = x + y;
method();//在method方法中调用method方法,形成了递归.
}
}
一直调用自己,产生的内存太大导致溢出错误
Exception
Exception是程序中的异常,即由于代码缺陷(bug)引起的问题 这类问题需要程序员处理
Exception 异常主要分为两类
- 运行期异常 RuntimeException
- 非运行期异常(即编译期异常)
编译期异常
编译期异常必须处理,否则程序将无法编译
示例(文件找不到异常)
import java.io.FileNotFoundException;
import java.io.FileReader;
public class ErrorDemo {
public static void main(String[] args) throws FileNotFoundException {
FileReader fis = new
FileReader("C:\\Users\\28993\\Desktop\\hello.txt");//非运行期异常,文件没有找到异常
}
}
常见的编译异常:
=================================================================
异常处理
=========================================================================
编译期异常有两种解决方案
1. 用try..catch代码块来处理异常。
2. 抛出(throws)异常声明,当前方法声明自己内部存在异常,把异常处理交给调用方法的地方。
try...catch
使用 try ... catch 语句可以捕获异常。
try...catch 的语法:
try {
//把可能出现异常的代码写在try代码块里
} catch (异常类型 变量名) {
//catch代码块里编写出现异常后要做什么
}
多重捕获
一个 try 代码块后面可以跟随多个 catch 代码块, 这样的写法叫多重捕获。
try{
// 把可能出现异常的代码写在try代码块里
}catch(异常类型1 变量名1){
// 程序代码
}catch(异常类型2 变量名2){
// 程序代码
}catch(异常类型n 变量名n){
// 程序代码
}
catch 后面的小括号里填写要捕获的异常。当try代码块中发生一个异常时,try 后面的 catch 块就 会被检查。如果发生的异常与catch 块要捕获的异常一致,就会进入相应的catch块执行,这和 switch...case语句很相似.
finally代码块
- try...catch代码块可以与finally代码块连用. 形成 try...catch...finally代码块
- 无论try中是否发生异常,finally 代码块中的代码总会被执行。finally 代码块出现在 最后一个 catch 代码块后面
- try..catch中有System.exit(0);//强制停止程序,finally不会执行
语法如下:
try{
// 程序代码
}catch(异常类型1 变量名1){
// 程序代码
}catch(异常类型2 变量名2){
// 程序代码
}finally{
// 程序代码
}
eg:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
FileReader fis = null;
try {
fis = new FileReader("C:\\Users\\28993\\Desktop\\hello.txt");
//存放读取内容的字符数组
char[] arr = new char[100];
//将文件内容读取到字符数组中, 并返回读取到的字符个数.
int length = fis.read(arr);
//把字符数组转换为字符串
String str = new String(arr, 0, length);
System.out.println(str);
} catch (FileNotFoundException e) {
System.out.println("没有这个文件,请检查文件路径正否正确");
} catch (IOException e) {
System.out.println("读取出现错误");
}finally {
//如果文件打开了, 要关闭文件
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
try-catch-finally 执行顺序的相关问题: finally 块中带有 return 语 句的情况
eg1:
public static void main(String[] args){
int result = test1();
System.out.println(result);
}
public static int test1(){
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
}catch(Exception e){
i--;
System.out.println("catch block i = "+i);
}finally{
i = 10;
System.out.println("finally block i = "+i);
}
return i;
}
输出结果:
try block, i = 2
finally block i = 10
10
eg1改动:
public static int test2(){
int i = 1;
try{
i++;
throw new Exception();//抛出异常,即直接出现异常,异常类型是Exception
}catch(Exception e){
i--;
System.out.println("catch block i = "+i);
}finally{
i = 10;
System.out.println("finally block i = "+i);
}
return i;
}
输出结果:
catch block i = 1
finally block i = 10
10
eg2:
public static void main(String[] args){
int result = test3();
System.out.println(result);
}
public static int test3(){
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
i ++;
System.out.println("catch block i = "+i);
return i;
}finally{
i = 10;
System.out.println("finally block i = "+i);
}
}
输出结果:
try block, i = 2
finally block i = 10
2
try-catch-finally:
1、不管有没有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、如果在finally之前遇到了return语句(此时并不会返回结果,而是先把要返回的值保存起来,不管 finally中的代码怎么样,返回的值都return时刻的值);
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
5、try..catch中有System.exit(0);//强制停止程序,finally不会执行
--------------------------------------------------------------------------------------------------------------------------------throws抛出异常声明
如果在编译期异常出现的时候没有通过try...catch处理异常,那么可以在该方法的方法声明处通过 throws 关键字来抛出异常声明。throws 关键字放在方法签名的尾部(即方法体左大括号的前面)。
void 方法名 ()throws 异常类型 { // 方法体 }
一个方法可以声明抛出多个异常声明,多个异常声明之间用逗号隔开。
如果一直通过throws抛出异常声明, 如果真的出现了异常, 异常最后会被虚拟机捕获到, 虚拟机的处理方式是中断程序的执行.
运行期异常--RuntimeException
编译期不报任何错误,但是在运行时产生的异常叫做运行期异常
eg:
int[] arr1 = {1,2,3,4};
System.out.println(arr1[4]);//运行期异常, 数组下标越界
int m = 100;
int n = 0;
System.out.println(m / n );//运行期异常, 除数为0的异常
运行期异常即使不处理也不影响程序编译,不过在运行时会出现异常,导致程序出错
常见运行异常:
throws关键字
作用:抛出异常
throw可以抛出Throwable体系里所有的异常.
格式: throw 异常类型对象;
eg:
if(b==0){
RuntimeException e =new RuntimeException("除数不能为零");
throw e;//抛出一个异常,如果没有try...catch处理的话程序会中止
}