Java中的异常
一、异常体系
1.异常的定义
异常Exception,是指程序运行时,由于输入错误,网络,程序逻辑等原因,导致运行时出现的问题。出现异常时,程序会暂时中断执行,并根据产生异常的原因,创建对应异常类型的异常对象,并抛给JVM捕获处理。
2.异常的分类
Throwable可以用来表示可以作为异常抛出的类,是所有异常类的父类。
Throwable类有两个子类:Error类和Exception类
(1)Exception类
用于描述运行时异常,此类异常可修复可处理。Exception类又分为两个子类分支,一个分支为RuntimeException,这种异常通常为程序错误导致的异常,为No Checked非检查异常,处理或不出来均可;另一个分支为非RuntimeException,这种异常通常是程序本身没有问题,由于像I/O错误,网络等问题导致的异常,为Checked检查异常,该异常必须处理。
(2)Error类
用于描述程序运行时系统的内部错误,通常比较严重,用于通知用户和和尽量使应用程序安全终止,应用程序不应该尝试去捕获这种异常。通常为JVM虚拟机异常,不可恢复。
二、异常中的关键字
在java中,主要使用try、catch、finally、throw、throws等关键字来处理异常。
1.try、catch、finally
(1)try:用于保护可能产生异常的代码
(2)catch:用于捕获运行时的异常对象
(3)finally:try块中是否有异常都会执行finally语句
只有虚拟机退出的时候才不执行finally语句
public static void main(String[] args) {
//try:用于保护可能产生异常的代码
try {
int num1 = 12;
int num2 = 6;
//运行时如果产生异常,系统会根据异常产生原因,创建异类对象
//代码运行流程会自动跳转至catch块进行异常类型的匹配
int result = num1 / num2;
System.out.printf("%d ÷ %d = %d\n",num1,num2,result);
String str = "duw467";
System.out.println(str.length());
String[] str1 = {};
System.out.println(str1[0]);
//当try块中没有异常的时候
System.out.println("try块结束");
} catch(ArithmeticException ex) {//catch:用于捕获运行时的异常对象
System.out.println("请注意,除数不能为零!");
ex.printStackTrace();//打印当前异常当堆栈信息
}catch(NullPointerException ex) {
System.out.println("请注意,不能访问一个null对象的方法!");
}catch(IllegalFormatConversionException ex) {
System.out.println("请注意格式化占位符的对应关系!");
}catch(Exception ex) {
System.out.println("哎呀,出错了!");// 上述异常类型均未匹配,则使用Exception代表其它异常
return;//退出方法
//System.exit(0); //退出虚拟机
}finally{
//只有虚拟机退出的时候才不执行finally语句
//程序是否有异常都会执行finally语句
System.out.println("finally.....");
}
//在执行此行之前,未执行return语句
System.out.println("程序结束");
}
2.throw、throws
(1)throw关键字:用来抛出方法或代码块中的异常对象,检查异常和非检查异常都可抛出
(2)throws关键字:用在方法定义处,用来标识该方法可能抛出的异常类型列表
public static void main(String[] args) {
//如果方法申明中包含throws + Checked异常类型
//则该方法的调用必须使用try...catch处理
try {
dosth();
donothing();
}catch(FileNotFoundException e) {
e.printStackTrace();
} catch (CountTooLargeException e) {
e.printStackTrace();
}
}
public static void dosth() throws FileNotFoundException{
int a= 23,b=3;
if(a>b) {
//如果抛出的异常对象类型对象是一个No Checked异常,则可以使用throws申明异常类型
//throw new NullPointerException()
//如果抛出的异常对象类型对象是一个Checked异常,则必须使用throws申明异常类型
throw new FileNotFoundException();
}
System.out.println();
}
//自定义异常
public static void donothing() throws CountTooLargeException{
int count = 9990;
if(count>=999) {
//创建并抛出自定义异常对象
//throw new CountTooLargeException(); //使用无参构造方法创建,采用默认提示信息
//使用有参构造方法创建,采用自定义提示信息
throw new CountTooLargeException("抢购商品数量过大");
}
}
三、常见的异常
1.NullPointerException空指针异常
产生原因:调用空对象的方法或属性的时候
public static void main(String[] args) {
String str = null;
System.out.println(str);
//错误1
//System.out.println(str.length());
//错误2
//System.out.println(str.equals("fga4"));
//纠正错误1
if(str != null) {
System.out.println(str.length());
}
//纠正错误2
System.out.println("sga2".equals(str));
//调用构造方法dosth()
int[] array = null;
System.out.println(array.length);
// 方法的动态参数,允许"零传入"
//dosth(12);
}
public static void dosth(int a,int...nums) {
System.out.println("a=" + a);
System.out.println("nums =" + nums.length);
System.out.println("nums =" + Arrays.toString(nums));
}
2.NumberFormatException数字转换异常
产生原因:将非数字内容的字符串转换成数字时出现
public static void main(String[] args) {
String strNum = "6ugd3 l7h2";
//异常
//int number = Integer.parseInt(strNum);
//System.out.println(number*100);
//解决方法
dosth(strNum);
//解决方法
public static void dosth(String param) {
//1.去除首尾空格
param = param.trim();
//2.去除字符串中非数字的内容
StringBuilder sb = new StringBuilder();
for(int i=0;i<param.length();i++) {
//获取每个字符,并判断是否为数字
char c = param.charAt(i);
if(c >= '0' && c <= '9') {
sb.append(c);
}
}
param = sb.toString();
//转换成数字
//String => Integer => int
int number = Integer.parseInt(param);
System.out.println(number*100);
}
3.ClassCastException类型转换异常
产生原因:将引用转换成错误的原类型
public class Java {
public static void main(String[] args) {
Book book = new Book();
Account account = new Account();
dosth(book);
//由于Object是所有类的父类,所以book对象和account对象均可传入
//错误
//dosth(account);
}
//参数为Object父类,传入时,发生向上转型,导致原对象的类型被隐藏
public static void dosth(Object obj) {
//为了调用到原对象的独有方法,必须“向下转型”
Book book = (Book)obj;
book.bookList();
}
}
class Book {
public static void bookList() {
}
}
class Account{
}
4.PraceException转换异常
产生原因:转换的字符串与SimpleDateFormat的日期格式不匹配导致
public static void main(String[] args) {
//获取当前时间
Date date1 = new Date();
//将日期转换成字符串输出
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
String nowstr = sdf.format(date1);
System.out.println("当前日期" + nowstr);
String str = "2020年10月";
//纠正
sdf = new SimpleDateFormat("yyyy年MM月");
Date date2 = sdf.parse(str);
System.out.println("指定日期:" + date2);
}
5.ArrayIndexOutOfBoundsException数组下标越界异常
产生原因:下标超出现有数组的长度范围
public static void main(String[] args) {
int[] num = {1,3,5};
//输入正常下标
System.out.println(num[0]);
System.out.println(num[2]);
//产生数组下标越界异常
//System.out.println(num[-1]);
//System.out.println(num[5]);
}
6.StringIndexOutOfBoundsException字符串下标越界异常
产生原因:字符串的下标越界
public static void main(String[] args) {
String str = "热爱可抵岁月漫长";
String str1 = str.substring(2, 4);
System.out.println(str1);
// 下标范围错误,导致字符串下标越界异常
//String str2 = str.substring(5, 8);
//System.out.println(str2);
//去除字符串中指定下标字符
System.out.println(str.charAt(3));//下标不能越界
}