黑马程序员:异常类的介绍及应用

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

异常:程序在运行时出现不正常情况

异常是java对不正常情况进行描述后的对象体现


两种问题:严重的、非严重的
严重的:java通过Error类进行描述,一般不编写针对性的代码对其进行处理
非严重的:java通过Exception类进行描述,可以用针对性的处理方式进行处理

Throwable
	|--Error
	|--Exception

异常的处理:由下面三部分完成
java提供了特有的语句进行处理
try
{
	需要被检测的代码;
}
catch(异常类 变量)
{
	处理异常的代码;(处理方式;)
}
finally
{
	一定会执行的语句;
}

对捕获到的异常对象进行常见变量的操作
String getMessage(); //获取异常信息
String toString(); //异常名称:异常信息
void printStackTrace(); //异常名称,异常信息,异常出现的位置。 JVM默认的异常处理机制就是在调用printStackTrace方法,打印异常的堆栈的跟踪信息


示例:
class Demo
{
	int show(int a,int b)
	{
		return a/b;
	}
}
class ExceptionDemo
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		/*
		int x = d.show(3,0); //分母为0,JVM在运行时会出现ArithmeticException类型错误
		System.out.println(x);
		*/
		//使用异常的处理
		try  //try的作用在于把异常封装成对象,该类中,即 new ArithmeticException()
		{
			int x = d.show(3,0);//因为在这里出现了错误,所以下面的语句不会被继续执行
			System.out.println(x);
		}
		catch(Exception e) //传入异常对象 即 Exception e = new ArithmeticException(); 多态
		{
			System.out.println("分母为零");
			System.out.println(e.getMessage());  // by zero
			System.out.println(e.toString());
			e.printStackTrace();
		}
		
		System.out.println("over");
	}
}

注:
当通过try、catch对异常的处理后,JVM会认为不存在异常从而继续执行后面的语句
若try方法体中不存在错误,则catch方法体不会执行


throws(抛出)关键字
作用:在方法上通过throws关键字声明该方法可能会出现异常
只要被throws关键字处理,必须对其捕捉或者抛出异常
格式:
method() throws Exception


示例:
class Demo
{
	int show(int a, int b) throws Exception //尽量声明的具体一些,比如 throws ArithmeticException
	{
		return a/b;
	}
}
class ExceptionDemo
{
	public static void main(String[] args) //若需要抛出,在这后面加上 throws Exception
	{
		Demo d = new Demo();
		//int x = d.show(4,0);  //要么通过try catch解决,要么在方法上抛出异常
		try
		{
			int x = d.show(4,0);
			System.out.println(x);
		}
		catch(Exception e)
		{
			System.out.println(e.toString());
		}
		System.out.println("over");
	}
}

对多异常的处理
1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体
2.对方声明几个异常,就应该有几个catch块,不要定义多余的catch块。
若多个catch块中的异常出现继承关系,父类异常catch块放在最下面,因为是从上往下执行
建议在进行catch处理时,catch中一定要定义具体的处理方式。
不要简单定义一句 e.printStackTrace();也不要简单的就书写一条输出语句。
通常的做法是把异常信息保存到异常日志文件,以便程序员后期调试
class Demo
{
	int show(int a, int b) throws ArithmeticException,ArrayIndexOutOfBoundsException
	{
	int[] arr = new int[a];
	System.out.println(arr[4]); //当a=4时,出现角标越界异常。arr数组最后一个值是arr[3];
	return a/b;
	}
}
class ExceptionDemo2
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		try
		{
			int x = d.show(4,0);
			System.out.println(x);
		}
		//catch (Exception e){} 这样写程序上没问题,但是处理问题不够针对性,而且Exception是父类
		catch (ArithmeticException e)
		{
			System.out.println(e.toString());
			System.out.println("分母是零");
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println(e.toString());
			System.out.println("出现角标越界错误");
		}
		System.out.println("over");
	}
}

注:catch不能同时执行多个,程序执行到哪里异常,就处理这个异常的catch方法,并继续执行后面的其他代码(不执行下一个catch方法)

自定义异常
因为项目中会出现特有的问题
而这些问题并未被JAVA所描述并封装对象
所以对这些特有的问题可以按照JAVA对问题封装的思想将特有的问题进行自定义异常封装
一般情况下,函数内出现异常,函数上需要声明
若不自定义异常信息,默认返回的是自定义异常名称
注:自定义异常类必须继承Exception
继承Exception原因:
异常体系有一个特点:
因为异常类和异常对象都需要被抛出,他们都具备可抛性,这个性质是Throwable这个体系中独有的特点
只有这个体系中的类和对象才可以被throws和throw操作
注:throw 语句单独存在时候,下面(方法体内)不要再写其他语句,因为已通过throw抛出,执行不到,而且编译时会出现异常


示例:
class FuShuException extends Exception //自定义异常需继承Exception这个异常父类
{
	/*
	private String msg;
	FuShuException(String msg)
	{
		this.msg = msg;
	}
	public String getMessage()
	{
		return msg;
	}
	*/
	//因为Throwable(String message)已经做过以上操作,子类继承的时候只需把msg传入到父类,再从父类返回回来即可
	FuShuException(String msg)
	{
		super(msg); //自定义getMessage信息
	}
	
}
class Demo
{
	int show(int a, int b) throws FuShuException
	{
		if (b<0) { // 
		   throw new FuShuException("getMessage内容:/ by fushu"); //手动通过throw关键字抛出一个自定义异常对象
		}
		return a/b;
	}
}


class ExceptionDemo3
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		/*int x = d.show(3,-1);
		System.out.println(x);
		*/
		try
		{
			int x = d.show(3,-1);
			System.out.println(x);
		}
		catch(FuShuException e)
		{
			System.out.println(e.getMessage());
		}
	}
}

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

Exception中有一个特殊的子类异常RuntimeException
如果在函数内抛出异常,函数上可以不用声明,编译可以通过
如果在函数上声明了该异常,调用者可以不用处理,编译可以通过


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


自定义异常时,若该异常的发生,无法在继续进行运算(调用者无法修复),就让自定义异常继承RuntimeException


对于异常分两种:
1.编译时被检测的异常
2.编译时不被检测的异常,即运行时异常(RuntimeException)

异常的应用
Mr.Bi用pc上课
思考上课中会出现的问题:
1.电脑蓝屏

2.电脑冒烟 -> 老师无法上课而影响课时(无法解决冒烟问题,只能解决其他问题,解决方法如让学生练习或者放假)


class ComputerDownException extends Exception
{
	ComputerDownException(String message)
	{
		super(message);
	}
}
class ComputerSmokeException extends Exception
{
	ComputerSmokeException(String message)
	{
		super(message);
	}
}
class NoPlanException extends Exception //因电脑冒烟导致的新异常
{
	NoPlanException(String message)
	{
		super(message);
	}
}
class Computer
{
	private int state = 1;
	Computer(int state)
	{
		this.state = state;
	}
	public void run() throws ComputerDownException,ComputerSmokeException
	{
		if (state == 2)
			throw new ComputerDownException("电脑蓝屏");
		else if (state == 3)
			throw new ComputerSmokeException("电脑冒烟");
		System.out.println("Computer Running");
	}
	public void reset()
	{
		state = 1;
		System.out.println("Computer Reset");
	}
}


class Teacher
{
	private String name;
	private Computer pc;
	Teacher(String name)
	{
		this.name = name;
		pc = new Computer(3); //写3测试电脑冒烟异常的处理方式,2为电脑蓝屏
	}
	
	public void teach() throws NoPlanException
	{
		/*
		pc.run();
		System.out.println("teaching");
		*/
		try
		{
			pc.run();
			System.out.println("teaching");
		}
		catch(ComputerDownException e)
		{
			System.out.println(e.toString());
			pc.reset();
		}
		catch(ComputerSmokeException e)
		{
			System.out.println(e.toString());
			throw new NoPlanException("电脑冒烟导致拖慢课程进度");  //因为电脑冒烟导致课时无法完成
		}
	}
}
class ExceptionTest
{
	public static void main(String[] args)
	{
		Teacher t = new Teacher("Mr.Bi");
		try
		{
			t.teach();
		}
		catch(NoPlanException e)
		{
			System.out.println("换老师 or 放假");
		}
		
	}
}

finally{}
finally中存放的是一定会被执行的代码,return也不能停止finally中的代码执行,只有System.exit(0);可以
System.exit(0); //JVM退出
finally代码块:定义一定执行的代码,通常用于关闭资源。
示例:
class NoSQLException extends Exception
{


}
public void method() throws NoSQLException
{
	/*
		连接数据库;
		数据操作;//throw new SQLException();
		关闭数据库;//无论数据操作是否出现异常,操作结束都应该关闭数据库连接
	*/
	try
	{
		连接数据库;
		数据操作; // throw new SQLException();
	}
	catch(SQLException e)
	{
		对数据库进行异常处理; //本层问题,内部解决
		throw new NoSQLException();  //影响外层问题,通知外层(把关联性问题提供出去)
	}
	finally
	{
		关闭数据库;
	}
}

异常语句的几种格式:
第一种:
try
{}
catch()
{}
第二种:
try
{}
catch()
{}
finally
{}
第三种:
try
{}
finally
{}


注:catch用于处理异常,如果没有catch就代表异常没有被处理,若异常未处理,就需要在函数上声明




异常在子父类覆盖(重写)中的体现:
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
2.若父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子集
3.若父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,若子类方法发生异常,只能使用try处理,绝对不能抛
示例:
异常关系结构
Exception
	|--AException
		|--BException
	|--CException
	
class AException extends Exception
{


}
class BException extends AException
{


}
class CException extends Exception
{


}
class Fu
{
	void show() throws AException
	{
	
	}
}
class Test
{
	void function(Fu f) //Fu f = new Zi();
	{
		try
		{
			f.show();
		}
		catch(AException a) //若Zi中show方法throws CException,AException不能处理CException导致编译失败
		{
		
		}
		
	}
}
class Zi extends Fu
{
	void show() throws AException //throws BException也可以
	{
		
	}
}
class TestDemo
{
	public static void main(String[] args)
	{
		Test t = new Test();
		t.function(new Fu());
		t.function(new Zi()); //若function方法中catch的异常对象不是父类异常或者父类异常的子类,那么就会导致编译失败
	}
}

异常的应用:
求面积(未知形状)
可能会遇到的异常:基数为负数,遇到后导致程序无法继续运算


class NoValueException extends RuntimeException
{
	NoValueException(String msg)
	{
		super(msg);
	}
}
interface GetArea
{
	public abstract double getArea();
}


class Rectangle implements GetArea
{
	private double a,b;
	/*
	若NoValueException继承的不是RuntimeException,这里需要在函数上声明
	Rectangle(double a, double b) throws NoValueException
	*/
	Rectangle(double a, double b)
	{
		if (a<0 || b<0)
			throw new NoValueException("无法计算面积");
		this.a = a;
		this.b = b;
	}
	public double getArea()
	{
		return a*b;
	}
}
class ExceptionText
{
	public static void main(String[] args)
	{
		Rectangle rec = new Rectangle(3,4);
		System.out.println("长方形的面积:"+rec.getArea());
	}
}

判断输出来说明异常运行的顺序
class Demo
{
	public static void func() throws Exception
	{
		try	
		{
			throw new Exception(); 
		}
		finally
		{
			System.out.print("B");
		}
	}
	public static void main(String[] args)
	{
		try
		{
			func(); //throw new Exception();后执行func()中finally中的代码 1.输出B
			System.out.print("A");  //因为上面一行代码throw,所以这句执行不到
		}
		catch(Exception e)  //接收func()抛出的new Exception()
		{
			System.out.print("C");  // 2.输出C
		}
		System.out.print("D"); //异常处理完成  3.输出D
	}
}
最终输出结果:BCD

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值