2、java.lang.Throwable异常体系

一、异常

 

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

二、好处

 

  1. 将问题进行封装
  2. 将正常流程代码和问题处理代码相分离,方便于阅读

三、问题有两种

 

1,严重的问题:java通过Error类进行描述

 

    对于Error一般不编写针对性的代码对其进行处理

 

2,非严重的问题:java通过Exception类进行描述

 

    对于Exception可以使用针对性的处理方式进行处理

 

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

 

四、异常的体系:

Throwable

	|--Error		:通常出现重大问题如:运行的类不存在或者内存溢出等
	
	|--Exception	:在运行时出现的一些情况,可以通过try catch finally等处理

 

五、异常体系的特点

 

  • 这个体系中的所有类和对象都具备一个独有的特点;就是可抛性
  • 即可以被:throw throws 操作

六、Throwable类

 

  • Throwable 类是 Java 语言中所有错误或异常的超类。
  • 只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。
  • 类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。
public class Throwable implements Serializable
{
	//成员变量
	private static final long serialVersionUID = -3042686055658047285L;
	private String detailMessage;
	private Throwable cause = this;
	
	//1、构造方法:构造一个将 null 作为其详细消息的新 throwable。
	public Throwable() {
        fillInStackTrace();
    }

	//2、构造方法:构造带指定详细消息的新 throwable。
	public Throwable(String message) {
        fillInStackTrace();
        detailMessage = message;
    }

	//3、构造方法:构造一个带指定详细消息和 cause 的新 throwable。
	public Throwable(String message, Throwable cause) {
        fillInStackTrace();
        detailMessage = message;
        this.cause = cause;
    }

	//4、构造方法:构造一个带指定 cause 和 (cause==null ? null :cause.toString())(它通常包含类和 cause 的详细消息)的详细消息的新 throwable。
	public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }

	//-----------------------------------------------

	//1、在异常堆栈跟踪中填充。此方法在 Throwable 对象信息中记录有关当前线程堆栈帧的当前状态
	public synchronized native Throwable fillInStackTrace();

	//2、返回此 throwable 的详细消息字符串。
	public String getMessage() {
        return detailMessage;
    }

	//3、返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null
	public Throwable getCause() {
        return (cause==this ? null : cause);
    }

	//4、创建此 throwable 的本地化描述。子类可以重写此方法,以便生成特定于语言环境的消息。对于不重写此方法的子类,默认实现返回与 getMessage() 相同的结果。 
	public String getLocalizedMessage() {
        return getMessage();
    }

	//5、将此 throwable 及其追踪输出至标准错误流。
	public String toString() {
        String s = getClass().getName();
        String message = getLocalizedMessage();
        return (message != null) ? (s + ": " + message) : s;
    }

	//6、将此 throwable 及其追踪输出至标准错误流
	//此方法将此 Throwable 对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。
	public void printStackTrace() {
        printStackTrace(System.err);
    }

	//7、将此 throwable 及其追踪输出到指定的输出流。
	public void printStackTrace(PrintStream s) {
        synchronized (s) {
            s.println(this);//toString
            StackTraceElement[] trace = getOurStackTrace();
            for (int i=0; i < trace.length; i++)
                s.println("\tat " + trace[i]);

            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printStackTraceAsCause(s, trace);
        }
    }

	//8、将此 throwable 及其追踪输出到指定的 PrintWriter。
	public void printStackTrace(PrintWriter s) {
        synchronized (s) {
            s.println(this);
            StackTraceElement[] trace = getOurStackTrace();
            for (int i=0; i < trace.length; i++)
                s.println("\tat " + trace[i]);

            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printStackTraceAsCause(s, trace);
        }
    }
}

 

七、Exception 类

 

    Exception 及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。

public class Exception extends Throwable
{
	//字段
	static final long serialVersionUID = -3387516993124229948L;

	//构造方法
	public Exception() {
		super();
    }
	public Exception(String message) {
		super(message);
    }
	public Exception(String message, Throwable cause) {
        super(message, cause);
    }
	public Exception(Throwable cause) {
        super(cause);
    }

	/*方法
		从类 java.lang.Throwable 继承的方法 
				fillInStackTrace, getCause, getLocalizedMessage, getMessage, 
				getStackTrace, initCause, printStackTrace, printStackTrace,
				printStackTrace, setStackTrace, toString 
		从类 java.lang.Object 继承的方法 
				clone, equals, finalize, getClass,
				hashCode, notify, notifyAll, wait, wait, wait 

	*/
}

 

八、异常的命名

 

    通常前面是功能后面是父类名

 

九、异常的处理

 

1,可抛可try(捕获)

2,java提供了特有的语句捕捉异常

try
{
	需要被检测的代码
}
catch(异常类 变量)
{
	处理异常的代码:(处理方式)
}
finally
{
	一定会执行的语句
}
常见的三种格式:
try{} catch(){}

try{} catch(){} finally{}

try{} finally{}

 

 

    记住一点:catch是用于处理异常.如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,那么必须声明

 

3,在开发时,如果定义功能时,发现该功能会出现一些问题,应该将问题在定义功能时标示出来,这样调用者就可以在使用这个功能的时候,预先给出处理方式。

 

  • 如何标示呢?通过throws关键字完成, 格式:throws 异常类名,异常类名...
  • 这样标示后,调用者在使用该功能时,就必须要处理,否则编译失败

4,异常处理原则

 

  • 功能抛出几个异常,功能调用如果进行try处理,需要与之对应的catch处理代码块,这样的处理有针对性,抛几个就处理几个。
  • 特殊情况:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。
  • 建议在进行catch处理时,catch中一定要定义具体处理方式,不要简单定义一句e.printStackTrace()
  • 也不要简单的就写一条输出语句
  • 因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。
  • 所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装 。

十、自定义异常

/*
需求:在本程序中,对于除数是-1,也视为是错误的是无法进行运算的
思路:需要对这个问题进行自定义描述
*/

//自定义异常
class FuShuException extends Exception
{
	FuShuException(String s)
	{
		super(s);
	}
}
class Demo
{
	int div(int a,int b)throws FuShuException
	{
		if(b<0)
			throw new FuShuException("除数出现了负数");
		return a/b;
	}
}
class ExceptionTest
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		try{
			int x = d.div(4,-1);
		}catch(FuShuException e){
			System.out.println(e.toString());
		}
		System.out.println("over");
	}
}

 

十一、throw和throws的区别

 

  1. throw:用在函数内,后面跟的是异常对象
  2. throws:用在函数上,后面跟的是异常类,可以跟多个,用逗号隔开
  3. 通常情况:函数内容如果有throw,抛出异常对象,并没有进行处理,那么函数上一定要声明,否则编译失败。
  4. 特殊情况:
  •    Exception 中有一个特殊的子类异常 RuntimeException运行时异常,
  •    如果在函数内抛出该异常,函数上可以不用声明,编译一样通过
  •    如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过
  •    之所以不用在函数声明,是因为不需要让调用者处理, 当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后, 对代码进行修正。

十二、finally代码块

 

  1. 存放的是一定要执行的代码,通常用于关闭资源
  2. finally只有一种情况不会执行,当执行到System.exit(0);finally不会执行

十三、异常分两种

 

  1. 编译时被检测的异常,只要是Exception及其子类都是编译时被检测的异常。
  2. 编译时不被检测的异常(运行时异常,RuntimeException以及其子类)
  3. 示例:老师用电脑讲课
/*
需求:模拟老师用电脑讲课
思路:
1,定义老师和电脑类Teacher Computer
2,电脑可能会出现异常:蓝屏,冒烟
3,所以自定义蓝屏和冒烟异常
4,当电脑出现蓝屏异常,重启就行了
5,当电脑出现冒烟异常,讲课将被迫终止,出现新的异常:无法完成课时计划
6,对无法完成课时计划异常进行处理:放假
*/
//电脑蓝屏异常
class LanPingException extends Exception
{
	LanPingException(String msg)
	{
		super(msg);
	}
}
//电脑冒烟异常
class MaoYanException extends Exception
{
	MaoYanException(String msg)
	{
		super(msg);
	}
}
//无法完成课时计划异常
class NoPlanException extends Exception
{
	NoPlanException(String msg)
	{
		super(msg);
	}
}
//老师类
class Teacher
{
	private String name;
	private Computer computer;
	Teacher(String name,Computer computer)
	{
		this.name = name;
		this.computer = computer;
	}
	public void prelect()throws NoPlanException
	{
		try{
			computer.run();
		}catch(LanPingException e){
			System.out.println(e.getMessage());
			computer.reset();
		}catch(MaoYanException e){
			throw new NoPlanException(e.getMessage()+"无法继续课程");
		}
		System.out.println("开始讲课");
	}
}
//电脑类
class Computer
{
	private int state = 2;
	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("重启电脑");
		try{run();}catch(Exception e){}
	}
}
//测试类
class ExceptionTest
{
	public static void main(String[] args)
	{
		Teacher t = new Teacher("毕老师",new Computer());
		try{
			t.prelect();
		}catch(NoPlanException e){
			System.out.println(e.getMessage());
			System.out.println("放假");
		}
	}
}

 

十四、异常的转换思想

 

    当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出。如上述例子中讲冒烟异常转换成无法完成课时异常

 

十五、异常在子父类函数覆盖中的体现

 

    1. 子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类,(也可以不抛,自己处理了) 
    2. 如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集 
    3. 如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常
    4. 如果子类方法发生了异常,就必须要进行try处理,绝对不能抛

十六、示例

/*
需求:求图形的面积
分析:
1,求面积不能出现负数
2,因为出现数据异常就灭有必要再继续下面的操作,
所以直接抛出RuntimeException终止程序,让调用者判断数据
*/

//抽象类定义图形的基本功能
abstract class Shape
{
	abstract double getArea();
}
//长方形
class Chang extends Shape
{
	private double len,wid;
	Chang(double len,double wid)
	{
		if(len <=0 || wid <= 0)
			throw new ErrorValueException("数据错误");
		this.len = len;
		this.wid = wid;
	}
	public double getArea()
	{
		return len * wid;
	}
}
//自定义异常,处理负数异常
class ErrorValueException extends RuntimeException
{
	ErrorValueException(String msg)
	{
		super(msg);
	}
}
//测试
class ExceptionTest
{
	public static void main(String[] args)
	{
		Chang chang = new Chang(5,-9);
		double area = chang.getArea();
		System.out.println("面积是:"+area);
	}
} 

。使用异常处理机制,将正常流程代码和问题代码分离
。在功能内不用if...else..等来判断处理,直接抛出异常
。让调用者自己判断处理数据
。可以提高代码的阅读性
。以后处理'问题'就要这样,用异常来封装

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值