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
@Test
public void test(){
try{
int[] i = new int[10];
System.out.println(i[10]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组下标越界");
}
}
//2.算术异常:ArithmeticException
@Test
public void test1(){
int i = 10;
try{
System.out.println(i/0);
}catch(ArithmeticException e){
System.out.println("\u7B97\u672F\u5F02\u5E38啦!");
}
}
//3.类型转换异常:ClassCastException
@Test
public void test2(){
try{
Object obj = new Date();
String str = (String)obj;
}catch(ClassCastException e){
System.out.println(e.getMessage());
}
}
//4.空指针异常:NullPointerException
@Test
public void test3(){
try{
Person p = null;
System.out.println(p.toString());
}catch(NullPointerException e){
System.out.println(e.fillInStackTrace());
}
}
//编译时异常
@Test
public 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基础中部