0.复习面向对象
1.异常的体系结构
异常:在Java语言中,将程序执行中发生的不正常情况.(开发中的语法错误和逻辑错误不是异常)
异常事件分两类(它们上一级为java.lang.Throwable
):
Error
Java虚拟机无法解决的严重问题。可以不使用针对性的代码进行处理。(如:JVM系统内部错误,资源耗尽等)
Exception
其他因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。(如:空指针访问,网络中断等)
可分为:
编译时异常:在编译期间出现的异常(执行javac.exe命令时,出现异常)
运行时异常:在运行时出现的异常(执行java,exe命令时,出现的异常)
例:
当执行一个程序时,如果出现异常,那么异常之后的代码就不再执行。
2.处理Exception的异常
Java提供的是异常处理的抓抛模型
“抛”
当我们执行代码时,一旦出现异常,就会在异常的代码处生成一个对应的异常类型的对象,并将此对象抛出。(一旦对象抛出,程序停止执行;异常类的对象抛给方法的调用者)
可分为:
自动抛出
手动抛出(throw + 异常类的对象
)
即可以是现成的异常类,也可以自定义的异常类
例:
public class Test4{public static void main(String[] args) { Circle c = new Circle(2.2);Circle c1 = new Circle(2.2);System.out.println(c.compareTo(c1));System.out.println(c.compareTo(new String("AA")));}
}
class Circle {private double radius;//构造器public Circle(double radius){super();this.radius = radius;}//方法public void setRadius(double radius){this.radius = radius;}public double getRadius(){return this.radius;}public int compareTo(Object obj){if(obj == this)return 0;else if(obj instanceof Circle){Circle c1 = (Circle)obj;if(this.radius > c1.radius){return 1;}else if(this.radius == c1.radius){return 0;}else{return -1;}}else{//手动抛出异常throw new RuntimeException("传入的类型有误");//抛出自定义的异常(具体编写见下代码块)//throw new TestException("传入的类型有误");}}
}
自定义异常类
- 自定义的异常类继承现有的异常类
- 提供序列号,提供几个重载的构造器
例:
//自定义的异常类public class TestException extends RuntimeException{ static final long serialVersionUID = -7123453234353423L;public TestException(){}public TestException(String msg){super(msg);}
}
“抓”
抓住上一步抛出的异常类的对象。(抓的方式即为异常处理的方式)
Java提供两种方式来处理一个异常类的对象
方式一(try-catch-finally
)
try{ //可能出现异常的代码
}catch(Exception e1){//处理方式1
}catch(Exception e2){//处理方式2
}....{//处理方式
}finally{//一定要执行的代码
}
注:
-
try内声明的变量,类似于局部变量,出了
try{}
语句,就不能被调用 -
finally
是可选的 -
catch
语句内部是对异常对象的处理getMessage()
:显示执行过程中出现的异常printStackTrace()
:显示堆出现的异常(打印异常信息在程序中出错的位置及原因)
-
可以有多个
catch
语句的代码,try
中抛出的异常类对象从上往下匹配catch中的异常类1的类型,一旦满足就执行catch
中的代码,执行完,就跳过之后的catch
语句(多条catch语句满足其一就行) -
如果异常处理了,那么其后的代码继续执行
-
若多个
catch
语句中的异常类型为"包含"关系,需要子类放在父类之前进行处理,否则报错 -
若多个
catch
语句中的异常类型为"并列"关系,则无先后放置的要求 -
不管
try,catch
中是否处理完异常,及是否有return
语句,finally
中存放的语句一定执行。 -
try-catch
语句可以嵌套 -
运行时异常,可以不显式处理;编译时异常,必须显式处理
例:常见的异常
import org.junit.Test;
import java.io.*;
import java.util.Date;
public class Test2{//1.数组下标越界的异常:ArrayIndexOutOfBoundsException@Testpublic void test(){try{ int[] i = new int[10];System.out.println(i[10]);}catch(ArrayIndexOutOfBoundsException e){System.out.println("数组下标越界");}}//2.算术异常:ArithmeticException@Testpublic void test1(){int i = 10;try{System.out.println(i/0);}catch(ArithmeticException e){System.out.println("\u7B97\u672F\u5F02\u5E38啦!");}}//3.类型转换异常:ClassCastException@Testpublic void test2(){try{Object obj = new Date();String str = (String)obj;}catch(ClassCastException e){System.out.println(e.getMessage());}}//4.空指针异常:NullPointerException@Testpublic void test3(){try{Person p = null;System.out.println(p.toString());}catch(NullPointerException e){System.out.println(e.fillInStackTrace());}}//编译时异常@Testpublic void test4(){FileInputStream f = null;try{f = new FileInputStream(new File("hello.txt"));int b;while((b = f.read()) != -1){System.out.println((char)b);}}catch(FileNotFoundException e){System.out.println("文件不存在");}catch(IOException e){System.out.println("输入输出有误");}finally{try{f.close();}catch(Exception e){System.out.println("文件关闭异常");}finally{System.out.println("程序执行完毕");}}}
}
方式二(throws + 异常的类型
)
- 在方法的声明处,显式的抛出该异常对象的类型
- 格式:如:
public static void test6() throwsFileNotFoundException,IOException{ }
- 当在此方法内部出现异常时,会抛出异常对象给调用者。
- 异常的对象可以逐层向上抛,直至
main
中,在此过程中可以用try-catch-finally
进行处理
例:
import java.io.*;public class Test3{public static void main(String[] args) throws FileNotFoundException,IOException{ try{test6();}catch(FileNotFoundException e){System.out.println(e.getMessage());}catch(IOException e){e.printStackTrace();}}public static void test6() throws FileNotFoundException,IOException{test5();}
public static void test5() throws FileNotFoundException,IOException{FileInputStream f = new FileInputStream(new File("hello1.txt"));int b;while((b = f.read()) != -1){System.out.println((char)b);}f.close();}
}
- 子类重写的父类异常方法,其抛出异常类只能是被重写的方法的异常类的子类或异常类型
例:
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;public class Test6{public static void main(String[] args) throws IOException { A a = new B();a.test1();}}
class A{public void test1() throws IOException{}
}
class B extends A{public void test1() throws FileAlreadyExistsException{}
}
练习
题一
结果:
进入A
A-finally
制造异常
进入B
B-finally
题二
public class EcmDef{public static void main(String[] args) { try{int i = Integer.parseInt(args[0]);//被除数int j = Integer.parseInt(args[1]);//除数ecm(i, j);}catch(NumberFormatException e){System.out.println("输入数据类型不一致");}catch(ArrayIndexOutOfBoundsException e){System.out.println("缺少命令行参数");}catch(ArithmeticException e){System.out.println("错误:分母为零");}catch(EcDef e){System.out.println(e.getMessage());}}public static void ecm(int i,int j) throws EcDef{if(i < 0 || j < 0){throw new EcDef("输入的数值存在负数");}System.out.println(i/j);}
}
//自定义异常类
class EcDef extends Exception{static final long serialVersionUID = -7223453234353423L;public EcDef(){}public EcDef(String msg){super(msg);}}
感谢大家的支持,关注,评论,点赞!
参考资料:
尚硅谷宋红康20天搞定Java基础中部