什么是异常?
举个例子:
class Demo{
public int div(int a,int b)
{
return a/b;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d=new Demo();
System.out.println(d.div(4, 0));//会出现异常,因为除数不可以是0
System.out.println("hello world!");
}
}
运行报错
java.lang.ArithmeticException: / by zero
异常就是程序在运行时出现不正常情况。
问题是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是Java对不正常情况进行描述后的对象体现。
对于问题的划分:
(1)严重的问题 ——error;对于Error一般不编写针对性的代码对其进行处理
(2)非严重的问——exception;
无论是error还是exception,都具有一些共性,因此我们可以将它们继续向上抽取,形成–Throwable
异常的处理
JAVA提供了特有的语句进行处理
try{
需要被检测的代码;
}
catch(异常类 变量)
{
处理异常的代码:(处理方式)
}
finally{
一定会执行的语句;
}
class Demo{
public int div(int a,int b)
{
return a/b;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d=new Demo();
try {
System.out.println(d.div(4, 0));
}
catch(Exception e)
{
System.out.println("by zero");
}
System.out.println("hello world!");
}
}
处理异常的流程:
注意:如果try里没有检测到异常,那么catch是不会运行的。
对捕获到的异常对象进行常见方法操作:
getMessage();
toString();//异常名称+异常信息
printStackTrace();//jvm 默认的异常处理机制。
异常声明:
在功能上通过throws的关键字声明了该功能有可能会出现问题
如果我们调用该功能,我们应该对这个异常进行处理
(1)抛出
class Demo{
public int div(int a,int b)throws Exception
{
return a/b; //new ArithmeticException
}
}
public class ExceptionDemo {
//对异常进行抛出
public static void main(String[] args) throws Exception{
Demo d=new Demo();
System.out.println(d.div(4, 0));
System.out.println("hello world!");
}
}
(2)捕捉
class Demo{
public int div(int a,int b)throws Exception
{
return a/b;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d=new Demo();
//对异常进行捕捉
try {
System.out.println(d.div(4, 0));
}
catch(Exception e)
{
System.out.println("by zero");
}
System.out.println("hello world!");
}
}
对多异常的处理:
1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体。一个功能多异常时,只要发生了一个异常则功能结束,不再运行,因此不会同时处理两个多异常。
2.功能声明几个异常,则应该有多少catch块,注意,父类Exception应该作为最下面的catch
3.catch处理时,要写出具体的处理方式,而不是只用一些语句。下列代码是为了方便叙述。
class Demo{
//声明更为具体的异常
public int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException
{
int[] arr=new int[3];
System.out.println(arr[3]);//数组角标越界异常
return a/b;//由于上面已经异常,所以这里不会再运行
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d=new Demo();
try {
System.out.println(d.div(4, 0));
}
catch(ArithmeticException e)
{
System.out.println("by zero");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
}
System.out.println("hello world!");
}
}
自定义异常:
因为项目中会出现一些特有的,未被Java所描述并封装对象的问题,于是我们可以自己对这些问题进行封装,我们自定义类必须继承Exception。因为异常体系里的对象和类具有可抛性,可抛性是throwable这个体系中独有的特点。也就是说只有这个体系里的类和对象才可以被throws和throw操作。
ex:
需求:在本程序中,对于除数是-1,也视为错误的无法进行运算的,那么就对这个问题进行自定义的描述。
当在函数内部出现throw抛出异常对象,那么就必须要给对应的处理动作,要么再内部catch try处理,要么在函数上声明让调用者使用
//要继承exception
class NegativeException extends Exception
{
}
class Demo{
//函数内出现throw异常,我们将问题抛给调用者处理
public int div(int a,int b)throws NegativeException
{
if(b<0)
throw new NegativeException();//只能通过手动抛出自定义异常对象
return a/b;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d=new Demo();
try {
System.out.println(d.div(4, -1));
}
catch (NegativeException e) {
System.out.println(e.toString());
System.out.println("Negative");
}
System.out.println("hello world!");
}
}
但是打印的结果中只有异常的名称,却没有异常的信息,因为我们自定义的异常中并没有定义信息
如何自定义异常信息
throwable 类里有个构造函数,
Throwable(String message)
构造一个具有指定的详细消息的新的throwable。
因此我们子类只需要在构造的时候将异常信息通过super语句传递给父类,那么就可以直接通过getMessage方法获取自定义的异常信息了
class NegativeException extends Exception
{
public NegativeException(String message) {
super(message);
}
}
throws和throw的区别
- throws使用在函数上,throw使用在函数内。
- throws后面跟一个或多个异常类,而throw后面跟的是一个对象。
RuntimeException
如果在函数内抛出该异常,函数上可以不用声明(不需要让调用者处理,当该异常发生时,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正),编译一样通过;如果函数上声明了该异常,调用者可以不用进行处理了,编译一样通过。
因此当我们自定义异常时,如果该异常的产生,无法在继续进行运算 ,就让自定义异常为runtime异常。
异常分为两种:
编译时被检测,
编译时不被检测的异常(运行时异常,RuntimeException以及其子类)