美文网首页
java笔记--异常

java笔记--异常

作者: 吃饱喝足搬代码丶 | 来源:发表于2018-04-06 20:46 被阅读0次

    异常:

    异常:是在运行时期发生的不正常现象。

    在java中用类的形式对不正常情况进行了描述和封装对象。

    描述不正常的情况的类,就称为异常类。

    以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离,提高阅读性。

    其实异常就是java通过面向对象的思想将问题封装成了对象。

    用异常类对其进行描述。不同问题用不同的类进行具体的描述,比如角标越界,空指针等等。

    异常体系:

    最终问题(异常情况)就分成了两大类:Throwable(下面两种情况的父类):

    |--1 一般不可处理的。Error
    特点:是由jvm抛出的严重性的问题。
    这种问题发生一般不针对性处理。直接修改程序。
    |-- 2 可以处理的。Exception

    无论error还是异常,都是问题,问题发生就应该可以抛出,让调用者知道并处理
    该体系的特点在于Throwable及其所有的子类都具有可抛性。
    可抛性到底指什么?怎么体现可抛性?
    其实是通过两个关键字来体现--throws throw。凡是可以被这两个关键字所操作的类和对象都具备可抛性。

    该体系的特点:
    子类的后缀名都是用其父类名作为后缀,阅读性很强。

    public class ExceptionDemo {
     
        public static void main(String[] args) {
            int[] arr=new int[1024*1024*800];//java.lang.OutOfMemoryError内存溢出
            sleep(-5);//但是时间没有负数,所以应该抛出异常
        } 
        public static void sleep(int time){
            //之前的处理方法是:if,阅读性差
    /*      if(time<0){
                处理方法
                处理方法
                处理方法
            }
            if(time>1000000){
                处理方法
                处理方法
                处理方法
            }*/
            System.out.print("我睡。。。"+time);
        }
        public static void sleep2(int time){
            //现在的处理方法是:封装成类,调用异常类
    //      if(time<0){
    //          抛出 new FuTime();//就代码时间为负的情况,这个对象中会包含着问题的名称,信息,位置等信息。
    //      }
    //      if(time>1000000){
    //          抛出 new BigTime();
    //      }
            System.out.print("我睡。。。"+time);
        }
    }
    
    class FuTime{
    }
    class BigTime{
    }
    

    异常对象的抛出:

    一般异常都是程序默认抛出异常,即由所调用的类抛出异常给(主函数里的)调用者,调用者抛给jvm,jvm直接显示异常的细节到Console。
    但是,异常也可以由程序员抛出:

    class Demo{
        public int method(int[] arr,int index){
            if(arr==null){
                throw new NullPointerException("数组的引用不能为空");
            }
            if(index>=arr.length){
                throw new ArrayIndexOutOfBoundsException("数组角标越界了"+index);
            }
            if(index<0){
                throw new ArrayIndexOutOfBoundsException("角标不能为负数"+index);
            }
            return arr[index];
        }
    }
    public class lizi {
    
        public static void main(String[] args) {
            int[] arr=new int[3];
            Demo d=new Demo();
            int num = d.method(null,8);
            //int num1= d.method(arr, 5);
            //int num2= d.method(arr, -4);
        }
    }
    
    运行:

    自定义异常:

    对于角标是整数不存在,可以用角标越界表示。
    对于负数为角标的情况,准备用负数角标异常来表示。

    负数角标这种异常在java中并没有定义过。
    那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述,并封装成对象。

    这种自定义的问题描述称为自定义异常。

    注意:如果让一个类成为异常类,必须要继承异常体系,因为只有成为异常体系的子类才有资格具备可抛性。 才可以被两个关键字所操作,throws、throw。

    class FuShuIndexException extends Exception{
        FuShuIndexException(){
        }
        FuShuIndexException(String s){
            super(s);//原理看底下Person的例子
        }
    }
    class Demo{
        public int method(int[] arr,int index) throws FuShuIndexException{//声明抛出
            if(index<0){
                throw new FuShuIndexException("角标不能为负数"+index);
            }
            return arr[index];
        }
    }
    public class lizi {
    
        public static void main(String[] args) throws FuShuIndexException{//调用者也需声明抛出
            int[] arr=new int[3];
            Demo d=new Demo();
            int num2= d.method(arr, -4);
        }
    }
    /*
    class Person{
        private String name;
        Person(String name){
            this.name=name;
        }
        public String getName(){
            return name;
        }
    }
    class Student extends Person{
        Student(String name){
            super(name);
        }
    }
    */
    
    运行:

    Exception异常的分类:

    1 编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。 这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。 这样的问题都可以针对性处理

    声明的目的时让调用我们的调用者去处理问题

    2 编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。这种问题的发生,无法让功能继续,运行无法进行,更多是因为调用的原因导致的,或者引发了内部状态的改变导致的。那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。
    所以无需在throws子类句中进行声明(开发时比较常遇到)

    所以自定义异常时,要么继承Exception,要么继承RuntimeException

    throws和throw的区别:

    1 throws使用在函数上;throw使用在函数内
    2 throws抛出的是异常类,可以抛出多个,用“,”隔开;throw抛出的是异常对象。

    class Demo{
        public int method(int[] arr,int index) 
        {
            if(arr==null){
                throw new NullPointerException("数组的引用不能为空");
            }
            if(index>=arr.length){
                throw new ArrayIndexOutOfBoundsException("数组角标越界了"+index);
            }
            return arr[index];
        }
    }
    public class lizi {
    
        public static void main(String[] args)
        {
            int[] arr=new int[3];
            Demo d=new Demo();
            int num = d.method(null,8);
        }
    }
    

    异常捕捉:

    异常处理的捕捉形式:

    这是可以对异常进行针对性处理的方式。

    具体格式是:
    try{
    //需要被检测异常的代码
    }catch(异常类  变量){//该变量用于接收发生的异常对象
    处理异常的代码
    }finally{
    //一定会被执行的代码
    }
    

    如果你内部能解决的问题就catch,如果解决不了就抛出去(try)让调用者处理

    class FuShuIndexException extends Exception{
        FuShuIndexException(){
        }
        FuShuIndexException(String s){
            super(s);
        }
    }
    
    class Demo{
        public int method(int[] arr,int index) throws FuShuIndexException//声明抛出    
        {
            if(index<0){
                throw new FuShuIndexException("角标变成负数啦!!!");
            }
            return arr[index];
        }
    }
    class CatchDemo1{
    
        public static void main(String[] args)
        {
            int[] arr=new int[3];
            Demo d=new Demo();
            try{
                int num = d.method(arr,-8);
                System.out.print(num);
            }catch (FuShuIndexException x){
                System.out.println("message"+x.getMessage());
                System.out.println("String"+x);//本来应该输出的是哈希值,这里默认调用toString
                
                x.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法
                System.out.println("负数角标异常!!!");
            }
            System.out.println("over");
        }
    }
    
    运行:
    多catch情况:
    class FuShuIndexException extends Exception{
        FuShuIndexException(){
        }
        FuShuIndexException(String s){
            super(s);
        }
    }
    
    class Demo{
        public int method(int[] arr,int index) throws FuShuIndexException//声明抛出    
        {
            if(arr==null){
                throw new NullPointerException("数组的引用不能为空");
            }
            if(index<0){
                throw new FuShuIndexException("角标变成负数啦!!!");
            }
            return arr[index];
        }
    }
    class CatchDemo1{
    
        public static void main(String[] args)
        {
            int[] arr=new int[3];
            Demo d=new Demo();
            try{
                int num = d.method(null,-8);
                System.out.print(num);
            }catch(NullPointerException y){
                System.out.println(y.toString());
            }
            catch (FuShuIndexException x){
                System.out.println("message"+x.getMessage());
                System.out.println("String"+x);//本来应该输出的是哈希值,这里默认调用toString
                
                x.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法
                System.out.println("负数角标异常!!!");
            }/*catch(Exception e){//面试可能会有      除以上异常之外又有异常的情况下,就用这个catch,
                                //不管发生啥异常 全都接收,但必须放在最后一个catch之后
                                //一般情况下不会发生这种情况(除声明抛出异常的情况下,jvm还是报错的情况下)
                                //多catch下父类的catch放在最下面
            }*/
            System.out.println("over");
        }
    }
    

    异常处理的原则:

    1 函数内部如果抛出需要检测的异常,那么函数上必须要声明(throws),否则必须在函数内用try-catch捕捉,否则编译失败。

    2 如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。

    3 什么时候catch,什么时候throws呢?
    内容功部可以解决,用catch;解决不了,用throws告诉调用者,由调用者解决。

    4 一个功能如果抛出多个异常,那么调用时,必须对应多个catch进行针对性的处理。内部有几个需要检测的异常,就抛出几个异常,抛出几个,就catch几个。

    finally:

    class Demo{
        public int show(int index)throws ArrayIndexOutOfBoundsException//有了这个,主函数就得try了
        {
            if(index<0){
                throw new ArrayIndexOutOfBoundsException("数组角标越界了"+index);
            }
            int[] arr=new int[3];
            return arr[index];
        }
    }
    public class FinnallyDemo {
    
        public static void main(String[] args) {
            Demo d=new Demo();
            try{
                int num =d.show(-1);
                System.out.println(num);
            }
            catch(ArrayIndexOutOfBoundsException e){
                System.out.println(e.toString());
                //return ;//finally还是能执行到
                System.exit(0);//退出jvm,finally就执行不到了
            }finally{//开发的时候常用         通常用于关闭(释放)资源
                System.out.println("finally");
            }
            System.out.println("over");
        }
    
    }
    /*
    连接数据库   数据库本身就有资源限制 所以浪费不得   所以一定要有finally
    查询      可能过程中出问题了
    关闭连接 -->但是这个无论怎样都要执行 所以定义在finally中
    
    try catch finally 代码块组合特点:
    1  try catch finally
    2 try catch(多个)当没有必要资源需要释放时,可以不用定义finally。
    3 try finally(常用)   异常无法直接catch处理,但是资源需要关闭。
    void show() throws Exception{
        try{
            //开启资源
            throw new   Exception();//出现异常
            
        }
        finally{
            //关闭资源
        }
    } 
    */
    

    应用:

    /*
     老师用电脑上课
     
     问题领域中涉及两个对象
     老师,电脑
     
     分析其中的问题:
     比如电脑蓝屏了。
    */
    class LanPingException extends Exception{
        LanPingException(String msg){
            super(msg);
        }
    }
    class MaoYanException extends Exception{
        MaoYanException(String msg){
            super(msg);
        }
    }
    class NoWanChengException extends Exception{
        NoWanChengException(String msg){
            super(msg);
        }
    }
    class Computer{
        private int stats=2;//0,1,2
        public void run()throws LanPingException,MaoYanException
        {
            if(stats==1)
                throw new LanPingException("电脑蓝屏了");
            if(stats==2)
                throw new MaoYanException("电脑冒烟了");
            System.out.println("电脑运行");
        }
        public void reset(){
            stats=0;
            System.out.println("电脑重启");
        }
    }
    class Teacher{
        private String name;
        private Computer comp;
        Teacher(String name){
            this.name=name;
            comp=new Computer();
        }
        public void prelect ()throws NoWanChengException{
            try{
            comp.run();
            System.out.println("讲课");
            }catch(LanPingException e){
                System.out.println(e.toString());
                comp.reset();
                prelect();
            }catch(MaoYanException e){
                System.out.println(e.toString());
                test();
                //可以对电脑进行维修
    //          throw e;并不是捕捉到异常就的抛出去,有的这边无法解决就得定义别的异常
                       //比如电脑冒烟,公司无法远程解决修理,就导致课程无法完成异常,所以就把问题换成解决无法完成课程的问题并抛出解决,老师可以换台电脑
                throw new NoWanChengException("课程无法完成"+e.getMessage());
            }
        }
        public void test(){
            System.out.println("大家练习");
        }
    }
    public class YingYong {
    
        public static void main(String[] args) {
            Teacher t=new Teacher("老师");
            try{
                t.prelect();
            }catch(NoWanChengException e){
                System.out.println(e.toString()+"...");
                System.out.println("老师换电脑");
            }   
        }
    }
    /*
    class NoAddException extends Exception{}
    void addData(Data d)throws (SQLException换成)NoAddException
    {
        连接数据库
        try{
               添加数据,出现异常SQLException
        }catch(SQLException e){
            //处理代码                                 这种方式也叫做异常的封装,就是不该暴露的问题就没有必要暴露出去,即使暴露出去对方也没办法解决
            throw new NoAddException
        }finally{
         关闭数据库
        }
    }
    */
    
    运行:

    异常注意事项:

    1 子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。

    2 如果父类抛出多个异常,那么子类只能抛出父类异常或者其子集。

    简单说:子类覆盖父类只能抛出父类的异常或者子类或者子集。

    注意:

    如果父类没抛出异常,那么子类覆盖时绝对不能抛。就只能try。

    相关文章

      网友评论

          本文标题:java笔记--异常

          本文链接:https://www.haomeiwen.com/subject/kqydhftx.html