JavaSE基础——异常机制
Posted ╭⌒若隐_RowYet——大数据
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE基础——异常机制相关的知识,希望对你有一定的参考价值。
目 录
1. 异常的概念
曾有人说过:“一个程序项目内30%的代码就能实现功能,剩下70%的代码都在检查异常、增加约束……”,为何会如此呢?
- 程序员写的某个功能模块,用户未必会按照你的意愿操作,人的不靠谱性往往导致墨菲定律的发生,如你写一个四则运算,但是用户就是输入一个除数等于0;
- 系统资源的一些缺陷,导致程序员的代码功能无法正常运行,如你去读取一个文件,但是该文件未必存在,或者是空文件,但是你的程序又要求文件不能为空;或者你运行代码时但是系统的磁盘、内存、CPU饱和了,等等……
针对这些影响程序正常运行的意外,我们称之为异常(Exception)
;
2. 小试牛刀——第一个异常
package cn.rowyet.J0004Exception;
public class C0001FirstExcept
private String str;
public static void main(String[] args) throws Exception
int a=0;
int b=1;
System.out.println(b/a);
以上代码就是最好理解的一个异常,俺上小学老师就教导我们,除数不能为0,不然除不尽,因此在Java代码中,如果出现除数为0的代码,就会出现图2.1的异常,那么异常该怎么解决呢?且听后文分晓。
3. 异常的分类
如图3.1,本着面向对象的思想,Java对异常进行了分类,所有的异常根类为java.lang.Throwable
,java.lang.Throwable
派生出两个子类Error
和Exception
,而Exception
又派生出CheckedException
和RuntimeException
,是不是只有这些异常呢?当然不是,根据继承的特性,原则上后续还有无限的子子孙孙异常类,这里是列举不完,博主就展开讲讲这几个最基本的,后续的一场子类你们也就能举一反三了。
3.1 Error
Error(错误)
:是指程序无法处理的严重问题,可能写Java遇到最多的一个问题就是OutOfMemoryError
,即JVM虚拟机所需的内存不足时报错,一般会导致JVM无法继续工作而终止,解决方法就是JVM可用内存调小点,或者加大JVM的所需内存,图3.2是Error
的API;
注意:Error一般和你的程序关系不大,属于JVM内的错误,但是也不是完全没关系哈,程序写的过烂,也可能导致资源滥用而出现Error;
3.2 Exception
Exception(异常)
是程序员能够处理的意外,Exception
类是所有异常类的父类,派生出来的RuntimeException(运行时异常)
和CheckedException(已检查异常,也叫编译时异常)
,也就是说通常Java的异常有分为运行时异常
和编译型异常
;
3.2.1 RuntimeException
RuntimeException(运行时异常)
,顾名思义就是派生于RuntimeException
类的异常类型,如空指针异常(NullPointerException)、数组下标越界异常(ArrayIndexOutOfBoundsException)、类型转换异常(ClassCastException)、算术异常(ArithmeticException)
等。如果显式的声明或捕获将会对程序可读性和运行效率影响很大。 因此由系统自动检测并将它们交给缺省的异常处理程序(用户可不必对其处理)。
这类异常通常是由编程错误导致的,所以在编写程序时,并不要求必须使用异常处理机制来处理这类异常,经常需要通过增加“逻辑处理来避免这些异常”,接下来代码实战一番;
ArithmeticException(运算条件异常)
代码举例:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
int a=0;
int b=1;
System.out.println(b/a); //运算条件异常,除数为0触发异常
运行结果:
解决方法:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
int a=0;
int b=1;
if (a!=0) //加逻辑条件,避免异常
System.out.println(b/a);
NullPointerException(空指针异常)
代码举例:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
String str=null;
System.out.println(str.charAt(2)); //空指针
运行结果:
解决方法:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
String str=null;
if (str!=null) //加逻辑判断
System.out.println(str.charAt(2));
ClassCastException (类型转换异常)
代码举例:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
Animals dog=new Dog();
Cat cat=(Cat) dog; //类型转换
class Animals
class Dog extends Animals
class Cat extends Animals
运行结果:
解决方法:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
Animals dog=new Dog();
Cat cat=(Cat) dog; //类型转换
if (dog instanceof Cat) //加逻辑判别
Cat cat=(Cat) dog;
class Animals
class Dog extends Animals
class Cat extends Animals
ArrayIndexOutOfBoundsException(数组跨界异常)
代码举例:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
int[] intA=new int[5];
System.out.println(intA[5]);
运行结果:
解决方法:
public class C0001FirstExcept
private String str;
public static void main(String[] args) throws Exception
int[] intA=new int[5];
a=5;
if (a<intA.length)
System.out.println(intA[a]);
NumberFormatException(数据格式异常)
代码举例:
public class C0001FirstExcept
public static void main(String[] args) throws Exception
String str2="123456hij";
System.out.println(Integer.parseInt(str2));
运行结果:
解决方法:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class C0001FirstExcept
public static void main(String[] args) throws Exception
String str2="123456hij";
Pattern p=Pattern.compile("^\\\\d+$"); //正则表达式,以数字开头和结尾
Matcher m=p.matcher(str2); //字符串满足正则才可以
if (m.matches())
System.out.println(Integer.parseInt(str2));
3.2.2 CheckedException
那些不属于RuntimeException的异常,统称为Checked Exception(编译型异常)
,如IOException、SQLException
等以及用户自定义的Exception异常。 这类异常在编译时就必须做出处理,否则无法通过编译,即如图3.8会出现红线提示异常;
一般怎么解决呢,就要用到接下的第四章的异常的处理;
4. 异常的处理
4.1 捕获异常try……catch……finally
package cn.rowyet.J0004Exception;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class C0003TryCatch
public static void main(String[] args)
FileReader reader=null;
try
reader=new FileReader("src/test.txt"); //第一个异常文件可能不存在,对应第一个catch
char read = (char)reader.read(); // 第二个异常,字符可能为空
char read2 = (char)reader.read();
System.out.println(read+read2);
catch (FileNotFoundException e) //第一个catch的异常类型要小于等于后续的catch异常
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally //finally一定会执行
try
if(reader!=null)
reader.close();
catch (IOException e)
e.printStackTrace();
以一个读文件的例子来列举下try-catch-finally
的用法要点:
try
语句指定了一段代码,该段代码就是异常捕获并处理的范围。在执行过程中,当任意一条语句产生异常时,就会跳过该条语句中后面的代码,所以不要每句都去try
一遍;try
不能单独存在,必须跟着catch
或者finally
,注意是或哈
,catch
可以有多个,但是finally
只能有一个;- 多个
catch
捕捉出来的异常类,如果这些类型不同且存在继承关系,那么越是父级的类越要往下放,否则会报错,原理也很简单,因为如果你catch
出来的最大父类放在了第一个,那么后续的catch
出来的子类根本发挥不了作用; finally
大多数情况下都是会执行的,不管发没发生异常,除非在finally之前遇到System.exit(0)
或程序被断电、网络等因素终止了;
4.2 声明异常throws
-
当
CheckedException
产生时,不一定立刻处理它,可以再把异常throws
到上级,一直可以抛到JRE
,有点类似甩锅,终究是JRE
抗下了一切; -
方法重写中声明异常原则:子类重写父类方法时,如果父类方法有声明异常,那么子类声明的异常范围不能超过父类声明的范围。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class C0002CheckedException
public static void main(String[] args) throws FileNotFoundException
FileInputStream fileInputStream=new FileInputStream("");
5. 自定义异常
自定义异常的要点:
-
在程序中,可能会遇到JDK提供的任何标准异常类都无法充分描述清楚我们想要表达的问题,或者想要加一些特殊的异常描述,比如中文描述,这种情况下可以创建自己的异常类,即自定义异常类,在开源项目中一般会定义一套服务于该项目的自定义异常;
-
自定义异常类一般只需从Exception类或者它的子类派生一个子类即可。但是如果自定义异常类如果继承Exception类,则为受检查异常,必须对其进行处理;如果不想处理,可以让自定义异常类继承运行时异常RuntimeException类。
-
习惯上,自定义异常类应该包含2个构造器:一个是默认的构造器,另一个是带有详细信息的构造器。
-
不需要定义新类,也可以直接
throw
一个异常包含自定义的描述,只是写项目这样显得很乱不规范,少用;
案例代码:
package cn.rowyet.J0004Exception;
public class C0005SelfException
public static void main(String[] args) throws HeightExcept
Person person = new Person();
person.setName("RowYet");
person.setHeight(500.0); //传一个超过3米的人引发异常
class HeightExcept extends Exception
public HeightExcept();
public HeightExcept(String message)
super(message);
class Person
private String name;
private double height;
public String getName()
return name;
public double getHeight()
return height;
public void setName(String name)
this.name = name;
public void setHeight(double height) throws HeightExcept
if(height>300.0) //判断身高,超过3米则异常
throw new HeightExcept("人的身高不能超过3米");
this.height = height;
运行结果:
当然也可以直接抛出某一个异常类但是自定义抛出的异常内容,但是你抛出的什么类型就要遵循该类型的使用规范,代码如下;
public class C0005SelfException
public static void main(String[] args)
int b=0;
if(b!=0)
System.out.println(1/b);
else
throw new ArithmeticException("除数不能为0");
运行结果;
6. 如何解决异常
实际开发中,异常是家常便饭,而且只有解决的异常越多,你才举例大神越来越近,那么遇到异常该怎么处理呢?
6.1 尝试自己解决
自己动手丰衣足食,第一步是先尝试自己动手,定位异常的位置,查看异常的原因,看看能否自己解决;
6.2 百度、必应、谷歌
百度、必应、谷歌,三大神器,基本上常见的异常都有前人遇见过,针对自己处理不了的异常,可以将异常的关键字去百度、必应、谷歌查找相关网页寻找思路。
6.3 求助同行的大神
以上两步都解决不了,可以尝试求助同行的大神,寻求帮助;
6.4 切忌看不懂,我不会
切忌一看到异常,又是英文就慌了神,我不会,看不懂,逃避就去问别人,这样不但是对自己不负责,也是不尊重他人的成果。
以上是关于JavaSE基础——异常机制的主要内容,如果未能解决你的问题,请参考以下文章