一、异常
1、概念
异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。
其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:两种:一种是严重的问题,一种非严重的问题。
对于严重的,java通过Error类进行描述。对于Error一般不编写针对性的代码对其进行处理。
对与非严重的,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。
异常的分类:1:编译时异常该异常在编译时期,如果没有处理,编译失败。该异常被标识,代表可以被处理
2:运行时异常
在编译时不需要处理,编译器不检查。该异常的发生,建议不处理,让程序停止,需要对代码进行修正
2、异常的处理2.1 throws:2.2使用throw抛出异常:在函数上声明异常。便于提高安全性,让调用处进行处理。不处理编译失败。一旦使用throws声明抛出异常,程序无需使用使用throws处理异常不是真正处理异常而是推卸责任。谁调用的就会抛给谁。格式:[修饰符] [返回值类型] [方法名] throws XXException, XXXException...{}
class Demo{int div( int a, int b) throws Exception //在功能上通过throws的关键字声明了该功能有可能会出现问题(Exception异常)。{return a/b;}}
如果程序中的数据、执行与既定的业务需求不符而产生的异常,必须由程序员来决定抛出,系统无法抛出这种异常。则应该使用throw语句,throw语句可以单独使用,它抛出的不是异常类,而是异常类的实例,而且每次只能抛一个异常实例。格式如下:
throw new 异常类("描述信息");
代码示例:
/*
需求:求两个数的和,当一个数小于等于0的时候,抛出异常
*/
public class Deom{
public static void main(String[] args)
{
int sum = sum(-2, 3);
System.out.println(sum);
}
public static int sum(int a, int b)
{
if(a <= 0 || b <= 0)
throw new RuntimeException("出现负数");
return a + b;
}
}2.3java 提供了特有的语句进行处理。
try{需要被检测的代码;}catch(异常类 变量){处理异常的代码;(处理方式)//当try中出现异常,catch捕捉到,此部分代码才会执行。}finally{一定会执行的语句;}
可以细分成3中格式:
第一个格式:
try{}catch (){}
第二个格式:
try{}catch (){}finally{
}
第三个格式:
try{}finally{}
catch对多异常的处理。
1,声明异常时,建议声明更为具体的异常。这样处理的可以更具体。2,对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。 如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。
try
{
throw new AException();
}
catch (AException e)
{
throw e;
}
如果该异常处理不了,但并不属于该功能出现的异常。
可以将异常转换后,在抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,
当调用者知道。并处理。也可以将捕获异常处理后,转换新的异常。
try
{
throw new AException();
}
catch (AException e)
{
// 对AException处理。
throw new BException();
}
finally中放什么样的代码?
通常我们会用来释放资源。
如果在方法返回之前,可以断开,那么就应该把断开的语句放到finally中,这样可以保证断开的语句总是执行。
finally中不会执行的情况
finally遇见了System.exit(0)时,就不会再执行了。因为System.exit(0)会把JVM停止了。
try{System.exit(0)}
finally{//不会执行}
异常的好处:1,将问题进行封装。2,将正常流程代码和问题处理代码相分离,方便于阅读。
异常处理机制:
Java的异常处理机制可以让程序具有极好的容错性,让程序更加健壮。当程序运行出现意外情况时,系统会自动生成一个Exception对象来通知程序,从而实现将"业务功能实现代码"和"错误处理代码"分离,提供更好的可读性。
3,对捕获到的异常对象进行常见方法操作。getMessage():获取异常信息。toString();获取异常类名和异常信息,返回字符串。printStackTrace();获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。printStackTrace(PrintStream s): 通常用该方法将异常内容保存在日志文件中,以便查阅
class Demo{int div( int a, int b) throws Exception //在功能上通过throws的关键字声明了该功能有可能会出现问题。{return a/b;}}
public class ExceptionDemo{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.getMessage()); // / by zero;System. out .println(e.toString()); // 异常名称 : 异常信息。
e.printStackTrace(); //异常名称,异常信息,异常出现的位置。//其实jvm默认的异常处理机制,就是在调用printStackTrace方法。//打印异常的堆栈的跟踪信息。/*java.lang.ArithmeticException: / by zeroat Demo1. div(ExceptionDemo.java:5)at ExceptionDemo.main(ExceptionDemo.java:17)*/
}
System. out .println( "over" );
}}
4,自定义异常因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想。将特有的问题,进行自定义的异常封装。
自定义异常通常继承于Exception 或RuntimeException1.编译时异常,直接继承Exception
2.运行时异常,直接继承RuntimeException继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。
只有这个体系中的类和对象才可以被throws和throw操作。
通过构造函数定义异常信息。
public class IllegalNameException extends Exception{ //编译时异常//public class IllegalNameException extends RuntimeException{ //运行时异常//定义异常一般提供两个构造方法public IllegalNameException(){}public IllegalNameException(String msg){super (msg);}}
//顾客相关的业务public class CustomerService{//对外提供一个注册的方法public void register(String name) throws IllegalNameException{//完成注册if (name.length()<6){//异常//创建异常对象//IllegalNameException e = new IllegalNameException("用户名长度不能少6位");//手动抛出异常//throw e;throw new IllegalNameException ( "用户名长度不能少6位" );}//如果代码能执行到此处,证明用户名是合法的.System. out .println( "注册成功!" );}public static void main(String[] args){//假如用户提供的用户名如下String username = "fdafdafdsa" ;//注册CustomerService cs = new CustomerService();try {cs. register(username);} catch (IllegalNameException e){System. out .println(e.getMessage());}}}
5,throws和throw的区别throws使用在函数上,后面跟的异常类。可以跟多个。用逗号隔开。用于标识函数暴露出的异常
throw使用在函数内,后跟的是异常对象。用于抛出异常对象
6,异常细节
RuntimeException 以及其子类如果在函数中被 throw 抛出,可以不用在函数上声明。一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子 类。7,常见异常信息如果父类抛出多个异常,那么重写(覆盖)方法必须抛出那些异常 的一个子集,不能抛出新的异常。如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,如果子类方法发生了异常,就必须要进行try处理,绝对不能抛class AException extends Exception
{
}
class BException extends AException
{
}
class CException extends Exception
{
}
class Fu
{
void show()throws AException
{
}
}
class Test
{
void function(Fu f)
{
try
{
f.show();
}
catch (AException e)
{
}
}
}
class Zi extends Fu
{
/*void show()throws CException只能抛AException或者AException的子类异常BException
不能抛CException
*/
{
}
}
class
{
public static void main(String[] args)
{
Test t = new Test();
t.function(new Zi());
}
}
ArithmeticException(算术异常)
OutOfMemoryError(内存溢出错误)
IndexOutOfBoundsException索引出界
IllegalStateException非法状态IllegalArgumentException非法参数NullPointerException空指针