Java异常
1、简介
1.1 概念
异常是程序在“编译”或者“执行”的过程中可能出现的问题,注意:语法错误不算在异常体系中。
比如:数组索引越界、空指针异常、 日期格式化异常,等…
1.2 分类
编译时异常可以理解为在开发工具写代码时让你抛出异常的
运行时异常是运行java代码时的报错
1.3 作用
异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止。
研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性。
2、常见的异常
2.1 常见的运行时异常
直接继承自RuntimeException或者其子类,编译阶段不会报错,运行时可能出现的错误。
- 数组索引越界异常: ArrayIndexOutOfBoundsException
- 空指针异常 : NullPointerException,直接输出没有问题,但是调用空指针的变量的功能就会报错。
- 数学操作异常:ArithmeticException
- 类型转换异常:ClassCastException
- 数字转换异常: NumberFormatException
运行时异常:一般是程序员业务没有考虑好或者是编程逻辑不严谨引起的程序错误,
自己的水平有问题!
2.2 常见的编译时异常
不是RuntimeException或者其子类的异常,编译阶就报错,必须处理,否则代码不通过。
编译时异常:继承自Exception的异常或者其子类
编译阶段报错,必须处理,否则代码不通过。
String date = "2015-01-12 10:23:21";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(date);
System.out.println(d);
3、异常的默认处理流程
- 默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException。
- 异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。
- 虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。
- 直接从当前执行的异常点干掉当前程序。
- 后续代码没有机会执行了,因为程序已经死亡。
4、编译时异常的处理机制
编译时异常是编译阶段就出错的,所以必须处理,否则代码根本无法通过
编译时异常的处理形式有三种:
- 出现异常直接抛出去给调用者,调用者也继续抛出去。用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理。
与异常的默认处理流程差不多,都是最终抛给JVM。
多个异常时可以改为throws Exception,代表可以抛出一切异常
public static void main( String[] args ) throws Exception {
String date = "2015-01-12 10:23:21";
paraseTime(date);
}
public static void paraseTime(String date) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(date);
System.out.println(d);
InputStream s = new FileInputStream("E:/qqq.jpg");
}
这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡。
2. try…catch…出现异常自己捕获处理,不麻烦别人。
监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。
这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行。
package com.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Exception {
public static void main(String[] args) {
String date = "2015-01-12 10:23:21";
paraseTime(date);
}
public static void paraseTime(String date){
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(date);
System.out.println(d);
} catch (ParseException e) {
System.out.println("出现解析异常");
}
try {
InputStream s = new FileInputStream("E:/qqq.jpg");
} catch (FileNotFoundException e) {
System.out.println("出现文件没有读取到异常");
}
}
}
- 前两者结合,出现异常直接抛出去给调用者,调用者捕获处理。
方法直接将异通过throws抛出去给调用者
调用者收到异常后直接捕获处理。
package com.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Exception {
public static void main(String[] args) {
try {
String date = "2015-01-12 10:23:21";
paraseTime(date);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
public static void paraseTime(String date) throws FileNotFoundException, ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(date);
System.out.println(d);
InputStream s = new FileInputStream("E:/qqq.jpg");
}
}
5、运行时异常的处理机制
运行时异常编译阶段不会出错,是运行时才可能出错的,所以编译阶段不处理也可以。
按照规范建议还是处理:建议在最外层调用处集中捕获处理即可。
package com.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Exception {
public static void main(String[] args) {
System.out.println("开始");
try {
chu(10,0);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
System.out.println("结束");
}
public static void chu(int a,int b) {
System.out.println(a);
System.out.println(b);
int c = a / b ;
System.out.println(c);
}
}
6、自定义异常
为什么自定义异常
Java无法为这个世界上全部的问题提供异常类。
如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类了。
作用
可以使用异常的机制管理业务问题,如提醒程序员注意。
同时一旦出现bug,可以用异常的形式清晰的指出出错的地方。
自定义异常分类
1、自定义编译时异常
定义一个异常类继承Exception.
重写构造器。
在出现异常的地方用throw new 自定义对象抛出,
作用:编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理!!
package com.test;
public class AgeIllegalsException extends java.lang.Exception {
public AgeIllegalsException() {
}
public AgeIllegalsException(String s) {
super(s);
}
}
package com.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Exception {
public static void main(String[] args) {
System.out.println("开始");
try {
checkAge(-34);
} catch (AgeIllegalsException e) {
e.printStackTrace();
}
System.out.println("结束");
}
public static void checkAge(int age) throws AgeIllegalsException {
if(age < 0 || age >200){
//抛出异常
//throw:在方法内部直接创建一个异常对象,并从此点抛出
//throws:用在方法申明上的,抛出方法内部的异常
throw new AgeIllegalsException(age + " is illegal!");
}else {
System.out.println("年龄合法");
}
}
}
2、自定义运行时异常
定义一个异常类继承RuntimeException.
重写构造器。
在出现异常的地方用throw new 自定义对象抛出!
作用:提醒不强烈,编译阶段不报错!!运行时才可能出现!!
package com.test;
public class AgeIllegalsRuntimeException extends RuntimeException{
public AgeIllegalsRuntimeException() {
}
public AgeIllegalsRuntimeException(String s) {
super(s);
}
}
package com.test;
public class ExceptionTest {
public static void main(String[] args) {
System.out.println("开始");
try {
checkAge(-34);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("结束");
}
public static void checkAge(int age) throws AgeIllegalsRuntimeException {
if(age < 0 || age >200){
//抛出异常
//throw:在方法内部直接创建一个异常对象,并从此点抛出
//throws:用在方法申明上的,抛出方法内部的异常
throw new AgeIllegalsRuntimeException(age + " is illegal!");
}else {
System.out.println("年龄合法");
}
}
}