Java基础(十)——异常

28 篇文章 5 订阅
  1. 异常:就是程序在运行时出现不正常情况,
    异常由来:问题也就是现实生活中一个具体的事物,也可以通过Java的类的形式进行描述,并封装成对象。其实就是Java对不正常情况进行描述后的对象体现。

    对于问题的划分:两种:一种是严重的问题,一种非严重的问题。

    对于严重的,java通过Error类进行描述。
    (一般不编写针对行的代码对其进行处理。)

    对于非严重的,Java通过Exception类进行描述。
    (对于Exception可以进行针对性的处理方式进行处理。)

    无论Error后者Exception都具有一些共性内容。
    比如:不正常情况的信息,引发原因。

    Throwable
        |------Error
        |------Exception
            |------RuntimeException:除零,空指针,类型转换,数组越界等。
            |------

class Demo
{
    int div(int a, int b)
    {
        return a/b;
    }
}
public class ExceptionDemp {
    public static void main(String[] args)
    {
        Demo d = new Demo();
        int x = d.div(4,0);
        System.out.println("x = " + x);

        System.out.println("OVER");
    }
}
  1. 异常处理
    java提供了特有的语句进行处理
try
{
	需要被检测的代码;
}
catch(异常类 变量)
{
	处理异常的代码:处理方式;
}
finally
{
	一定会执行的代码;
}
class Demo
{
    int div(int a, int b)
    {
        return a/b;
    }
}
public class ExceptionDemp {
    public static void main(String[] args)
    {
        Demo d = new Demo();
        try {
            int x = d.div(4,0);
            System.out.println("x = " + x);
        }
        catch (Exception e)   //Exception e = new ArithmeticException();
        					//多态:父类引用指向子类对象,只能调用父类方法,执行子类覆写的方法
        {
            System.out.println("除零了");
            System.out.println(e.toString()); //  异常名称:异常信息
            System.out.println(e.getMessage());   //异常信息
            e.printStackTrace();       //异常名称:异常信息,异常出现的位置。
                                    //其实JVM默认的异常处理机制,就是在调用printStackTrace
                                    //打印异常的堆栈的跟踪信息。
        }
        System.out.println("OVER");
    }
}

在这里插入图片描述
3. 对捕获的异常对象进行常见的方法操作

e.toString() //  异常名称:异常信息
e.getMessage()  //异常信息
e.printStackTrace();    //异常名称:异常信息,异常出现的位置。
class Demo
{
    int div(int a, int b) throws Exception //throws谁调用我谁处理,
    //在功能上通过throws的关键字声明了该功能可能会出现问题
    {
        return a/b;
    }
}

方法一:向上抛出

public class ExceptionDemp {
    public static void main(String[] args) throws Exception  //扔给JVM处理(谁调用我谁处理)
    {
        Demo d = new Demo();

        int x = d.div(4,0);
        System.out.println("x = " + x);

        System.out.println("OVER");
    }
}

方法二:处理

public class ExceptionDemp {
    public static void main(String[] args) throws Exception  //扔给JVM处理(谁调用我谁处理)
    {
        Demo d = new Demo();
        try {
            int x = d.div(4, 0);
            System.out.println("x = " + x);
        }
        catch (Exception e)
        {
            System.out.println("除零了");
        }

        System.out.println("OVER");
    }
}
  1. 对多异常的处理
    a. 申明异常时,建议申明更为具体的异常,这样处理的可以更具体。
    b. 对方声明几个异常,就对应几个catch块,不要定义多余的catch块
    如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。

    建议在进行catch处理时,catch中一定要定义具体处理方式。
    也不要简单定义一句e.printStackTrace(),
    也不要简单的就书写一条输出语句。

  2. 自定义异常
    因为项目中会出现特有的问题,而这些问题并未被Java所描述并封装对象。
    所以对于这些特有问题可以安装java的对对象封装的思想。
    将特有的问题,进行自定义的异常封装。

    当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
    要么在内部try catch处理
    要么在函数上throws声明让调用者处理。
    一般情况下,函数内出现异常,函数上需要声明

public class FuShuException extends Exception
{

}

class Demo1{
    int div(int a, int b) throws FuShuException
    {
        if(b < 0)
            throw new FuShuException();  //函数内部抛出异常,方法上一定要声明
        return a/b;
    }
}

class ExceptionDemo2
{
    public static void main(String[] args) {
        Demo1 d = new Demo1();
        try
        {
            int x = d.div(4,-1);
            System.out.println("x = " + x);
        }
        catch (FuShuException e)
        {
            System.out.println(e.toString());
            System.out.println("除数出现负数了");
        }
    }
}

在这里插入图片描述

发现打印的结果中只有异常的名称,却没有异常的信息
因为自定义的异常并没有定义信息。

如何自定义信息呢?
public class FuShuException extends Exception
{
    private String msg;
    FuShuException(String msg)
    {
        this.msg = msg;
    }
    public String getMessage()
    {
        return msg;
    }
}

class Demo1{
    int div(int a, int b) throws FuShuException
    {
        if(b < 0)
            throw new FuShuException("除数中出现了负数的情况: / by 负数");  //函数内部抛出异常,方法上一定要声明
        return a/b;
    }
}

class ExceptionDemo2
{
    public static void main(String[] args) {
        Demo1 d = new Demo1();
        try
        {
            int x = d.div(4,-1);
            System.out.println("x = " + x);
        }
        catch (FuShuException e)
        {
            System.out.println(e.toString()); //异常名称:异常信息
            System.out.println(e.getMessage());  //异常信息
            System.out.println("除数出现负数了");
        }
    }
}

在这里插入图片描述
Exception已经定义好了。
因为父类中已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息传递给父类通过super语句。
那么就可以直接通过getMessage方法获取自定义信息。

public class FuShuException extends Exception
{
    FuShuException(String msg){
        super(msg);
    }
}

注意:自定义异常必须要继承Exception
原因:异常体系有一个特点,因为异常类和异常对象都被抛出。
他们都具备可拋性,这个可抛性时Throwable这个体系中独有的特点。
只有这个体系中的类和对象才可以被throw和throws操作。

throw和throws的区别:
throws使用在函数上,后面可以跟多个异常类,用逗号隔开
throw使用在函数内,后面跟的是异常对象。

  1. RuntimeException,运行时异常(Exception特殊异常类,引发程序停止)
    如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
    如果在函数上声明了该异常,调用者可以不用处理,编译一样通过。
    让程序停下来,让程序员修改代码。

    之所以不用在函数声明,是因为需要调用者处理。
    当该异常发生,希望程序停止。因为在运行时,出现可无法继续运算的情况,希望停止程序后,对代码进行修改。

    自定义异常时:如果该异常的发生,无法再继续进行运算。
    就让自定义异常继承RuntimeException。

对于异常分两种:
a. 编译时被检测的异常。(非RuntimeException)
b. 编译时不被检测的异常(运行时异常,RuntimeException以及其子类)

练习:
a. 老师用电脑上课
比如:电脑蓝屏,
    电脑冒烟
要对问题进行描述,封装成对象

可是当冒烟发生后,出现讲课进度无法继续。
出现讲课问题:课时计划无法完成。

class LanPingException extends Exception
{
    LanPingException(String msg){
        super(msg);
    }
}

class MaoYanException extends Exception
{
    MaoYanException(String msg)
    {
        super(msg);
    }
}

class NoPlansException extends Exception
{
    NoPlansException(String msg)
    {
        super(msg);
    }
}

class Computer
{
    private int state = 3;   //状态标识
    public void run() throws LanPingException, MaoYanException
    {
        if(state == 2)
            throw new LanPingException("蓝屏了");
        if(state == 3)
            throw new MaoYanException("冒烟了");
        System.out.println("电脑运行");
    }

    public void reset()
    {
        state = 1;
        System.out.println("电脑重启");
    }
}

public class Teacher {
    private String name;
    private Computer cmpt;
    Teacher(String name)
    {
        this.name = name;
        cmpt = new Computer();
    }
    public void prelect() throws NoPlansException
    {
        try
        {
            cmpt.run();
        }
        catch (LanPingException e)
        {
            cmpt.reset();
        }
        catch (MaoYanException e)
        {
            test();
            throw new NoPlansException("课时无法继续 原因:" + e.getMessage());
            //throw  停止当前函数运行,相当于return
        }
        System.out.println("讲课");
    }
    public void test()
    {
        System.out.println("做练习");
    }
}

class Test
{
    public static void main(String[] args) {
        Teacher t = new Teacher("毕老师");
        try
        {
            t.prelect();
        }
        catch (NoPlansException e)
        {
            System.out.println(e.toString());
            System.out.printf("换老师或者放假");
        }
    }
}
  1. finally关键字
    一定会执行的代码,通常用于关闭资源。
class NoException extends Exception   //数据库没有操作成功
{
    
}
public void method() throws NoException //SQLException{
{
	/*
    连接数据库;
    数据库操作;//throw  new SQLException();
    关闭数据库;//该动作,无论数据操作是否成功,一定要关闭资源
    */
    try
    {
        连接数据库;
        数据操作;//throw new SQLException();
    }
    catch (SQLException e)
    {
        会对数据库进行异常处理;
        throws new NoException();  //调用者可以识别
    }
    finally {
        关闭数据库;
    }
}
  1. 异常格式
    第一种;
try
{
}
catch(Exception e)
{
}

第二种:

try
{
}
catch()
{
}
finally
{
}

第三种:

try
{
}
finally
{
}
class Demo
{
	public void method()
	{
		try
		{
			throw new Exception();
		}
		catch(Exception e)
		{
			try
			{
				throw e;
			}
			catch()
			{
			}
		}
	}
}

注意:catch是用于处理异常。如果没有catch就代表异常没有被处理过,如果该异常是检测时异常。那么必须要声明或者处理。

  1. 异常在子父类中的体现:
    a. 子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类异常或者该异常的子类。(父类范围大,子类的范围小于等于父类)
    b. 如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子类。
    c. 如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
    如果子类方法发生了新异常,就必须进行try处理,绝对不能抛。

练习:
有一个圆形和长方形
都可以获取面积。对于面积如果出现非法的数值,视为时获取面积出现的问题。
问题通过异常来表示。
现在对这个程序进行基本设计。

class NoValeException extends RuntimeException // Exception
{
    NoValeException(String msg)
    {
        super(msg);
    }
}

interface  Shape
{
    void getArea();
}

class Rec implements Shape
{
    private int len, wid;
    Rec(int len, int wid) //throws NoValeException
    {
        if(len <=0 || wid <=0)
            throw new NoValeException("出现非法值");
        this.len = len;
        this.wid = wid;
    }
    public void getArea()
    {
        System.out.println(len*wid);
    }
}

class Circle implements Shape
{
    private int radius;
    public static final double PI = 3.14;
    Circle(int radius)
    {
        if(radius<=0)
            throw new NoValeException("非法");
        this.radius = radius;
    }

    public void getArea()
    {
        System.out.println(radius*radius*PI);
    }
}

class Test2
{
    public static void main(String[] args) {
        Rec r = new Rec(3,4);
        r.getArea();
        /*
        try{
            Rec r = new Rec(-3,4);
            r.getArea();
        }
        catch (NoValeException e)
        {
            System.out.println(e.toString());
        }
        System.out.println("OVER");
         */

        Circle c = new Circle(-1);
        r.getArea();
    }
}

异常:将正常代码和异常处理代码分离开,方便处理和阅读。

总结

异常:是对问题的描述。将问题进行对象的风筝。

异常体系
		Throwable
			|---Error
			|---Exception
				|---RuntimeException

异常体系的特点:异常体系中的所有类记忆建立的对象都具备可抛性。
也就是说可以被throw和throws关键字所操作。也只有异常体系具备这个特点。

throw和throws的用法:
throw定义在函数内,用于抛出异常对象。
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。

当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数上声明,否则编译失败。
注意:RuntimeException除外。也就是说,函数内如果抛出RuntimeException异常,函数上可以不用声明。

如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try.

异常有两种:
  编译时被检测异常
    该异常在编译时,如果没有处理——没有抛也没有try,编译失败。
    该异常被标识,代表这可以被处理。
  运行时异常(编译时不检测)
    在编译时,不需要处理,编译器不检查
    该异常的发生,建议不处理,让程序停止,需要对代码进行修正。

异常处理语句:

try
{
	需要被检测的代码;
}
catch()
{
	处理异常的代码;
}
finally
{
	一定会执行的代码;
}

有三种结合方式

第一种;

try
{
}
catch(Exception e)
{
}

第二种:

try
{
}
catch()
{
}
finally
{
}

第三种:

try
{
}
finally
{
}

注意:
a. finally中定义的通常是:关闭资源代码。因为资源必须关闭。
b. finally中只有一种情况不会执行。当执行到System.exit(0);finally不会执行。

自定义异常:定义类继承Exception或者RuntimeException
a. 为了让该自定义类具备可抛性。
b. 让该类具备操作异常的共性方法。

当要定义自定义异常的信息时,可以使用父类已经定义好的功能。
异常信息传递给父类的构造方法。

class MyException extends Exception
{
	MyException(String msg)
	{
		super(msg);
	}
}

自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。

异常的好处:
a. 将问题进行封装。
b. 将正常流代码和问题代码相分离,方便阅读。

异常的处理原则:
a. 处理方式有两种:try或者throws
b. 调用到抛出异常的功能时,抛出几个,就处理几个。
一个try对应多个catch.
c. 多个catch,父类的catch放到最下面。
d. catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,也不要输出语句,也不要不写。
当捕获到的异常,本功能处理不了,可以继续在catch中抛出。

try
{
	ttrow new AException();
}
catch(AException e)
{
	throw e;
}

如果该异常处理不了,但并不属于该功能的异常。
可以将异常转换后,在抛出和该功能相关的异常。

或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去。
让调用者知道并处理,也可以将捕获异常处理后,转换新的异常并抛出。

try
{
	throw new AException();
}
catch(AException e)
{
	//对AException处理
	throw new BException();
}

异常的注意事项:
在子类覆盖时:
a. 子类抛出的异常必须时父类的异常的子类或者子集。
b. 如果父类或者接口没有抛出异常时,子类覆盖出现异常,只能try不能throws。
(子类不能抛出比父类多的异常)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值