目录
一、异常概念
在java中,将程序执行过程中发生的一些不正常行为称之为“异常”,编译阶段语法错误不是异常!在现实生活的很多app中,出现的错误大多是逻辑上的错误。例如:教务管理登陆系统,当输入错误的用户名和密码时,程序出错,这个错误不是语法错误。
注意点:异常也是类!
二、异常分类
Throwable | java.lang.Throwable类,这个类是Java中所有异常和错误的基类。Throwable下有两个大类那就是异常(Exception)和错误(Error) |
Error | 指的是Java虚拟机无法解决的严重问题,比如:JVM内部错误、资源耗尽。典型代表:StackOverflowError和OutOfMemoryError |
Exception | 异常产生后程序员可以通过代码块进行处理,是程序继续执行 |
IOException | 输入或输出异常 |
CloneNotSupportedException | 不支持克隆异常。当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常 |
ClassNotFoundException | 这意味着JVM已遍历整个类路径,但未找到您尝试引用的类 |
FileNotFoundException | 文件找不到异常。 一是“拒绝访问”, 二是“系统找不到指定路径 |
MalformedURLException | 抛出此异常表示发生了格式错误的URL。 要么在规范字符串中找不到合法的协议,要么无法解析字符串 |
UnknownHostException | java不能联网的异常 |
EOFException | 当输入过程中意外到大文件或流的末尾时,抛出此异常 |
RuntimeException | 是运行时异常,是Java编译器事先不可预见的异常 |
ArithmeticException | 是出现异常的运算条件时,抛出此异常 |
ClassCastException | 类型转换异常 |
IllegalArgumentException | 非法论据异常,也可称为非法形参异常。抛出的异常表明向方法传递了一个不合法或不正确的参数 |
IllegalStateException | 当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向客户端(实际上是缓冲区)输出任何内容 |
IndexOutOfBoundsException | 该异常通常是指数组下标越界异常 |
NoSuchElementException | 表示不存在可操作的元素,在使用迭代器中抛出该异常就表示不存在元素可以迭代。线程访问越界 |
NullPointerException | 空指针异常,最常见的问题就是没有初始化 |
根据异常的发生时机又将异常分成两大类:
受查异常和非受查异常
1.非受查异常(运行时异常):在程序运行时发生的异常,不需要显示进行异常处理的异常都是非受查异常。例如:Error与RunTimeException(蓝色框内)
2.受查异常:在程序编译阶段需要显示进行异常处理的异常类。例如:IOException(IO相关的异常),SQLException(数据库相关的异常)(红色框内)
三、异常处理
1.异常中的关键字
a.try和catch和finally
try{
//所有可能产生异常的代码块
}catch(要捕获的异常类型){
//出现异常之后执行的代码
}finally{
//无论是否产生异常,一定会执行的代码
}
//执行剩下的代码块
catch用法一:
多个异常处理,可以使用多个catch代码块(注意只捕获最上面的异常信息)
public class exception {
public static void main(String[] args) {
try{
System.out.println(10/0);//算数异常
String str=null;
System.out.println(str.length());//空指针异常
}catch(ArithmeticException e){
System.out.println("算数异常,除数不为0");
}catch(NullPointerException e){
System.out.println("算数异常,null没有长度");
}
}
}
该代码有算数异常和空指针异常两处异常,但当代码捕获到算数异常,便不再执行。故而如果多个catch代码块出现了父子关系,一定是子类写在前,父类写在后面。多个代码块只会捕捉一次,走一个catch程序代码块。
catch用法二:
可以用父类异常,处理多个异常的情况。但不推荐,因为此时出现异常不知道具体地产生异常的原因
public class exception {
public static void main(String[] args) {
try{
System.out.println(10/0);//算数异常
String str=null;
System.out.println(str.length());//空指针异常
}catch(Exception e){
System.out.println("发生异常");
}
}
}
finally注意项:
一般资源关闭,网络关闭放到finally代码块中
finally包含return语句,则finally中的返回值会覆盖try和catch中的,finally只进行资源关闭操作不涉及返回值
public class exception {
public static void main(String[] args) {
System.out.println(fun());
}
public static int fun () {//返回2
try {
return 1;
} finally {
return 2;
}
}
}
b.throws和throw
throws:用在方法声明上,明确表示当前方法可能产生的异常,但是当前方法不处理,将异常抛出给调用者(可以抛出多个异常)
throws抛出多个异常,如果有父子关系,只需要声明父类异常就行
public static void fun() throws ArithmeticException,NullPointerException,ClassCastException{
//可以抛出多个异常,可以这几异常都不处理,抛出给调用者,也可以处理一个两个异常,其余抛出给调用者
System.out.println(10/0);
System.out.println("方法结束");
}
throw:用在方法内部,表示人为进行异常对象的产生,一般和自定义异常搭配
(完整代码请见异常登录模拟)http://t.csdn.cn/xYwnx
public void login(String name,String password) throws PasswordException {//抛出了受查异常,受查异常要处理,不然会出错
if(!this.userName.equals(userName)){
throw new UserNameException("用户名错误!");//不显示异常
}
if(!this.password.equals(password)){
//产生异常对象之后需要显示处理
//显示处理有两种。当前方法使用try...catch或者通过throws向上抛出
throw new PasswordException(("密码错误!"));
}
}
2.异常处理流程
a.方法内部产生异常,当前方法就处理
发生异常在当前主方法直接处理
public class exception {
public static void main(String[] args) {
System.out.println("异常处理之前");
try{
System.out.println("异常捕获");
System.out.println(10/0);//由于除0导致的算数异常
}catch(ArithmeticException e){
System.out.println("发生异常,除数不能为0");
}
finally{
System.out.println("无论是否异常处理,都要执行的代码块");
}
}
}
b.方法内部产生异常,不处理异常,将异常对象沿着方法的调用链向上传递
主方法处理异常,剩余代码正常执行
public class exception {
public static void main(String[] args) {
try {
fun();//调用方法
}catch(ArithmeticException e){
System.out.println("发生异常,除数不为0");
}
System.out.println("异常二三事");
}
public static void fun()throws ArithmeticException{//向上抛出异常
System.out.println(10/0);//算数异常
}
}
主方法不处理异常,返回给JVM(java虚拟机),结束代码
public class exception {
public static void main(String[] args) {
fun();//调用方法
System.out.println("异常二三事");
}
public static void fun()throws ArithmeticException{//向上抛出异常
System.out.println(10/0);//算数异常
}
}
四、自定义异常
1.自定义异常概念
Java内置的异常类可以描述在编程时出现的绝大部分出现异常的情况。
除此之外,用户还可以自定义异常。用户自定义异常类,需要继承Exception类或者RuntimeException类,根据受查类型使用关键throws。
2.自定义异常步骤
a.创建自定义异常类。
b.在方法中通过throw关键字抛出异常对象。
c.方法一:在当前抛出异常的方法中处理异常,使用try-catch语句捕获处理异常。方法二:当前方法不处理异常,在方法的声明处通过throws关键字指明要抛出给方法调用者的异常。
ps:受查异常在当前方法不处理时,一定要使用关键字throws抛出,不然程序会报错
d.在出现异常方法的调用者中捕获处理异常。
3.自定义异常完整代码
五、异常其余小贴士
1.printStackTrace()
在命令行打印异常信息在程序中出错的位置及原因,捕捉显示异常行数和信息。
2.System.err.println()
System.err.println("异常产生了红色");优先级低于标准输出System.out.println
public class exception {
public static void main(String[] args) {
System.out.println("异常出现前");
try {
System.out.println(10/0);//程序在执行过程由于除以0出现异常
}catch (ArithmeticException e){//算数异常
System.err.println("红色");
System.out.println("黑色");
e.printStackTrace();
}
}
}