目录
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太低了,涨工资