java基础-异常

异常的概念:

程序在运行过程中出现的特殊情况

异常处理的必要性:任何程序都可能存在大量的未知问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。

异常的分类:

Throwable:

可抛出的,一切错误或异常的父类,位于java.lang包中。

|- Error:

JVM、硬件、执行逻辑错误,不能手动处理。(程序无法处理的)

|-Exception:

程序在运行和配置中产生的问题,可处理。

|-RuntimeException:

运行时异常,可处理,可不处理。(编译可通过)

|-CheckedException:

受查异常,必须处理。(编译不通过)

package com.james;
​
import java.io.File;
​
public class TestException02 {
​
    public static void main(String[] args) {
        File f = new File("");
        
        //  NullPointerException(空指针异常)任何直接或者间接继承了RunTimeException的异常对象
        //      在编译期间,即使不做额外的处理,编译器也是不会报错的
        
        NullPointerException n;
        
        //  f.createNewFile()属于检测异常,如果在编译期间不做处理,编译器会报错
        //f.createNewFile();
        
        System.out.println();
        
        System.out.println("over");
    }
}
​

异常的产生

自动抛出异常

当程序在运行时遇到不符合规范的代码或结果时,会产生异常。

package com.james;
​
public class TestException01 {
​
    public static void main(String[] args) {
        String str = null;
        
        //  如果程序出现了异常,那么程序会在出现异常处中断,即使后面的代码没有问题
        System.out.println(str.length());
        
        System.out.println("over");
    }
}
​

手动抛出异常

语法:throw new 异常类型(“实际参数”);

产生异常结果

相当于遇到return语句,导致程序因异常而终止。

异常的传递

定义:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理

受查异常:throws声明异常,修饰在方法参数列表后端。

运行时异常:因可处理可不处理,无需声明异常。

异常的处理

try{
    可能出现异常的代码
}catch(Exception e){
    异常处理的相关代码,如:getMessage()、printStackTrace()
}finally{
    无论是否出现异常,都需执行的代码结构,常用于释放资源
}

异常机制的目的是,在程序出现异常后,不至于异常处之后的代码也中断执行

常见异常处理结构

try{ } catch{ }

适用于可以确定异常类型

package com.james;
​
public class TestException04 {
​
    public static void main(String[] args) {
        String str = null;
        
        //  异常机制的目的是,在程序出现异常后,不至于异常处之后的代码也中断执行
        try {
            System.out.println(str.length());
        } 
        catch (Exception e) 
     //   catch (NullPointerException e) (两个打印结果一样)
     // 不仅仅可以写Exception,也可以写Exception的子类,但是异常类型必须等于或大于代码异常类型的范围
     //例如程序中出现的异常对象为NullPointerException,但是你要用IndexOutOfBoundsException(数组越界异常)来处理
     //异常机制相当于“形同虚设”,程序依然会提前中断执行(over不会被打印)
     //这是因为NullPointerException和IndexOutOfBoundsExceptionde的父类都是RunTimeException
     //这两个异常之间没有从属关系,是并列关系
        {
            System.out.println("exception");
            
            //  程序出现异常后,可以通过e.printStackTrace()来进行异常信息的追踪
        //e.printStackTrace()不写不会报编译错误,但是一般需要写,利于代码的维护,比较容易发现错误代码的位置
            e.printStackTrace();
        }
        
        System.out.println("over");
    }
}
输出:
exception
java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
    at com.james.TestException03.main(TestException03.java:10)
over
package com.james;
​
public class TestException06 {
​
    public static void main(String[] args) {
        String str = "abc";
        
        try {
            System.out.println(str.length());
            
            System.out.println(str.charAt(99));
        } catch (IndexOutOfBoundsException e) {
        //异常处理的类型符合代码异常的类型,则异常会被处理  
            System.out.println("exception");
            e.printStackTrace();
        }
        
        System.out.println("over");
    }
}
输出:
3
exception
java.lang.StringIndexOutOfBoundsException: String index out of range: 99
    at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)
    at java.base/java.lang.String.charAt(String.java:712)
    at com.james.TestException06.main(TestException06.java:12)
over

try{ } catch{ } catch{ }

对异常类型不确定,需要进行判断

不仅仅可以只有两个 catch{ }

一个try{ }多个catch{ }

一旦判定一种异常以后不会再判定其他异常(判定了一个代码以后不会再判定其他的代码)

package com.james;
​
/**
 * 一段try块的代码可以对应多个catch块的代码
 *  要注意:异常对象的编排顺序
 *      先子类异常对象,后父类的异常对象
 *      如果不存在继承关系,顺序可以随意
 *      最大的异常时Exception
 *      考虑效率问题,不要上来就使用Exception,而应该使用各自具体的Exception对象
 * @author james
 *
 */
public class TestException07 {
​
    public static void main(String[] args) {
        String str = null;
        String st = "ab";
        
        try {
            System.out.println(str.length());
            //只会对第一个代码进行判定,后续代码直接跳过
            
            System.out.println(str.charAt(99));
        } catch (NullPointerException e) {
            
            //   若程序中出现的异常对象为IndexOutOfBoundsException,则NullPointerException不能处理,会选择其他的异常处理结构
            System.out.println("null poniter exception");
            
            e.printStackTrace();
        } catch (StringIndexOutOfBoundsException e) {
            
            System.out.println("string index exception");
            
            e.printStackTrace();
        } catch (IndexOutOfBoundsException e) {
            System.out.println("index exception");
            
            e.printStackTrace();
        } 
        //IndexOutOfBoundsException,StringIndexOutOfBoundsException ,IndexOutOfBoundsException没有继承关系,顺序可以随意
        catch (RuntimeException e) {
            
            System.out.println("Runtime exception");
            
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("exception");
            
            e.printStackTrace();
        }
        //RuntimeException 是Exception的子类,需要放在前面
        System.out.println("over");
    }
}
输出:
null poniter exception
java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
    at com.james.TestException07.main(TestException07.java:21)
over
​

每段代码一个try{ }一个catch{ }

判定一个代码以后,继续判定下一个代码

package com.james;
​
/**
 * 异常处理机制中,可以多段代码共享一个try catch结构
 *  也可以每段代码编写自己的try catch结构,
 *  每个代码有自己的try catch结构的话,该代码出问题,后面的代码可以继续执行
 *  多段代码共享try catch,那么在出问题的代码块之后的代码将不被执行
 * @author james
 *
 */
public class TestException08 {
​
    public static void main(String[] args) {
        String str = null;
        
        //  异常机制的目的是,在程序出现异常后,不至于异常处之后的代码也中断执行
        try {
            System.out.println(str.length());
        } catch (NullPointerException e) {
            
            //   程序中出现的异常对象为NullPointerException,但是你要用IndexOutOfBoundsException来处理
            //      异常机制“形同虚设”,程序依然会提前中断执行
            System.out.println("string index exception");
            
            //  程序出现异常后,可以通过e.printStackTrace()来进行异常信息的追踪
            e.printStackTrace();
        } 
        
​
    /*  try {
            System.out.println(str.charAt(99));
        }//错误类型依旧是NullPointerException,判定的异常类型错误,程序会中断
        catch(IndexOutOfBoundsException e) {
            System.out.println("index exception");
            e.printStackTrace();
        }*/
        try {
            System.out.println(str.charAt(99));
        }
        catch(NullPointerException e) {
            System.out.println("index exception");
            e.printStackTrace();
        }
        
        System.out.println("over");
    }
}
输出:
string index exception
java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
    at com.james.TestException08.main(TestException08.java:18)
index exception
java.lang.NullPointerException: Cannot invoke "String.charAt(int)" because "str" is null
    at com.james.TestException08.main(TestException08.java:38)
over
​

try{ } catch{ } finally{ }

package com.james;
​
public class TestException09 {
​
    public static void main(String[] args) {
        try {
            String str = "";
            
            System.out.println(str.length());
        } catch (Exception e) {
            System.out.println("Exception");
            e.printStackTrace();
        }finally {
            System.out.println("finally");
            //无论Catch的异常类型是否异常对象的类型,都会执行finally
        }
        
        System.out.println("over");
    }
}

try{ } catch{ } catch{ } finally{ }

package com.james;
​
public class TestException10 {
​
    public static void main(String[] args) {
        try {
            String str = null;
            
            System.out.println(str.length());
        } catch (NullPointerException e) {
            System.out.println("Nullpointer Exception");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("Exception");
            e.printStackTrace();
        }//选择了一个catch以后,直接执行finally
        finally {
            System.out.println("finally");
        }
        
        System.out.println("over");
    }
}

try{ } finally{ }

package com.james;
​
/**
 * try catch结构也可以有try直接加finally结构
 *      注意:该结构并不真正处理异常对象,try finally块之后的代码将不会被执行
 * @author james
 *
 */
public class TestException11 {
​
    public static void main(String[] args) {
        try {
            String str = null;
            
            System.out.println(str.length());
        } finally {
            System.out.println("finally");
        }
        
        System.out.println("over");
    }
}
输出:
finally
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
    at com.james.TestException11.main(TestException11.java:15)

注:多重catch,遵循从子(小)到父(大)的顺序,父类异常在最后

​ 不可以是单独的try{ }

拓展

在主函数main和无返回值的方法中的用法

package com.james;
​
public class TestException12 {
​
    public static void main(String[] args) {
        try {
            System.out.println("try");
            String str = "aaaa";
            
            System.out.println(str.length());
        } catch(Exception e) {
            System.out.println("catch");
            e.printStackTrace();
        } finally {
            System.out.println("finally");
        }
        
        System.out.println("over");
    }
}
输出:
try
4
finally
over

带有返回值的方法中的用法

package com.james;
​
/**
 * 对于try catch finally结构而言,
 *  finally代码块一定在try或者catch的return之前执行
 *每种可能的结果只能有一个返回值
 *
 */
public class TestException13 {
​
    public static void main(String[] args) {
        System.out.println(getNum());
    }
    
    public static int getNum() {
        try {
            System.out.println("try");
            System.out.println(1 / 0);
//          return 1;
        } catch (Exception e) {
            System.out.println("catch");
            return -1;
        }finally {
            System.out.println("finally");
            
//          return 0;
        }
        /*在try catch结构中判定以后先暂存return的值,执行finally后在返回return的值
         * 
         * */
         
        return 0;
    }
}
输出:
try
catch
finally
-1
package com.james;
​
/**
 * 
 *
 */
public class TestException14 {
​
    public static void main(String[] args) {
        System.out.println(getNum());
    }
    
    public static int getNum() {
        int a = 0;
        try {
            System.out.println("try");
            
            //  return瞬间,a的值为0,即使在finally代码块中对a做了额外的运算,
            //      return a的值的瞬间的值永远是0,所以返回结果为0
            return a;
        } catch (Exception e) {
            System.out.println("catch");
            return -a;
        }finally {
            System.out.println("finally");
            a++;
//          return a;
        }
        
//      return 0;
    }
}
输出:
try
finally
0

自定义异常

概念:需继承Exception或Exception的子类,代表特定问题。

经验:异常类型名称望文生义,可在发生特定问题时抛出对应的异常。

常用构造方法:

​ 无参构造方法

​ String message参数的构造方法

package com.james;
​
public class IDLengthException extends Exception {
​
    public IDLengthException(String msg) {
        super(msg);
    }
}
​

应用:验证身份证号位数

package com.james;
​
public class TestMyException {
​
    public static void main(String[] args) throws IDLengthException {
        Person p = new Person();
        
        p.setPid("123456789012345678");
        p.setName("zhangsan");
        p.setAddr("nanyaoguoji");
        
        System.out.println(p);
    }
}
/**
 * throws和throw
 *  throws用于方法上的异常声明,意思是当前方法中可能出现的所有的异常对象,
 *      都可以在这里进行声明,写在当前方法的头部, 如果有多个,可以使用逗号分隔
 * 
 *  throw遇到某种具体的异常进行特殊的处理,进行异常的抛出处理
 *      解决异常的一种手段,写在方法体内
 * @author james
 *
 */
public class Person {
​
    private String pid;
    private String name;
    private String addr;
​
    @Override
    public String toString() {
        return "Person [pid=" + pid + ", name=" + name + ", addr=" + addr + "]";
    }
​
    public String getPid() {
        return pid;
    }
​
    /**
     * 身份证号码的长度必须是15或者18
     * @param pid
     * @throws IDLengthException
     */
    public void setPid(String pid) throws IDLengthException//使用自定义异常进行判定
    {
        if(!(pid.length() == 15 || pid.length() == 18)) {
            throw new IDLengthException("the length of ID must be 15 or 18");
        }
        this.pid = pid;
    }
//位数符合条件则打印身份证,不符合则报出异常
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getAddr() {
        return addr;
    }
​
    public void setAddr(String addr) {
        this.addr = addr;
    }
}

异常的方法重写

方法名、参数列表、返回值类型必须和父类相同。

子类的访问修饰符和父类相同或是范围大于父类。

子类的方法,不能抛出比父类更多、更宽(范围更大)的异常

package com.james;
​
/**
 * 重写关系中的异常抛出
 *      子类的方法的异常抛出不能大于父类的异常抛出
 * @author james
 *
 */
public class Son extends Father{
​
    @Override
    //编译错误,子类的方法的异常抛出大于父类的异常抛出
    public void test() throws Exception {
        // TODO Auto-generated method stub
        super.test();
    }
}
package com.james;
​
public class Father {
​
    public void test () throws RuntimeException{
        System.out.println("test in father");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值