异常的定义
异常就是程序在编译或运行期间 所产生的一种不正常的结果。
异常指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。
在 Java 的异常处理机制中,引进了很多用来描述和处理异常的类,称为异常类。
异常类定义中包含了该类异常的信息和对异常进行处理的方法。
所谓异常处理,就是指程序在出现问题时依然可以正确的执行完。
Java中的 异常的体系结构
Throwable
Error(错误) 一个Error是的子类Throwable表示严重的问题,合理的应用程序不应该试图捕获 VirtualMachineError
Exception(异常)
RuntimeException
Excpetion的直接子类称为编译期异常(检查异常)
RuntimeException的子类称为运行时异常(非检查异常)
Error:严重问题,不需要处理
Exception:称为异常类,它表示程序本身可以处理的问题
RuntimeException:在编译期是不检查的,出现问题后,需要我们回来修改代码
非 RuntimeException:编译期就必须处理的,否则程序不能通过编译,就更不能正常运行了
常见的RuntimeException
//运行时异常
// IndexoutOfBoundsException--->ArrayIndexOutOfBoundsException
int[] arr = new int[5];
System.out.println(arr[0]);
//System.out.println(arr[5]);
// 空指针异常 NullPointException
String str = null;
// System.out.println(str.equals("abc"));
// 类型转换异常 ClassCastException
Object obj = new String();
// Integer inte = (Integer)obj;
// 算术异常ArithmeticException
System.out.println(1/0);
// 解析异常 ParseException
String strDate = "2020-12-23 " ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(strDate);// 有可能发生异常 必须处理 不处理程序无法正常执行
System.out.println(date);
异常对程序产生的影响
当发生异常的时候 程序就会终止,异常代码之后的 程序将不在执行。
异常的处理
Java中对异常的处理 提供了一种异常处理模型抓抛模型
捕获异常:
try{
包含有可能发生异常的代码。
}catch(异常类型 变量){ //捕获
针对这种异常的处理。
}finally{
无论程序是否发生异常 都需要执行的代码
}
// 解析异常 ParseException
String strDate = "2020-12-23 " ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;// 有可能发生异常 必须处理 不处理程序无法正常执行
try {
date = sdf.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
通过catch捕获异常 并对异常做出相应的处理 这样就可以保证程序继续执行
在捕获异常时 可以有多个catch
// 解析异常 ParseException
String strDate = "2020-12-23 " ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;// 有可能发生异常 必须处理 不处理程序无法正常执行
try {
// System.out.println(arr[5]);
System.out.println(str.equals("abc"));
Integer inte = (Integer)obj;
System.out.println(1/0);
date = sdf.parse(strDate);
} catch (ParseException e) {
System.out.println("ParseException。。。。");
e.printStackTrace();
}catch (ArrayIndexOutOfBoundsException ae){
System.out.println("ArrayIndexOutOfBoundsException。。。。。");
}catch (NullPointerException ne){
System.out.println("NullPointerException。。。。。");
}
System.out.println(date);
System.out.println("program end");
}
多异常捕获的写法
try {
Integer inte = (Integer)obj;
System.out.println(arr[5]);
System.out.println(str.equals("abc"));
System.out.println(1/0);
date = sdf.parse(strDate);
} catch (ParseException |ArrayIndexOutOfBoundsException |NullPointerException e) {
System.out.println("异常处理");
e.printStackTrace();
}
通过异常的多态来捕获
try {
System.out.println(arr[5]);
System.out.println(str.equals("abc"));
Integer inte = (Integer)obj;
System.out.println(1/0);
date = sdf.parse(strDate);
} catch (Exception e) {
System.out.println("异常处理");
// e.printStackTrace();
}
这种写法仅限于jkd7以上
可以这样写
try {
Integer inte = (Integer)obj;
System.out.println(arr[5]);
System.out.println(str.equals("abc"));
System.out.println(1/0);
date = sdf.parse(strDate);
} catch (ParseException e) {
System.out.println("异常处理");
e.printStackTrace();
}catch (ArrayIndexOutOfBoundsException ae){
}catch (NullPointerException ne){
}catch (Exception ee){
}
捕获异常 将有可能发生异常的代码写在try块中,当发生异常的时候 就会执行相应的catch块的内容 可以保证异常处理之后的代码的正常执行 从而使得程序可以正常终止
在程序设计时,只需将有可能发生异常的代码放在try块中 而不要将没有异常发生的 代码添加到try 这样会影响程序的执行的效率
异常信息的 分析
异常信息的描述
在异常体系中,所有的子类都没有具体方法 方法都是 来自于Throwable
} catch (ParseException e) {
System.out.println("异常处理");
e.printStackTrace();
}catch (ArrayIndexOutOfBoundsException ae){
System.out.println("数组下标越界");
ae.printStackTrace();
String message = ae.getMessage();//Index 5 out of bounds for length 5
System.out.println(message);
}catch (NullPointerException ne){
ne.printStackTrace();
}catch (Exception ee){
ee.printStackTrace();//得到的异常的全部信息
String msg= ee.toString();
System.out.println(msg);
}
编译期异常和运行时异常的区别:
1 运行时 异常不处理 不会影响程序的运行 而运行期异常则必须做出相应的处理 否则程序无法运行
2运行时异常 往往都可以通过优化代码来进行规避 运行时异常的出现 都是我们的程序存在逻辑上的漏斗或者缺陷
在实际处理中 处理的重点编译期异常
第二种处理方式:抛出异常
//将String类型转换为Date 解析
public static Date str2Date(String strDate) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(strDate);
return date;
}
抛出异常是在方法的 声明上 通过throws 关键字 来进行声明
告诉方法的调用者,该方法存在这样类型的异常 throws后边跟的 是异常类型
//将String类型转换为Date 解析
public static Date str2Date(String strDate) throws ParseException, IOException {
File file = new File("src/str.txt");
file.delete();
file.canWrite();
file.getCanonicalPath();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(strDate);
return date;
}
在throws后边可以 跟多个类型异常
抛出异常是 抛给了方法 的 调用者,此时对于方法的 调用者来说将有两种选择
第一种使用try{}catch{}来捕获异常并处理
第二种则是不处理 继续使用throws往外抛
直到在main放中 如果此时 也不处理 则抛出的 话就抛给了jvm
JVM对于接受到的异常的默认处理
以上就是jvm的默认处理方式:
就是打印异常的 堆栈信息,并终止程序的 执行。
对于与业务相关的 异常,就需要我们自己来定义异常
自定义异常
有一个考试系统,需要老师 来录入学生的考试成绩 ,如果 老师录入的成绩是0-100则为正常,负责就抛出一个成绩不合法的异常信息
如何自定义异常:
自定义 异常就有两种:
一种是自定义编译期异常
另一种就是定义运行时 异常
如果要自定义个一个编译期异常 则继承Exception即可 并实现相应的构造方法即可
如果要自定义一个运行时异常 则继承RuntimeException 并实现相应的构造方法
//自定义一个成绩异常
public class ScoreException extends Exception{
public ScoreException(){
super();
}
//message表示显示的错误信息
public ScoreException(String message){
super(message);
}
}
public class Teacher {
public void recoderScore(int score) throws ScoreException {
if(score >0 && score <=100){
System.out.println("本次录入的成绩为:" + score);
}else{
// 手动抛出异常
throw new ScoreException("成绩不合法");
}
}
public static void main(String[] args) throws ScoreException {
Teacher teacher = new Teacher();
teacher.recoderScore(180);
}
}
throw和throws的区别
1 位置:throws用在方法的声明上 throw在方法体
2 抛出类型:throws抛出的是 异常的类型 throw抛出的是异常对象
3 数量:throws可以抛出多个异常 throw只能抛出 一个异常对象
什么时候抓是么时候抛?
捕获异常一般都在我们可以自己处理 并且处理之后不会再次产生新的异常时 才捕获处理。
如果 不能完全处理 异常 则将异常抛出给下一个方法的调用者 让其来做出相应的处理,直到最后抛给jvm