黑马程序员04_异常
异常
知识点一:异常概述
-
1、定义
异常就是不正常,是指程序在运行时出现的不正常情况。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。
出现的问题有很多种,比如角标越界,空指针等都是。就对这些问题进行分类。而且这些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位置,所以可以不断的向上抽取。形成了异常体系。
-
2、异常体系
Throwable
|--Error:(严重)通常指JVM出现重大问题,如:运行的类不存在或者内存溢出等。不 需要编写针对代码对其处理,程序无法处理。
|--Exception:(非严重)在运行时运行出现的一些情况,可以通过try,catch,finally处理。
|--Checked异常:在程序中必须使用try...catch处理;
|--Runtime异常:可以不使用try...catch处理,但一旦出现异常就将由JVM处理。
-
3、异常的处理格式
java 提供了特有的语句进行处理。
try
{
需要被检测的代码(可能出现异常);
}
catch(异常类 变量)
{
处理异常的代码;(处理方式)
}
finally
{
一定会执行的语句(多用于关闭资源);
}
-
4、对捕获到的异常对象进行常见方法操作
String getMessage():获取异常信息,如:
com.itheima.FuShuException:
String toString():包括异常名称,异常信息,如:
com.itheima.FuShuException: 除数是负数啦!!!!!
e.printStackTrace() 包括异常名称,异常信息,异常出现的位置。如:
com.itheima.FuShuException: 除数是负数啦!!!!!
at com.itheima.Demo.div(Test1.java:20)
at com.itheima.Test1.main(Test1.java:32)
知识点二:一个方法没有throws Excetption,这时该方法既是有问题调用者不处理,编译也能通过
如:
class Demo { int div(int a,int b)//该方法没有throws Excetption,这时调用者就不必处理,编译也能通过。 { return a/b; } } class ExceptionDemo { public static void main(String[] args) { Demo d = new Demo(); int x = d.div(4,1); System.out.println("x="+x); System.out.println("over"); } }
知识点三:一个方法有throws Excetption,也就是说该方法在声明自己有可能会产生异常,这时调用者就必须处理,编译才能通过
-
处理的方法有两种:1、捕捉2、继续向上抛
如:
class Demo { int div(int a,int b) throws Exception//该方法有throws Excetption,也就是说该方法在声明自己有可能会产生异常,这时调用者就必须处理,编译才能通过。 { return a/b; } } class ExceptionDemo { public static void main(String[] args) throws Exception//处理方法:2、继续向上抛 { Demo d = new Demo(); try//处理方法:1、捕捉 { int x = d.div(4,1); System.out.println("x="+x); }catch(Exception e) { e.printStackTrace(); } System.out.println("over"); } }
知识点四:当声明异常时,最好声明更为具体的异常。这样处理的可以更具体。而且对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面(通俗理解:大哥能处理的就不需要小弟了)。
例如:
class Demo { intdiv(inta,intb)throws ArithmeticException,ArrayIndexOutOfBoundsException { int[] arr = new int[a]; System.out.println(arr[4]); return a/b; } } class Test1 { public static void main(String[] args) //throws Exception { Demo d = new Demo(); try { int x = d.div(3,0); System.out.println("x="+x); } catch (ArithmeticException e) { System.out.println(e.toString()); System.out.println("被零除了!!"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.toString()); System.out.println("角标越界啦!!"); } catch(Exception e)//当此异常位于第一个时编译出错 { System.out.println("hahah:"+e.toString()); } System.out.println("over"); } }
知识点五:自定义异常。
因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想。将特有的问题。进行自定义的异常封装。
例如:需求:对于除数是负数,也视为是错误的是无法进行运算的。那么就需要对这个问题进行自定义的描述。
-
自定义异常的形式:
自定义异常形式1:简单的输出错误信息
public class ExceptionDemo { public int a; public int b; public int method(int a,int b) { if(b<0) throw new Exception("除数小于0"); return a/b; } } 此时编译不通过,当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。、在内部try catch处理。、在函数上声明让调用者处理。 、在内部try catch处理: public class ExceptionDemo { public int a; public int b; public static void main(String[] args) { new ExceptionDemo().method(1,-1); } public int method(int a,int b) { if(b<0) try { throw new Exception("除数小于0"); } catch (Exception e) { e.printStackTrace(); } return a/b; } } 运行结果:java.lang.Exception: 除数小于0 at ExceptionDemo.method(ExceptionDemo.java:16) at ExceptionDemo.main(ExceptionDemo.java:10)
自定义异常形式2:通过继承Exception创建异常类
其中打印异常信息等通过复习Exception中的getMessage(),toString(),printStackTrace()等方法获得。
如:
try { x = d.div(10,-1); System.out.println(x); } catch (FuShuException e) { System.out.println(e.toString()); System.out.println(e.getMessage()); e.printStackTrace(); } class FuShuException extends Exception { private String msg; //因为父类中已经把异常信息的操作都完成了。所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。 class FuShuException extends Exception { FuShuException(String msg) { super(msg); } } public class ExceptionDemo { public int a; public int b; public static void main(String[] args) { new ExceptionDemo().div(1,-1); } public int div(int a,int b) { if(b<0) try { throw new FuShuException("除数小于0"); } catch (FuShuException e) { e.printStackTrace(); } return a/b; } }
知识点五:编译异常和运行时异常
1、编译时被检测的异常。在程序中必须使用try...catch处理;
2、编译时不被检测的异常(运行时异常。RuntimeException以及其子类),可以不使用try...catch处理,但一旦出现异常就将由JVM处理。
函数内部抛异常,要么在函数上抛异常,要么在内部try。但是如果在函数内容抛出特殊的子类异常RuntimeException 运行时异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过。之所以不用在函数声明,是因为不需要让调用者处理。当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正。自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException。
class Demo { int div(int a,int b) { if(b==0) throw new Exception("被零除啦");//编译不通过 return a/b; } } class ExceptionDemo4 { public static void main(String[] args) { Demo d = new Demo(); int x = d.div(4,-9); System.out.println("x="+x); System.out.println("over"); } } 但是: class Demo { int div(int a,int b) { if(b==0) throw new ArithmeticException("被零除啦");//编译通过 return a/b; } } 而且如果在函数上声明了RuntimeException 运行时异常。调用者可以不用进行处理。编译一样通过。