目录
1、运行时异常 RuntimeException的子类都是运行时异常
索引越界异常IndexOutOfBoundsException
一、断言
1、功能
JDK1.4版本开始,增加了断言机制;
断言用来进行调试,不在生产环境中使用;
换言之,断言是为了帮助程序员在编程的过程中,尽快发现错误并进行修改,使得程序在生产环境中正常运行;
2、assert关键字表示
assert <布尔表达式> assert <布尔表达式> : <错误信息>
- 当布尔表达式的值是true时,忽略assert;
 - 当布尔表达式的值是false时,发生AssertionError错误,程序中断;如果用第二种形式,同时显示错误信息;
 
3、idea开启断言
Edit Configurations
找到要执行的类,在VM options添加 -ea
public class Test1 {
    public static void main(String[] args) {
        int i=10;
        assert i!=10:"断言错误!";
        System.out.println("i = " + i);
    }
}
/*
Exception in thread "main" java.lang.AssertionError: 断言错误!
    at a07.Test1.main(Test1.java:6)
*/
 
二、异常处理
1、异常Exception
异常指的是程序运行时发生的不正常事件;异常能够被程序处理,保证程序继续运行下去;例如除数为0、文件没有找到、输入的数字格式不对……
System.out.println("程序出现异常:");
System.out.println(100/0);//出现异常没有被正确处理,不能往下运行
System.out.println("程序继续运行");
java.lang.ArithmeticException: / by zero
 
 
2、错误Error
错误程序没法处理,eg内存泄漏。发生错误后,一般虚拟机会选择终止程序运行,需要修改代码解决
int[] a=new int[1024*1024*1024];
//java.lang.OutOfMemoryError对空间超出JVM内存,内存溢出,只能把长度改小
 
Throwable类(顶级父类)
Throwable类有两个子类:Exception和Error
所有异常都是Exception类的直接或间接子类
所有错误都是Error的直接或间接子类

1、运行时异常 RuntimeException的子类都是运行时异常
非检测异常(unchecked Exception),这些异常在编译期不检测,程序中可以选择处理,也可以不处理,编译通过,如果不处理运行时会中断,但是编译没问题;
空指针异常NullPointerException
发生前提:当对一个空对象既没有初始化依然为null的对象调用属性或方法时
String str1 = "";//输出0,str1为空字符串,长度为0,存在
String str = null;//不存在
System.out.println(str.length());
//str为null,对象为null,调用length(),就会报NullPointerException异常
 
数学异常ArithmeticException
整数除以0
System.out.println(10.0/0);//**浮点型不抛出异常**,输出Infinity
System.out.println(10/0);//**整数抛出异常**java.lang.ArithmeticException
 
索引越界异常IndexOutOfBoundsException
数组索引:ArrayIndexOutOfBoundsException
字符串索引:StringIndexOutOfBoundsException
当访问字符串中的字符或数组中的元素超过了其长度时
//int[] a=new int[3];
//System.out.println(a[3]);//数组索引越界,出现异常java.lang.ArrayIndexOutOfBoundsException: 3(冒号左边异常类型,右边提示信息)
String str="hello";
//打印字符串索引5的字符,会出现异常StringIndexOutOfBoundsException: String index out of range: 5
System.out.println(str.charAt(5));//字符串长度为5,索引 最大值为4,访问第5个字符,将发生索引越界异常
 
数字格式化异常 NumberFormatException
把字符串转成数字,字符串内容不是数字时发生
String str="abc";
System.out.println(Integer.valueOf(str));
//数字格式化出现异常NumberFormatException: For input string: "abc"
 
类型转换异常 ClassCastException
把父类对象转换成不相关的子类类型时
Object o=new Object();
//编译没有问题,向下造型,能不能转成功就不一定了
String s=(String ) o;
System.out.println(s);
ClassCastException:java.lang.Object cannot be cast to java.lang.String
 
2、非运行时异常(检测异常)
检测异常(checked Exception)
编译期处理且必须处理,如果不处理将会发生编译期错误
//检测异常不处理,编译不能通过,强行要求处理  
FileReader fileReader=new FileReader("a.txt");
 
-  
标准异常处理流程
 

try-catch-finally
try{
  可能抛出异常的代码块;
}catch(异常类型  变量名){
    处理异常的代码;
}finally{
    不管什么情况,一定被执行的代码块; 
}
 
1、发生异常被捕获处理
如果catch住异常执行catch的代码,后面的代码不会正常执行
public class CheckExceptionTest {
    public static void main(String[] args) {
        test1();
        System.out.println("main方法运行结束");//
    }
    private static void test1(){
        //try-catch处理异常
        //出现异常后不影响下面代码的执行
        try {
            int x = 100;
            int y = 0;
            //代码运行发生异常
            System.out.println("x/y" + (x / y));
           //下面的不会执行,如果catch住异常执行catch的代码,后面的代码不会正常执行
           //没有catch住,程序就会退出
            System.out.println("计算完成");
        }catch (ArithmeticException e){
            System.out.println("除法发生了异常,进行了处理");
        }
    }
}
/*
除法发生了异常,进行了处理
main方法运行结束
*/
 
2、发生异常没有被捕获处理
异常类型匹配
catch (NullPointerException e) {
//异常处理机制将ArithmeticException与catch语句的异常类型匹配
    System.out.println("发生了异常");
    //匹配失败,不运行catch代码块,异常没有被处理;
}
 
3、没发生异常
所有代码正常运行,但catch的代码不运行
public class CheckExceptionTest {
    public static void main(String[] args) {
        test1();
        System.out.println("main方法运行结束");
    }
    private static void test1() {
        //try-catch处理异常
        try {
            int x = 100;
            int y = 10;
            //代码运行没有发生异常,所有代码正常运行,但catch的代码不运行
            System.out.println("x/y=" + (x / y));
            //下面的不会执行,如果被catch住异常了,那么执行catch的代码,后面的代码不会正常执行,没有catch住,程序就会退出
            System.out.println("计算完成");
        } catch (NullPointerException e) {
            System.out.println("除法发生了异常,进行了处理");
        }
    }
}
 
try-catch【多个catch】
匹配顺序由上到下,Exception e放在最下面
catch语句的异常类型必须从子类到父类的顺序,否则编译错误;
try {
    数学计算
    int x=100;
    int y=0;
    System.out.println("x/y="+(x/y));
    空指针
    String s=null;
    System.out.println(s.length());
    其他
    int[] a=new int[3];
    System.out.println(a[3]);
    System.out.println("test2()运行完成");
  }catch (ArithmeticException e){                 
  //多个catch 有一个被捕获了就不再匹配其他的catch
    System.out.println("数学计算发生了异常");
  }catch (NullPointerException e){
    System.out.println("空指针异常");
  }catch (Exception e){            
  //**匹配顺序由上到下,Exception e放在最下面**,如果放到第一个后面的catch便没有意义永远不会被执行,所以编译报错
    //todo 写日志
    System.out.println("其他异常");
  }
 
try-finally finally内的代码一定执行
throw
new一个异常对象,throw关键字交给异常处理机制去处理;
throw关键字在方法体中使用
throw 异常对象;throw new Exception(); 或者catch(Exception e){ throw e;}
-  
运行时异常是JVM自动抛出
 -  
非运行时异常需要程序员用throw抛出
-  
throw
由于抛出了Exception,是非运行时异常,所以编译器检测要处理:
1、try-catch-finally //没意义
2、不处理,用throws声明异常 //常用
 -  
throws
用在方法声明处,声明该方法可能发生的异常类型
可声明多种类型,用逗号隔开
抽象方法也可以用throws声明该方法可能抛出的异常类型
 -  
调用带有throws方法必须处理这些异常
真正抛出和处理的异常是声明的子类或本身类,不能比他大
 
 -  
 
public class Calculator {
    /**
     * 除法计算
     *
     * @param x
     * @param y
     * @throws Exception 方法声明了  抛出Exception异常(表示这个方法运行过程中会有Exception发生的可能性)
     */
    public void div(int x, int y) throws Exception {
        //如果y==0,除法会抛异常
        if (y == 0) {
            throw new Exception("异常测试,主动抛出异常");//没人处理,编译报错
        }
        System.out.println(x / y);
    }
    public static void main(String[] args) throws Exception {
        Calculator calculator = new Calculator();
       try{
            calculator.div(10, 0);
//必须要处理异常,不处理不能通过编译try-catch或者throws Exception,二者选一就行
        }catch (Exception e){
            System.out.println("div方法发生了异常:"+e.getMessage());
        }
    }
}
 
先统一处理,再次抛出
public class Calculator {
    public void div(int x, int y) throws Exception {
        try {
            if (y == 0) {
                throw new Exception("异常测试,主动抛出异常");
            }
        }catch (Exception e){
            System.out.println("处理数据");
            //再次抛出
            throw e;
        }
        System.out.println(x / y);
    }
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        try{
            calculator.div(10, 0);
        }catch (Exception e){
            System.out.println("div方法发生了异常:"+e.getMessage());
        }
    }
}
 
不管有没有异常作统一处理,有异常声明抛出可以用try-finally
public void div(int x, int y) throws Exception {
        //如果y==0,除法会抛异常
        try {
            if (y == 0) {
                throw new Exception("异常测试,主动抛出异常");
            }
            System.out.println(x / y);
        }finally {
            System.out.println("关闭文件句柄");
        }
    }
 
throw和throws的区别
throw就是自己处理一个异常,要么自己捕获异常try...catch,要么抛出一个异常(throws 异常)
throws在方法后边声明异常,自己不想对异常做出任何的处理,告诉别人自己可能出现的异常,交给别人处理
-  
throw:抛出一个具体的异常类型
用在方法体内,后面是异常对象名,只能抛出一个异常对象名
由方法体内的语句处理 ,throw是抛出了异常,执行throw则一定抛出了某种异常
 -  
throws:用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁。
用在方法声明后面,跟的是异常类名,可以跟多个异常类名,用逗号隔开
由该方法的调用者来处理 ,throws表示出现异常的一种可能性,并不一定会发生这些异
 
自定义异常类的实现方法和一般规则
自定义异常类实现
public class DataValueException extends **Exception**{
    public DataValueException(){
    }
    public DataValueException(String message){
        super(message);
    }
    /**
     * 构造方法
     * @param e** 异常对象
**     */
    public DataValueException(Throwable e){
        super(e);
    }
    public DataValueException(String message,Throwable e){
        super(message,e);
    }
}
 
使用自定义异常与使用API标准异常一样
public class Employee {
    private String name;
    private double salary;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    //工资小于等于2500抛出异常
    public void setSalary(double salary) throws DataValueException {
        if(salary<=2500){
            throw new DataValueException("工资小于2500太低了,涨工资");
        }else{
            this.salary = salary;
        }
    }
    public static void main(String[] args) {
        Employee e=new Employee("肖战王一博",2026);
        try {
            e.setSalary(2400);
        } catch (DataValueException ex) {
            //打印ex对象DataValueException的toString方法,DataValueException没有冲洗toString(),然后找父类Exception,也没有,再找Throwable,
            System.out.println(ex);
        }
    }
    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
}
//com.bjyx.myException.DataValueException: 工资小于2500太低了,涨工资









