1、异常的分类
Error是无法处理的异常,比如OutOfMemoryError,一般发生这种异常,JVM会选择终止程序。因此我们编写程序时不需要关心这类异常。
Exception类的异常包括checked exception和unchecked exception(unchecked exception也称运行时异常RuntimeException,当然这里的运行时异常并不是前面我所说的运行期间的异常,只是Java中用运行时异常这个术语来表示,Exception类的异常都是在运行期间发生的)。
运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。
非运行时异常(运行时异常以外的异常就是非运行时异常),java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。
2、异常处理的三种方式
1)对代码块用try…catch进行异常捕获处理;
2)在该代码的方法体外用throws进行抛出声明,告知此方法的调用者这段代码可能会出现这些异常,你需要谨慎处理。此时有两种情况:
如果声明抛出的异常是非运行时异常,此方法的调用者必须显示地用try…catch块进行捕获或者继续向上层抛出异常。
如果声明抛出的异常是运行时异常,此方法的调用者可以选择地进行异常捕获处理。
3)在代码块用throw手动抛出一个异常对象,此时也有两种情况,跟2)中的类似:
如果抛出的异常对象是非运行时异常,此方法的调用者必须显示地用try…catch块进行捕获或者继续向上层抛出异常。
如果抛出的异常对象是运行时异常,此方法的调用者可以选择地进行异常捕获处理。
当然catch块可以有多个,注意try块只能有一个,finally块是可选的(但是最多只能有一个finally块)。
如果没有发生异常,则catch块不会执行。但是finally块无论在什么情况下都是会执行的(这点要非常注意,因此部分情况下,都会将释放资源的操作放在finally块中进行)。
try {
// 可能会发生异常的程序代码
} catch (Type1 id1) {
// 捕获并处理try抛出的异常类型Type1
} catch (Type2 id2) {
// 捕获并处理try抛出的异常类型Type2
} finally {
// 无论是否发生异常,都将执行的语句块
}
public class TestException {
public static void main(String args[]) {
int i = 0;
String greetings[] = { " Hello world !", " Hello World !! ",
" HELLO WORLD !!!" };
while (i < 4) {
try {
// 特别注意循环控制变量i的设计,避免造成无限循环
System.out.println(greetings[i++]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界异常");
} finally {
System.out.println("--------------------------");
}
}
}
}
public String openFile() {
try {
FileInputStream inputStream = new FileInputStream("d:/a.txt");
int ch = inputStream.read();
System.out.println("aaa");
return "step1";
} catch (FileNotFoundException e) {
System.out.println("file not found");
return "step2";
}catch (IOException e) {
System.out.println("io exception");
return "step3";
}finally{
System.out.println("finally block");
//return "finally";
}
}
public class Main {
public static void main(String[] args) {
try {
int[] data = new int[]{1,2,3};
System.out.println(getDataByIndex(-1,data));
} catch (Exception e) {//捕获异常对象
System.out.println(e.getMessage());//调用异常对象的getMassage()方法
}
}
public static int getDataByIndex(int index,int[] data) {
if(index<0||index>=data.length)
throw new ArrayIndexOutOfBoundsException("数组下标越界");//抛出一个新建的异常对象
return data[index];
}
}
3、throws与throw的区别
throws:
****用在方法声明后面,跟的是异常类型名。
****可以跟多个异常类名,用逗号隔开。
****表示抛出异常,由该方法的调用者来调用。
****throws表示出现异常的一种可能性,并不一定会发生这些异常。
****可以单独使用。
throw:
****用在方法体内,跟的是异常对象名。
****只能抛出一个异常对象名。
****表示抛出异常,由方法体内的语句处理。
****throw则是抛出了异常,执行throw则一定是抛出了某种异常。
****不可以单独使用,需配合throws或try,catch使用。
public class demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s = "abc";
if(s.equals("abc")) {
throw new NumberFormatException();
} else {
System.out.println(s);
}
}
}
public class throwsdemo {
public static void function() throws NumberFormatException{
String s = "abc";
System.out.println(Double.parseDouble(s));
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
function();
} catch (NumberFormatException e) {
System.err.println("非数据类型不能转换。");
//e.printStackTrace();
}
}
}