异常类
1.继承关系
Throwable (父类)
两个子类:
- Error:不能处理的 XXXError
- Exception:能处理的 xxxException
Exception分为:
- RuntimeException:运行时
- 其他:编译时
运行时异常(RuntimeException):
NullPointerException,ArrayIndexOfBoundsException
StringIndexOfBoundsException,ArithmeticException等
编译时产生的异常:
IOException,FileNotFoundException,InterruptedException,SQLException 等
2.处理异常:
运行时异常不强制处理,如果代码写的严谨,可以避免运行时异常的产生;
编译时产生的异常必须处理
//运行异常
//运行时异常,如果代码写的严谨,可以避免运行时异常
String[] names=null;
System.out.println(names[0].substring(0));
int[] num= {2};
System.out.println(num[1]);
3.异常处理的两种方式:
-
throws 声明异常(mian方法抛异常,由jvm处理 )
-
try-catch块捕获异常
异常代码块:在日志文件中保存堆栈信息
外行,翻译异常信息
检查代码:直接打印堆栈信息
一旦有某行代码异常,程序终止,后面的代码不能被执行。
- try-catch块捕获异常
//处理异常的两种方式:
//throws 抛出异常
//try catch块
public static void test3() {
try {
FileReader fr=new FileReader("a.txt");
//System.out.println("上面一旦异常,则这句不会执行,执行下面的catch,finally是一定会执行的");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
}
}
上面程序调用了 Exception 对象 getMessage() 方法来得到异常对象的详细信息。运行上面程序,结果:
a.txt (系统找不到指定的文件。)
a.txt没找到
- throws 抛出异常(声明异常)
//编译时异常
public static void test2() throws FileNotFoundException {
FileReader fr=new FileReader("a.txt");
}
jvm处理:
4.异常块的正确使用语法
try-catch
try-catch-finally
try-catch-catch…finally
try-finally:语法是正确的,但不能捕获异常
异常处理语法结构中只有try块是必需的, catch 块和finally 块都是可选的,但catch块和finally块至少出现其中之一,也可以同时出现;可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面;但不能只有try块,既没有catch 块,也没有finally 块;多个catch块必须位于try 块之后,finally 块必须位于所有的catch块之后。看如下程序。
处理多个异常方式一:
一个try后面可以跟多个catch,且必须有catch
public static void test4() {
try {
FileReader fr=new FileReader("a.txt");
Thread.sleep(1000);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
处理多个异常方式二:异常为Exception
public static void test5() {
try {
FileReader fr=new FileReader("a.txt");
Thread.sleep(1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch只捕获和他最近的try的异常(多个try跟一个catch不对)
以下为错误代码:
public static void test6() {
try {
FileReader fr=new FileReader("a.txt");
Thread.sleep(1000);
}try {
Thread.sleep(1000);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
5.try-catch可以嵌套使用try-catch块
6.执行过程:
如果try中有异常,从异常语句开始,不再执行try后边的语句
跳到catch执行
不管有无异常,finally块都会执行
练习:
1.return表示方法的结束
public static int test6() {
try{
return 1 ;
}catch(Exception e){
return 2;
}finally{
System.out.println("end");
}
}
//结果为end 1
public static int test7() {
int i=0;
try {
return i++;
}catch (Exception e) {
return 2;
}finally {
i++;
System.out.println(i);
System.out.println("end");
}
}
// 2 end 0 (try先做运算,最后再输出)
public static int test7() {
int i=0;
try {
return i++;
}catch (Exception e) {
return 2;
}finally {
i++;
System.out.println(i);
System.out.println("end");
return i++;
}
}
// 2 end
上面程序在 final 块中定义了一个 return 语句,这将导致try块中的 return 失去作用。
当Java程序执行try块、catch 块时遇到了return 或throw语句,这两个语句都会导致该方法立即结束,但是系统执行这两个语句并不会结束该方法,而是去寻找该异常处理流程中是否包含finally 块,如果没有finally块,程序立即执行return或throw语句,方法终止;如果有finally块,系统立即开始执行finally块——只有当finally块执行完成后,系统才会再次跳回来执行try块.catch块里的return或throw语句;如果finally块里也使用了return 或throw等导致方法终止的语句,finally 块已经终止了方法,系统将不会跳回去执行try块、catch 块里的任何代码。
注意: 在 finally块中,尽量不要写return,有时候会屏蔽异常代码
public static String test7(String name){
try{
name.length();
}finally{
return name+"hello";
}
}
public static void main(String[] args) {
System.out.println(test7(null));
}
结果为:
nullhello
自定义异常类:
标识异常类:继承任意异常类
异常信息:super(msg)
使用:if()throw new 异常类();
(问题:如果没有接口(因为里面默认是常量),直接在子类构造器中super(“请输入…”)会不会报错)????
关于这个问题,可以去看https://blog.csdn.net/mcaiWu/article/details/52637093
“子类无参构造调用父类有参构造方法”这篇文章。
解答:如果直接在AgeException类中写
String ageMsh=“请输入正确的范围(0-100)”;
AgeException(){
//调用父类带参的构造方法,初始化错误信息 super(ageMsh); }
则编译错误。 因为先回执行父类的静态,子类的静态,父类的构造,子类的构造。由于子类没有静态,所以执行构造时,没法传入String message;
//定义接口是因为里面的值是static修饰的
public interface DemoMessage {
String ageMsh="请输入正确的范围(0-100)";
}
//自定义异常类:继承现有的异常
public class AgeException extends Exception{
AgeException(){
//调用父类带参的构造方法,初始化错误信息
super(DemoMessage.ageMsh);
}
}
public class Student {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) throws AgeException {
//使用自定义的异常
if(age<=0||age>=100)
throw new AgeException(); //抛出异常
this.age = age;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Student stu=new Student();
try {
stu.setAge(100);
System.out.println(stu.getAge());
} catch (AgeException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
}
}
方法重写时声明抛出异常的限制
子类方法重写父类的方法的异常规则:
异常<=父类的(指编译时异常,和运行时异常没有关系)
<= :
个数,异常类型
class A{
public void test()throws IOException,SQLException{
}
public void test2(){
}
}
public class Demo4 extends A {
public void test()throws IOException{
}
public void test2()throws RuntimeException{
}
}
throw 和 throws的区别
throw :抛出异常 throws:声明异常
在方法内 方法声明
+ 异常类的对象 + 异常类的类型
只能有一个异常类的对象 多个异常类型,用,隔开
小结:
1.异常的继承关系
2.Exception
3.处理异常
4.try-catch多种格式
5.自定义异常
extends Exception
super(异常信息);
用:if(){throw 异常类对象}
6.方法重写的异常(编译时异常)