黑马程序员--异常处理

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1异常

1.1异常的体系

         Throwable

                   Error

                            通常出现重大问题:如运行的类不存在或者内存溢出等

                            不编写针对代码对其处理

         Exception

                   在运行时运行出现的一些情况,可以通过try,catch,finally

Exception和error的子类名都已父类名作为后缀


例:被除数为零

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

1.2异常的由来

问题也是实现生活中的一个具体的事物,也可以通过java的类的形式进行描述.并封装成对象,其实就是java对不正常情况进行描述后的对象体现

1.3对于问题的划分

两种:

一种是严重的问题,

一种是非严重的问题

 

1.对于严重的,java通过Error类进行描述(例:疾病中不可治愈的),对于Error一般不编写针对性的代码对其进行处理

2.对于非严重的,java通过Exception类进行描述(例:疾病中可治愈的),对于Exception可以使用针对性的处理方式进行处理

 

无论Error或者Exception都具有一些共性内容

比如:不正常情况的信息,引发原因等

1.4异常处理

Java提供了特有的语句进行处理

try{

         需要被检测的代码

}catch(异常类 变量){

         处理异常的代码(处理方式)

}finally{

         一定会执行的语句

}

1.5对捕获到的异常对象进行常见方法操作

getMessage

public String getMessage()  //获取异常的信息

toString

public String toString()  //异常名称:异常信息

printStackTrace

public void printStackTrace()打印异常的堆栈的跟踪信息;异常名称,异常信息,异常出现的位置(其实jvm默认的异常处理机制,就是在调用printStackTrace方法.)

1.6异常声明

在一个方法后面进行throws抛出

1.7多异常处理

1.      声明异常时,建议声明更为具体的异常,这样处理可以更具体(声明的具体,处理就会具体)

2.      出现程序以外的异常,程序应该停掉,而不是通过Exception(最大的异常处理掉),而且如果catch获取异常为Exception为第一个,其他的异常就都失效了,而且放在Exception下面会报错

3.      对方声明几个异常,就对应有几个catch块,不要定义多余的catch块

 如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面

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

1.8自定义异常

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

 

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

 

自定义异常继承Exception,因为是自定义的,jvm不认识,所以不能自动抛出,只能手动抛出

 

当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作.

要么在内部try catch处理.

要么在函数上声明,让调用者处理

一般情况下,函数内出现异常,函数上需要声明.

class FuShuExcption extends Exception
{
}
class Demo
{
	int div(int a,int b)throws FuShuExcption//当方法内部出现了非RuntimeException的异常,都需要在方法后面进行生命,让调用者处理
	{
		if(b<0)
			throw new FuShuExcption();
		return a/b;
	}
}

class ExceptionDemo2 
{
	public static void main(String[] args) 
	{
		Demo d=new Demo();
		try{
			d.div(4,1);
		}catch(FuShuExcption e){
			System.out.println("hello");
		}
	}
}

发现打印的结果中只有异常的名称,却没有异常的信息

 hello.FuException
at hello.ZiException.chu(Test.java:22)
at hello.Test.main(Test.java:8)

因为自定义的异常并未定义信息

如何定义异常信息呢??

         因为父类中已经把异常信息的操作都完成了

         所以子类只要在构造时,将异常信息传递给父类通过super语句

         那么就可以直接通过getMessage方法获取自定义的异常

 

自定义异常:

1.      必须是自定义类继承Exception

继承Exception原因:

异常体系有一个特点:因为异常类和异常对象都被抛出.它们都具备可抛性,这个可抛性是trowable这个体系中独有特点.

只有这个体系中的类和对象才可以被throws和throw操作


1.9throws和throw的区别

1.      throws使用在函数上,throw使用在函数内

2.      throws后面跟的异常类,可以跟多个,用逗号隔开;throw后面跟的是异常对象

函数内抛要在函数上声明


如果不想使用异常自带的报错信息,可以自己写一个

class Demo
{
	int div(int a,int b)
	{
		if(b==0)
			throw new ArithmeticException("除数为零了...");//jdk提供的Exception有一个构造方法可以传递自定义的报错信息
		return a/b;
	}
}
class ExceptionDemo2 
{
	public static void main(String[] args) 
	{
		Demo d=new Demo();
		int x=d.div(4,0);
		System.out.println(x);
	}
}


1.10 RuntimeException

Exception中有一个特殊的子类异常:RuntimeException  即运行时异常

         如果在函数内容抛出该异常或其子类,函数上可以不用声明,编译可以通过

class Demo
{
	int div(int a,int b)//这里不需要声明
	{
		if(b==0)
			throw new ArithmeticException("除数为零了...");//jdk提供的Exception有一个构造方法可以传递自定义的报错信息
		return a/b;
	}
}

class ExceptionDemo2 
{
	public static void main(String[] args) 
	{
		Demo d=new Demo();
		int x=d.div(4,0);
		System.out.println(x);
		
	}
}


如果在函数上声明了该异常或其子类,调用者可以不用进行处理,编译一样通过

class Demo
{
	int div(int a,int b)throws ArithmeticException//此处声明调用者可以不用对异常进行处理
	{
		return a/b;
	}
}

class ExceptionDemo2 
{
	public static void main(String[] args) 
	{
		Demo d=new Demo();
		int x=d.div(4,0);//调用方法不需要对异常进行处理
		System.out.println(x);
		
	}
}

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

 

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

 

对于异常,分为两种:

1.      编译时被检测的异常

Javac在编译时,会检测方法,如果这个方法抛出了非RuntimeException异常或者其子类,如果函数上没有标明异常,就会认为这是有安全隐患的.而且调用者也要对异常进行处理(要么抛,要么try)

2.      编译时不被检测时的异常(运行时异常.RuntimeException及其子类)

 

1.11异常练习

毕老师用电脑上课.(名词提炼法)

         异常:

1.      电脑蓝屏了

2.      电脑冒烟了

要对问题进行描述,封装成对象.

1.      蓝屏时,可以处理,所以要表示出去

 

可是当冒烟发生后,出现讲课进度无法继续

出现了讲师的问题:课时计划无法完成

 

在找领导解决事情的时候,可以让学员做练习

class ExceptionTest
{
	public static void main(String[] args){
		Teacher t=new Teacher("李老师",new Computer());
		try
		{
			t.jiangKe();
		}
		catch (NoPlanException e)
		{
			System.out.println(e.toString());
			System.out.println("换老师,换电脑");
		}
	}
}
class Teacher
{
	private String name;
	private Computer pc;
	public Teacher(String name){
		this.name=name;
	}
	public Teacher(String name,Computer pc){
		this(name);
		this.pc=pc;
	}
	public void jiangKe()throws NoPlanException{
		try{
			pc.run();
			System.out.println("讲课");
		}catch(LanPingException e){
			pc.reset();
		}
		catch(MaoYanException e){
			test();//抛出异常,程序结束,此句话执行不到
			throw new NoPlanException("课时无法继续"+e.getMessage());//不能讲课有一个理由,即报的异常
		}
	}
	public void test(){
		System.out.println("练习");
	}
}
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("电脑重启了...");
	}
}

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


1.12 finally关键字:

finally中存放的是一定会被执行的代码

应用:关闭资源

当catch中有return时,程序将跳出,这时,将不会执行try  catch外的其他代码,但会执行finally中的代码

class FinallyDemo
{
	public static void main(String[] args){
		int x=0;
		DoChu d=new DoChu();
		try
		{
			x=d.chu(4,-5);
			System.out.println("x="+x);
		}
		catch (SuanFaException e)
		{
			e.toString();
			return ;
		}finally{
			System.out.println("finally");
		}
		System.out.println("over");
		
		
	}
}
class SuanFaException extends Exception
{
	SuanFaException(String msg){
		super(msg);
	}
}
class DoChu
{
	public int chu(int a,int b)throws SuanFaException{
		if(b<0)
			throw new SuanFaException("除数不能为负");
		return a/b;
	}
}

1.13处理语句其他格式:

try---catch()

try{                           //这样编译是可以通过的,因为异常在内部被解决了
    throw new Exception();
}catch(Exception e){
    
}

try{                         
    throw new Exception();
}catch(Exception e){
    throw e;         //这样是不能编译通过的,因为处理了一个异常,又抛出了新的异常
}

try{                         
    throw new Exception();
}catch(Exception e){
try{
    throw e;        //这样就可以编译通过,因为程序又在内部解决了异常
}catch(){

}
}

try---catch()---finally

try---finally

用法:可能会产生一些问题,但是这些问题不会再这个方法中处理.但是最后要关闭资源

try{
    throw new Exception();
}finally{
                               //这样编译不能通过,因为程序没有处理异常
}

一个try多个catch

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

1.14重写时的异常特点:

异常在子父类重写中的体现:

1.      子类覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或该异常的子类(你只能是父类的相同问题,或是比父类更小的问题  ),如果子类重写的方法真的要抛出不是父类的异常,就得使用try---catch

早期的程序不能处理后期的新程序,

2.      如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集

3.      如果父类或者方法的接口中没有异常抛出,那么子类在覆盖方法时也不可以抛出异常;如果子类方法发生了异常.就必须要进行try处理.绝对不能抛

异常练习:异常的产生能让正常流程和问题处理代码相分离

有个圆形和长方形

都可以获取面积

对于面积如果出现非法的数值,视为是获取面积时出现的问题.

问题通过异常来表示.

先要对这个程序进行基本的设计

 

当值出现非法时,应该把程序直接停掉,因为下面的内容再执行是没有意义的

 

分析:

         遇到问题,把对象封装起来,万物皆对象

         抛异常可以抛更大的,但是不便于查看是哪的问题
class AreaTest
{
	public static void main(String[] args){
		Chang c=new Chang(-12.1,12.3);
		c.getArea();
	}
}

interface DoArea 
{
	void getArea();
}

class Chang implements DoArea 
{
	private double wid;
	private double hei;
	Chang(double wid,double hei)// throws FuShuException
		{
		if(wid<0 || hei<0)
			throw new FuShuException("长方形的长和宽都不能为负数");
		this.wid=wid;
		this.hei=hei;
	}
	public void getArea(){
		System.out.println( wid*hei);
	}
}

class Yuan implements DoArea
{
	private static final double PI=3.14;
	private double r;
	Yuan(double r){
		this.r=r;
	}
	public void getArea(){
		
		System.out.println(PI*r*r);
	}
}
class FuShuException extends RuntimeException
{
	FuShuException(String msg){
		super(msg);
	}
}

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

你可能感兴趣的:(黑马程序员)