**Throwable:**在程序定义中一般指不期而至的各种情况,如:文件找不到、网络连接失败、非法参数等。异常是一种事件,它发生在程序运行期间、或者代码编译时候,它干扰了正常的程序指令流程继续下去。Java通过API中的Throwable类的众多子类描述各种不同的异常。其中Error与Exception也都是Throwable的两个重要子类。
**Error:**即错误,是在程序编译时出现的错误,表示在运行应用程序中较严重的问题,一般与代码无关,只能通过修改程序才能修正。一般是JVM(Java虚拟机)的相关问题。如系统崩溃,虚拟机错误,内存不足,动态链接失败等。
例如两个比较常见的错误,一个是Virtual MachineError(Java虚拟机运行错误) 代码在运行时JVM出现的问题;
还有一个是OutOfMemoryError,即JVM不再继续执行操作所需的内存资源。
对于这种错误程序本身是无法恢复和预防的,当这些错误发生时,JVM会选择线程停止。
**Exception:**即异常,是指程序本身可以处理的异常,可以捕获且可能可以恢复。当遇到这类异常时,要尽可能处理异常,增强代码的健壮性,使程序恢复运行。
Exception可以分为CheckedException(UnCheckedException)编译异常(非运行时异常)和RuntimeException运行时异常
**RuntimeException运行时异常:**就是我们在开发测试功能时程序终止,控制台出现异常
常见的有:
ArithmeticException 算数异常
NullPointerException 空指针异常(最容易出现最容易犯的错)
ArrayIndexOutOfBoundsException 索引超出异常
IndexOutOfBoundsException 下标越界异常
ClassCastException 两个类型转换不兼容
NumberFormatException 数字格式异常
对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。
故该类的异常处理方法有:(下面会对两种方法进行讲解)
CheckedException(UnCheckedException)编译异常:也叫检查异常或非运行异常,也就是程序在编译时就出现异常。
常见的异常有:
IOException输入或输出异常(即写读异常)
FileNotFoundException文件未被找到
SQLException数据库交互异常
对于非运行时异常,java编译器强制程序员必须进行捕获处理,如果不进行捕获或者抛出声明处理,编译无法通过。
故该类的异常处理方法有:(下面会对两种方法进行讲解)
使用try和catch关键字,对异常先进行捕获,再进行处理。
try中包围的代码表示这段代码可能会发生异常,如果发生异常,便会被catch捕获到,然后在catch块中对异常进行处理。
下面看一个例子:
public static void main(String[] args) {
try {
File file = new File("e:/demo1.txt");
if(!file.exists())
file.createNewFile();
} catch (IOException e) {
// TODO: handle exception
}
}
何为抛出异常?
一个方法不处理这个异常,而是调用层次向上传递,谁调用这个方法,这个异常就由谁来处理。此时需要用到throw或throws关键字。
第一种方法是使用throws关键字 :
如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。
用它修饰的方法向调用者表明该方法可能会抛出异常(可以是一种类型,也可以是多种类型,用逗号隔开)
(位置: 写在方法名 或方法名列表之后 ,在方法体之前。)
下面看一个具体的例子:
public class Demo01{
public static void createException() throws IOException{
File file = new File("e:/Demo1.txt");
if(!file.exists())
file.createNewFile();
}
public static void main(String[] args) {
try{
createException();
}catch(Exception e){
// TODO: handle exception
}
}
}
在实际的createException方法中并没有捕获异常,而是用throws关键字声明抛出异常,即告知这个方法的调用者此方法可能会抛出IOException。那么在main方法中调用createException方法的时候,再采用try…catch块对异常进行捕获。
PS:如果最终将异常抛给main方法,则相当于交给jvm自动处理,此时jvm会简单地打印异常信息
第二种方法就是使用throw手动来抛出异常对象 :
将产生的异常抛出(强调的是动作),抛出的既可以是异常的引用,也可以是异常对象。(位置: 方法体内)
下面看一个具体的例子:
public class Demo02 {
public static void main(String[] args) {
try {
int[] data = new int[]{1,2,3,4};
System.out.println(getDataByIndex(5,data));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static int getDataByIndex(int index,int[] data) {
if(index<0||index>=data.length)
throw new ArrayIndexOutOfBoundsException("数组下标越界");
return data[index];
}
}
当然还可以自定义异常,自定义异常类继承于Exception类,其他操作相同。
1.若父类的方法中没有抛出异常,则子类在重写该方法时不可以抛出异常
2.若父类的方法声明了一个异常,那么子类在重写该方法时声明的异常不能大于父类(即不能是父类异常的上级异常)
3.若父类的方法声明的异常只有非运行异常或者运行异常其中的一个,那么子类在重写这个方法时也只能有与父类相同类型的一种异常。
1.final finally finalize的区别
final用于修饰类 方法 属性,修饰类表示类无法被继承,修饰方法表示方法无法被重写,修饰属性表示是常量
finalize是Object自带方法,当System.gc()会先调用此方法
finally与try-catch合用,表示无论如何都会执行,在return前执行,一般用于关闭资源
2.不要频繁使用异常,可能会影响程序的性能
3.只能由一个try,但可以对应多个catch块
4.不要使用空catch块,捕获了异常又对它不进行处理,那么相当于隐藏了这个异常,可能会导致程序出现不可预判的结果。
5.在finally中可以放释放资源的语句,例如关闭文件等操作,可以节约程序的资源,避免引起不必要的因为资源未关闭而导致的异常或者是资源的浪费。