写完后又没有检查,如果出现错误的地方请见谅!!!
1.什么是异常?
异常是指程序运行过程出现如内存空间不足,系统错误,加载类不存在,类型不兼容之类的非正常状态
2.异常分类
异常类的体系架构图如下
Object类:一个类可以有父类,他的父类又可以有父类,父类又可以有父类,为了更好的体现类的继承关系,java定义了Object类,Object类是java其他所有类的祖宗(基类
),可以说没有Object类java面向对象这一特性就失去意义。Object类详解
异常主要可以分为两大类:
Error类
和Exception类
;他们都继承自java.lang.Throwable类,是Throwable类的两个子类,Throwable类是一切异常类的超类(父类)
1.Error类
- Error (
错误类
) 一般是指JVM(java虚拟机
)相关的问题,如系统内部错误,java环境异常,内存空间不足(资源耗尽)等异常,这类异常与code block(代码块
)无关,无法在代码块中捕获并加以处理(是不可捕获的异常
)
2.Exception类
- Exception(
异常类
)与程序code block有关,属于可以被捕获并处理
的异常,java中所有可以被捕获的异常都派生自Exception类
Exception类又可分为两部分:
非运行时异常
和 RuntimeException
(运行时异常) (又称:check exception
和unchecked exception
)
1.非运行时异常
- 非运行时异常有很多种叫法(如:编译期异常,check exception,普通异常)
- 非运行时异常的主要特点:
java编译器会检查这类异常
,然后提示你进行异常处理 - 非运行时异常,通俗点讲就是编译期异常,如:创建一个文件输入流对象(FileInputStream),这时候程序就会报错了(在出现异常的代码下方出现红色波浪线),对于这类异常,java编译器会提示try catch()捕获处理 或者 throws抛出,否则程序就不能编译通过(
即:编译期异常要求强制捕获或抛出,编译器才能通过编译
)
自定义异常
因为自定义异常需要用到throw关键字,所以在下面讲了throw后在一起接着讲
2.RuntimeException
- RuntimeException的主要特点:
java编译器不会检查这类异常
,但运行后控制台会显示异常信息 - RuntimeException属于编译错误异常,如:数组下标越界异常,算术运算异常等,这类异常出现的频率很高,为了避免巨大的系统资源开销,java编译器不会对这类异常进行检查,所以这类异常出现时,java编译器不会有任何错误提示,
RuntimeException异常不要求强制捕获或抛出,程序也可以编译通过
,但,如果不捕获该类异常 ,一旦执行了该异常语句,则程序就会直接终止,不会再执行下面的语句了
常见的RuntimeException:
1.数组下标越界异常–ArrayIndexOutOfBoundsException
public class ArrayIndexOutOfBoundsException {
public static void main(String[] args) {
int[] arr={2,5,13};
try {
System.out.println(arr[3]);//数组下标为0-2,3超出了这个范围
} catch (Exception e) {
System.err.println("异常信息:");
e.printStackTrace();
}
}
}
2.类型强制转换异常–ClassCastException
public class ClassCastException{
public static void main(String[] args) {
Object x = new String("java.lang.ClassCastException");
try {
System.out.println((Integer) x);
} catch (Exception e) {
System.err.println("异常信息:");
e.printStackTrace();
}
}
}
3.空指针引用异常–NullPointerException
public class NullPointerException{
public static void main(String[] args) {
String str=null;
try {
// System.err.println(str.charAt(0));
System.out.println(str.toString());
} catch (Exception e) {
System.err.println("异常信息:");
e.printStackTrace();
}
}
}
4.非法算术运算异常–ArithmeticException
public class ArithmeticException {
public static void main(String[] args) {
int a=1;
int b=0;
try {
System.out.println(a/b); //众所周知,分母不能为0
} catch (Exception e) {
System.err.println("异常信息:");
e.printStackTrace();
}
}
}
5.向数组中存放与数组类型不兼容对象异常–ArrayStoreException
public class ArrayStoreException {
public static void main(String[] args) {
Object[] arr=new String[3];
arr[1]=123;
try {
System.err.println(arr[1]);
} catch (Exception e) {
System.err.println("异常信息:");
e.printStackTrace();
}
}
}
…
还有很多就不一一举例说明了
3.异常处理
- java针对程序运行过程出现内存空间不足,系统错误,加载类不存在等非正常情况,以异常类的形式对这些非正常情况进行封装后,通过异常处理机制对这些问题进行处理
- java的异常处理是面向对象的,当程序出现异常情况时,Exception对象就会随之产生
- java实现异常处理的5个关键字:try,catch,throw,throws,finally
注意
在讲异常处理前先讲一个注意事项,那就是程序一旦发生异常,如果总是throws抛出或者不做任何处理,那么程序就会非正常终止,后面没执行的语句也不会在执行了
异常处理的两种方式——就地捕获处理,向外抛出
1.就地捕获处理
try
- 存放可能发生异常的java语句,如果try 代码块中的程序出现了异常,系统就会将这些异常的信息封装进一个异常对象中,并将这个对象传递给catch
- try语句不能单独使用,try语句后面至少要跟着catch语句或finally语句中的一个,当然也可以着多个catch语句,如上图异常捕获语句模板所示
- try语句块中,一旦遇到异常语句,那么try语句块中异常语句后面的语句就不会在执行了
public class FileNotFoundException{
public static void main(String[] args) {
try {
System.out.println("执行try代码块异常语句前面代码");
FileInputStream in=new FileInputStream("o.txt");
System.out.println("执行try代码块异常语句后面代码");
} catch (Exception e) {
System.out.println("执行catch代码块1");
e.printStackTrace();
System.out.println("执行catch代码块2");
}finally{
System.out.println("执行finally代码块");
}
}
}
catch
- catch()中必须指定一个参数来表明它所能接收的异常类型,这个参数的类型必须是Exception类或其子类,因此,一个用于捕获Exception对象(即: 参数类型为Exception)的catch语句块可以用于捕获任意
可被捕获
的异常 - 在try语句块之后,可能会跟着多个catch语句,每一个catch语句用于处理不同类型的异常
- 注: catch是用来捕获try语句块中发生的异常的,如果try语句块中没有出现异常,那么catch语句块就不会执行
public class Test {
public static void main(String[] args) {
try{
System.out.println("执行try语句块");
}catch(Exception e){
e.printStackTrace();
System.out.println("执行catch语句块");
}
System.out.println("try中没有出现异常,跳过catch语句块向下执行");
}
}
finally
- finally语句块不可以单独使用,必须与try或try-catch()语句一起使用
- 不管try代码块的是否出现异常,jvm(
java虚拟机
)都会保证finally代码块的始终会执行,即便是再try语句块中使用return语句,唯一 一种使finally语句块无法执行的方法是在finally语句块执行之前退出java虚拟机,而且一旦退出java虚拟机后,整个程序都会终止
public class Test {
public static void main(String[] args){
try{
System.out.println("执行try语句块");
System.exit(0); //执行这条语句退出java虚拟机
}finally{
System.out.println("执行finally语句块");
}
System.out.println("执行finally语句块后面语句");
}
}
- return 是用于结束当前方法的关键字,那么为什么try语句块中使用了return语句,finally语句块还是会执行?
其实try中的return语句并不会直接就按try语句块中代码的顺序来执行,而是只有在finally块执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止
public class Test {
public static void main(String[] args){
int result=method1();
System.err.println(result);
}
private static int method1(){
try{
System.out.println("开始执行");
return 10;
}catch(Exception e){
e.printStackTrace();
System.out.println("执行catch语句块");
return 20;
}finally{
return 30;
}
}
}
4. try语句块中如果出现异常,那么finally语句块后面的语句就不会再执行了,如果没有出现异常则会出现继续执行
public class Test {
public static void main(String[] args){
try{
System.out.println("执行try语句块");
System.out.println(1/0);
}finally{
System.out.println("finally语句块");
}
System.out.println("finally语句块后面的语句");
}
}
- 继续上面的话题,try语句块中出现异常,finally语句块后面的语句就不会再执行,但如果通过catch语句捕获处理之后,finally语句块后面的语句就可以执行了
public class Test {
public static void main(String[] args){
try{
System.out.println("执行try语句块");
System.out.println(1/0);
}catch(Exception e){
e.printStackTrace();
System.out.println("执行catch语句块");
}finally{
System.out.println("finally语句块");
}
System.out.println("finally语句块后面的语句");
}
}
2.向外抛出异常
throws
- throws关键字用于方法体外部的方法声明部分,表示对外声明该方法可能抛出的异常,由下图语法格式可以看出,throws后面需要声明方法中可能抛出异常的类型
2.当异常所在的方法选择throws抛出异常时, 那么该方法的调用者,在调用该方法后java编译器就会提示你进行处理或者重新抛出,否则就会编译不通过
- 当大家都只抛出,不处理的时候,最后就会交给java虚拟机处理(
main是最上层的方法了,如果main方法也不想处理或者不知道怎么处理,而是throws抛出,那么就会直接交给java虚拟机处理
)
throw
- throw关键字是用于方法体内部,用来抛出一个Throwable类型的异常,语法结构如下
- 如果throw抛出的是check exception(
非运行时异常
),那么就要对该异常进行捕获处理,或者在方法的头部声明方法可能抛出的异常类型,如下
自定义异常
java中定义了大量异常类,这些类几乎可以描述编程中的大部分异常情况,但在程序开发过程中有时又需要用到一些特定的描述来表示程序中特有的异常情况,但这写是java中没有提供的(因为java的开发者又不是神,不可能什么情况都考虑到,也无法实现那么大的工程量),所以为了解决这一问题,java允许用户自定义异常,但这些自定义的异常必须继承自Exception或其子类
- 自定义异常要先创建一个异常类来继承自Exception,创建好异常对象后,通过throw关键字在方法中声明抛出异常的实例对象,但通过throw抛出异常对象时,java编译器会提示你用try…catch语句捕获处理或者在方法头上通过throws关键字继续抛出,由该方法的例子来处理
(注:上面这个例子中,main已经是最上层的方法了,没有其他方法能掉用它了,在main中抛出就是交由JVM处理了,)
扩展
异常处理:finally块中代码什么时候执行总结!
六个例子彻底理解finally语句块
java 中try catch finally 的具体执行顺序返回结果+代码测试