1 Java运行时期发生的问题就是异常。
2 异常的体系
Java中运行时发生的除了异常Exception还有错误Error
Throwable
|--Error 不会有针对性的处理方式。必须修改代码。
|--Exception 通常发生可以有针对性的处理方式的。
|--RuntimeException 运行期异常
|--非RuntimeException 编译期异常,必须处理的
3 异常的处理:
A:JVM的默认处理
把异常的名称,原因,位置等信息输出在控制台,但是呢程序不能继续执行了。
B:自己处理
a:try...catch...finally
自己编写处理代码,后面的程序可以继续执行
b:throws
写在方法名后,参数列表前
4 案例
代码1:
public static void method3() {
int a = 10;
int b = 0;
int[] arr = {1, 2, 3};
try {
System.out.println(arr[3]);
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("除数不能为0");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你访问了不该的访问的索引");
}
System.out.println("over");
}
输出:
你访问了不该的访问的索引
over
// 一旦try里面出了问题,就会在这里把问题给抛出去,然后和catch里面的问题进行匹配,
// 然后继续执行catch外面的语句。
代码2:
* 有些时候,我们是可以对异常进行处理的,但是又有些时候,我们根本就没有权限去处理某个异常。
* 或者说,我处理不了,我就不处理了。
* 为了解决出错问题,Java针对这种情况,就提供了另一种处理方案:抛出。
*
* 小结:
* 编译期异常抛出,将来调用者必须处理。
* 运行期异常抛出,将来调用可以不用处理。
public class ExceptionDemo3 {
public static void main(String[] args) {
try{
method();
}catch(ParseException e){
//e.printStackTrace();
}
System.out.println("不该有雾霾");
method2();
}
// 编译期异常的抛出
public static void method() throws ParseException{
String s = "2014-11-20";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
System.out.println(d);
}
// 运行期异常的抛出
public static void method2() throws ArithmeticException{
int a = 10;
int b = 0;
System.out.println(a / b);
}
}
代码3:
出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常往往我们不对他处理罢了。也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。
异常处理的目标之一就是为了把程序从异常中恢复出来
5 面试题
A:编译期异常和运行期异常的区别?
编译期异常 必须要处理的,否则编译不通过
运行期异常 可以不处理,也可以处理
B:throw和throws是的区别
throw:
在方法体中;后面跟的是异常对象名;并且只能是一个;
throw说明这里肯定有一个异常产生了
throws:
在方法声明上;后面跟的是异常的类名;可以是多个
throws是声明方法有异常,是一种可能性,这个异常并不一定会产生
6 finally关键字及其面试题
A:finally用于释放资源,它的代码永远会执行。在IO流操作和数据库操作中会见到
特殊情况:在执行到finally之前jvm退出了(System.exit(0);)
B:面试题
a:final,finally,finalize的区别?
finalize是Object类的一个方法,用于垃圾回收
b:如果在catch里面有return,请问finally还执行吗?如果执行,在return前还是后
会,前。(实际上在中间)
C:异常处理的变形.
try...catch...catch...
代码1:
public static void main(String[] args) {
String s = "2014-11-20";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = null;
try{
d = sdf.parse(s);
}catch(ParseException e){
//System.exit(0);
}finally{
System.out.println("这里的代码是可以执行的");
}
System.out.println(d);
}
代码2:
public static void main(String[] args) {
System.out.println(getInt());
}
public static int getInt(){
int a = 10;
try{
System.out.println(a / 0);
a = 20;
}catch(ArithmeticException e){
a = 30;
return a;
/*
* 这里确切的说不是return a; 而是 return 30;然后继续执行finally中的语句
*/
}finally{
a = 40;
//return a;
}
return a;
}
7 自定义异常
继承自Exception或者RuntimeException,只需要提供无参构造和一个带参构造即可
代码1:
* java不可能对所有的情况都考虑到,所以,在实际的开发中,我们可能需要自己定义异常。
*
* 两种方式:
* A:继承Exception
* B:继承RuntimeException
public class MyException extends Exception{
public MyException(){}
public MyException(String message){
super(message);
}
}
// public class MyException extends RuntimeException {
//
// }
代码2:
public class Teacher {
public void check(int score)throws MyException{
if(score > 100 || score < 0){
throw new MyException("分数必须在0-100之间");
}else{
System.out.println("分数没有问题");
}
}
// 针对MyException继承自RuntimeException
// public void check(int score) {
// if (score > 100 || score < 0) {
// throw new MyException();
// } else {
// System.out.println("分数没有问题");
// }
// }
}
代码3:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生成绩:");
int score = sc.nextInt();
Teacher t = new Teacher();
try{
t.check(score);
}catch(MyException e){
e.printStackTrace();
}
}
8 异常的注意实现
A:父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于等于父的异常
B:父的方法没有异常抛出,子的重写方法不能有异常抛出
C:父的方法抛出多个异常,子的重写方法必须比父少或者小
代码1:
class Fu{
public void show() throws Exception{}
public void method(){}
}
class Zi extends Fu{
public void show() throws ArithmeticException{}
public void method(){}
}