---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
一.概述
先直观感受一下
定义 int a = 4/0;
异常:就是程序在运行时出现的不正常情况
异常的由来:问题也是现实生活中的一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:两种,一种是严重的问题,一种是非严重的问题
对于严重的问题,java通过Error类进行描述
对于Error一般不编写针对性的代码对其进行处理
对于非严重的,java通过Exception类进行描述
对于Exception可以使用针对性的处理方式进行处理
除零异常
数组角标越界异常
空指针异常
对于Error,直观感受一下,
我们根本没有aa类,直接运行
再看一个Error
内存溢出
每个程序运行的时候,虚拟机会默认的分配一片内存空间,超出了大小,就会出错
(可以手动的加参数改变虚拟机分配的内存空间)
无论Error还是Exception都具有一些共性的内容
比如:不正常情况信息,引发原因等
Throwable
|---Error
|---Exception
二.try和catch
出现了异常,JVM认识这个异常的话,就会处理,异常处理机制
只要出现问题,程序就停止了
我们要对其进行处理,让程序继续执行
java提供了特有的语句进行处理
try
{需要被检测的代码;}
catch(异常类 变量)
{处理异常的代码;(处理方式)}
finally
{一定会执行的语句;}
例子
class Demo
{
int div (int a,int b)
{
return a/b;
}
}
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)
{
System.out.println("/by zero");
}
System.out.println("over");
}
}
*对捕获的异常操作的常见方法
String getMessage(); 返回异常信息
String toString(); 返回异常信息、异常名字,在输出语句中直接输出异常对象,会自动调用这个方法
void printStackTrace(); 输出异常名称、异常信息、异常出现的位置。其实JVM默认的异常处理机制,就是在调用printStackTrace()方法,打印异常的堆栈的跟踪信息。
添加
System.out.println(e.getMessage());
System.out.println(e.toString());
System.out.println(e);
e.printStackTrace();
三.异常声明 throws
功能是我们写的,别人用的时候一定会try处理吗,不一定,因为他们都不知道这个功能会不会抛出异常,所以我们在写功能的时候要进行声明
int div(int a,int b)throws Exception
{
returna/b;
}
我们声明了有可能发生异常,别人在使用这个功能的时候不处理,就会编译失败。
处理方式有两种:要么捕捉try{}catch(){},要么抛出去,在使用功能的函数上throws Exception。
在使用抛出异常的功能的时候,我们一般不要往外抛,要“负责任”。
四.多异常处理
try{}
catch(){}
catch(){}
我们在定义功能的时候,有可能发生不止一种异常,我们会抛出不止一种异常。
声明异常的时候,建议声明更为具体的异常,这样别人处理就会更有针对性。
int div(int a,int b)throws ArithmeticException,ArrayIndexOutofBoundsException
{
int arr = new arr[a];
System.out.println(arr[4]);
return a/b;
}
别人用功能的时候,就会有对应的几个catch
直接用catch(Exception e)可以吗,可以,多态性的原因,但是没有针对性
别人在用功能的时候感觉这个功能有可能抛出没有声明过的异常,在最后再加一个catch(Exception e)可以吗,可以,但是不好,如果真的发生了声明过的异常之外的异常,直接用Exception接了的话,相当于隐藏了问题,如果真的发生了这种情况,应该让程序停掉,找问题,处理掉。
对多异常处理的原则
1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体
2.对方声明几个异常,就对应有几个catch块,不要定义多余的catch块
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
建议在进行catch处理时,catch中一定要定义具体处理方式,不要简单的定义语句
e.printStackTrace或者简单的输出语句
将问题的信息用一个异常日志文件记录下来
class Demo
{
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
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 (ArithmeticException e)
{
System.out.println("算数异常");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("数组越界异常");
}
catch (Exception e)
{
System.out.println ("其他异常");
}
System.out.println("over");
}
}
五.自定义异常
java只是将常见的异常进行了封装,我们在写一个软件的时候,可能会出现本项目之中的特有的异常,这时就需要自定义异常。
自定义异常
需求:在本程序中,对于除数是负数,也视为错误是无法进行计算的
那么就需要对这个问题进行自定义描述
在编译的时候,先报告的是基本的语法异常,如果出现异常的错误,那么就已经处理到最后了。
当函数内出现了throw抛出异常对象,那么就必须要给出对应的处理动作。
要么在函数内部try catch处理
要么在函数上声明让调用者处理
一般情况下,函数内throw了异常,在函数上声明(RuntimeException是特例)
如果自定义的信息不定义内容,只是继承了Exception,处理的时候用e.toString(),结果只有异常的名称,却没有异常的信息,因为自定义的异常并未定义信息,处理方式,可以复写父类中的getMessage(),也可以调用父类的构造函数Exception(String message)
因为父类已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息传递给父类通过super语句。
那么就可以直接通过getMessage方法获取自定义的异常信息了。
为什么要继承Exception,原因:
异常体系有一个特点,因为异常类和异常对象都需要被抛出,他们都具备可抛性,这个可抛性是Throwable这个体系中的独有特点,只有这个体系中的类和对象才可以被throw和throws抛出
class FuShuException extends Exception
{
private int value;
FuShuException(String msg,int value)
{
super(msg);
this.value = value;
}
public int getValue()
{
return value;
}
}
class Demo
{
int div(int a,int b)throws FuShuException
{
if (b<0)
{
throw new FuShuException("负数异常",b);//手动通过throw关键字抛出异常对象
}
return a/b;
}
}
class ExceptionDemo
{
public static void main (String [] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
System.out.println("错误的负数是:"+e.getValue());
}
System.out.println("over");
}
}
throw和throws的区别
throws使用在函数上,后面跟的是异常类,可以跟多个,用逗号分开
throw使用在函数内,后面跟的是异常对象
六.RuntimeException异常
一般,函数内抛,函数上要声明,但是RuntimeException以及他的子类很特殊,函数内抛,函数上可以不用声明。
Exception中有一个特殊的子类异常RuntimeException运行时异常
如果在函数内抛出异常,函数上可以不用声明,编译一样通过
如果函数上声明了该异常,调用者可以不用进行处理,编译一样通过
之所以不用再函数上声明,是因为不需要让调用者处理,当该异常发生时,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序,修改程序。
RuntimeException的子类
自定义异常的时候,如果该异常发生,无法继续进行运算,就让自定义异常继承RuntimeException。
所以,自定义异常的时候,要不继承Exception,要么继承RuntimeException。
对于异常,分两种:
1.编译时被检测的异常
2.编译时不被检测的异常,运行时异常,就是RuntimeException及其子类
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------