异常
异常是什么
异常的分类
错误
异常
编译时异常
运行时异常
异常的创建
异常的处理
抛出
捕获
方法重写时的异常处理
自定义异常
异常是什么
异常是为了通知调用者,这里的代码有问题才出现的。 包含了一些异常信息
public static void main(String [] args){
divide(100,0);
}
public static int divide(int num1,int num2){
if(num2 == 0){
System.out.println("除数不能为0 ");
// 这里不知道返回什么东西回去
}else{
return num1 / num2;
}
}
上述代码中不知道返回什么值回去的时候,这个时候可以考虑使用异常来进行处理。
java中异常可以理解为时一种通知。
异常的分类
Throwable 是所有异常和错误的父类
|
----- Error 错误 常见的OutOfMemoryError 内存溢出错误
|
----- Exception 异常
|
------ 编译时(检查时) 异常
|
------ 运行时异常
Throwable 在java中异常和错误的父类
Error 错误 一般情况下出现了错误,表示很难或者无法挽回的情况 常见的OutOfMemoryError 内存溢出错误
Exception 异常 是所有异常的父类
编译时异常 在写代码的时候,程序认为这个地方可能会发生异常,并且强制要求程序员去处理,做好预防措施。常见的编译时异常:IOException,FileNotFoundException,SqlException
运行时异常 (RuntimeException): 在程序运行过程中可能出现的异常,一般情况下出现运行时异常,一定是程序员的逻辑错误,代码出现问题。所以运行时异常都是可以得到解决的。一个完美的程序不应该出现运行时异常。运行时异常不会要求程序员强制处理。常见的运行时异常:NullPointerException 空指针异常,ArrayIndexOutOfBoundsException 数组下标越界异常,ClassCastException 类转换异常,NagetiveArraySizeException 数组长度异常 ArithmerticException 数学异常
异常的创建
package com.exceptions;
import java.io.IOException;
public class Exceptions {
public static void main(String [] args){
try {
divide(100,0);
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public static int divide(int num1,int num2) throws IOException{
if(num2 == 0){
throw new ArithmeticException("除数不能为0");// 当抛出异常对象的时候后面代码就不会执行了
//throw new IOException("除数不能为0");
}else{
return num1 / num2;
}
}
}
当创建一个运行时异常的时候,抛出去不需要特殊的处理。
当创建一个编译时异常的时候,需要在方法的参数列表后,加上抛出去的异常类型
异常的处理
异常的抛出
当方法的调用层数过多的时候,底层抛出异常,如果上一级还是无法处理,可以选择继续抛出。
当调用者接收到被调用者传递过来的异常信息后,如果还是没办法处理这个异常信息,可以选择将他继续抛出,如果一直没有处理这个异常信息,最后抛到main方法上还是没有处理,就会抛给java虚拟机,java虚拟机就会异常终止。
package com.exceptions;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
a();
System.out.println(5);
}
public static void a() throws IOException {
System.out.println(1);
b();
}
public static void b() throws IOException {
System.out.println(2);
c();
}
public static void c() throws IOException {
System.out.println(3);
d();
}
public static void d() throws IOException {
System.out.println(4);
throw new IOException("测试异常");
}
}
异常的捕获
当被调用者抛出异常对象的时候,调用者可以处理这个异常,那么可以将这个异常捕获住,然后根据具体的异常信息进行对应的处理即可
try {
//可能会抛出异常的代码
}catch (异常类型1 对象1){
//处理的代码
}catch (异常类型2 对象2){
//处理的代码
}catch (异常类型3 对象3){
//处理的代码
}
当try中抛出了异常,会将异常对象在catch中进行类型匹配,匹配的顺序是从上往下,如果匹配到了某一个catch,那么后面的catch就不会再进了
catch的顺序描述:前面的异常类型可以是后面异常类型的子类,但不能是后面异常类型的父类。
package com.exceptions;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
a();
System.out.println(5);
}
public static void a() {
System.out.println(1);
try {
e();
b();
} catch (FileNotFoundException e) {
System.out.println("处理了" + e.getMessage());
} catch (IOException e) {
System.out.println("处理了" + e.getMessage());
}
}
public static void e() throws FileNotFoundException {
System.out.println(2);
//throw new FileNotFoundException("文件没找到");
}
public static void b() throws IOException {
System.out.println(2);
c();
}
public static void c() throws IOException {
System.out.println(3);
d();
}
public static void d() throws IOException {
System.out.println(4);
throw new IOException("测试异常");
}
}
可以有一个try 多个catch,try中如果抛出了异常,那么抛出异常的代码后面的内容就不会再执行了,而是进入对应的catch代码中进行处理异常
try里面的代码不一定会完全执行,catch中的代码也不一定会执行
package com.exceptions;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
int a = a();
System.out.println(a);
}
public static int a() {
System.out.println(1);
try {
e();
b();
return 1;
} catch (FileNotFoundException e) {
System.out.println("处理了" + e.getMessage());
System.exit(0);
return 2;
} catch (IOException e) {
System.out.println("处理了" + e.getMessage());
return 3;
} finally {
// 无论try和catch是如何执行的 finally 是一定会执行的内容
System.out.println("finally");
}
}
public static void e() throws FileNotFoundException {
System.out.println(2);
throw new FileNotFoundException("文件没找到");
}
public static void b() throws IOException {
System.out.println(2);
c();
}
public static void c() throws IOException {
System.out.println(3);
d();
}
public static void d() throws IOException {
System.out.println(4);
throw new IOException("测试异常");
}
}
finally 是一定会执行的代码,即使try和catch中有return也不能阻止finally的执行,只有System.exit(0) 才可以 阻止finally的执行。
重写时异常的处理
如果父类的方法抛了某个异常,那么子类在重写父类的这个方法的时候,
package com.exceptions;
import java.io.IOException;
public abstract class A {
public abstract void a() throws IOException;
}
package com.exceptions;
import java.io.FileNotFoundException;
public class B extends A{
@Override
public void a() throws FileNotFoundException {
}
}
子类方法在重写的时候可以选择不抛,可以选择和父类方法抛出的异常一致,还可以选择抛出父类异常的子类
子类方法抛出异常的范围不能比父类方法抛出异常的范围更大
上面的描述主要针对编译时异常,运行时异常本身不做强制处理,不存在上面描述的情况
自定义异常
在java中虽然已经定义了很多异常类型,但实际的开发过程中可能还是不能满足我们项目的需求,这个时候就需要我们自定义异常。
在自定义异常的时候,首先需要确定定义的是编译时异常还是运行时异常。
自定义一个运行时异常,只需要去继承RuntimeException即可,添加两个构造方法
public class MyException extends RuntimeException{
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
自定义编译时异常,只需要去继承Exception即可,添加两个构造方法
public class MyException extends Exception{
public MyException(){
}
public MyException(String msg){
super(msg);
}
}