异常机制

  • 异常机制的框架

  • 基本概念

    异常就是"不正常"的含义,在Java语言中主要指程序运行阶段发生的错误。

    java.lang.Throwable类是所有错误(Error)和异常(Exception)的超类。

    其中Error主要用于描述比较严重无法通过编码解决的错误,如:JVM挂了。

    其中Exception类主要用于描述比较轻微可以编码解决的错误,如:0作为除数。

  • 基本分类

    java.lang.Exception类是所有异常的超类,主要子类有两大类:

    RuntimeException - 运行时异常,也叫作非检测性异常。

    IOException和其它异常 - 其它异常,也叫作检测性异常。

    所谓检测性异常就是指在编译阶段能够被编译器检测出来的异常。
    
  • 注意:

    当程序执行过程中发生异常又没有手动处理时,该异常由Java虚拟机采用默认方式处理,而默认处理方式就是打印:异常名称、异常原因、异常发生的位置,然后终止程序.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 非检测性异常
    int ia = 10;
    int ib = 0;
    System.out.println(ia / ib);

    // 检测性异常
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //sdf.parse("");

    System.out.println("程序结束了!");

异常的避免

在以后的开发中尽量多使用if条件判断来避免异常的发生。

如:

1
2
3
4
5
int ia = 10;
int ib = 0;
if(ib != 0) {
System.out.println(ia / ib);
}

异常的捕获

  • 语法格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try {
    编写所有可能发生异常的语句;
    }
    catch(异常类型 变量名) {
    编写针对该类异常处理的语句;
    }
    ...
    finally { //可以不写
    编写无论是否发生异常都应该执行的语句;
    }
  • 注意事项:

    a.当需要编写多个catch分支时,切记小类型的异常处理放在大类型的上面。懒人的写法: catch(Exception e) {}

    b.finally主要用于进行善后处理,如:关闭打开的文件等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ExceptionFinallyTest {
public static void main(String[] args) {
// 打开了文件...
try {
int ia = 10;
int ib = 0;
System.out.println(ia / ib);
} catch(Exception e) {
e.printStackTrace();
return; // 用于结束当前方法
} finally {
// 关闭文件...
System.out.println("无论是否发生异常都记得来找我哦!");
}

System.out.println("程序结束了!");
}
}

异常的抛出

  • 基本概念

    在某些特殊场合中发生异常无法捕获或者不便于捕获处理时,则可以将该异常转移给该方法的调用者,这个过程就叫异常的抛出。

  • 语法格式

    访问权限 返回值类型 方法名称(形参列表) throws 异常类型1, 异常类型2, … {}

    如:public void show() throws IOException {}

    1
    2
    3
    4
    5
    6
    7
    8
    import java.io.FileInputStream;
    import java.io.IOException;
    public class ExceptionThrowsTest {
    public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("c:/a.txt");
    fis.close();
    }
    }
  • 方法重写的原则

    a.要求方法名相同、参数列表相同、返回值类型相同,jdk1.5开始可以返回子类类型

    b.要求访问权限不能变小,可以相同或者变大

    c.要求不能抛出更大的异常

  • 注意:

    子类重写的方法不可以抛出更大的异常、平级不一样的异常,但可以抛出一样的异常、更小的异常以及不抛出异常。

    1
    2
    3
    4
    5
    6
    import java.io.IOException;
    public class ExceptionOverrideTest {
    public void show() throws IOException {
    System.out.println("父类中的方法!");
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import org.omg.CORBA.portable.ApplicationException;
    public class SubExceptionOverrideTest extends ExceptionOverrideTest {
    @Override
    //public void show() throws ApplicationException { // error
    //public void show() throws Exception { // error
    //public void show() throws IOException { // ok
    //public void show() throws FileNotFoundException { // ok
    public void show() { // ok
    System.out.println("子类中的方法!");
    }
    }

自定义异常

  • 基本概念

    虽然Java官方提供了大量的异常类,但没有提供针对年龄不合理等情况的异常,为了使用这种具备针对性的异常,就需要程序员自定义异常类。

  • 实现流程

    a.自定义xxxException类继承Exception类或者其子类。

    b.提供两个版本的构造方法,一个是无参构造方法,另一个是字符串作为参数的构造

  • 异常的产生

    throw new 异常类型();

    如:throw new NullPointerException();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class AgeException extends Exception {
    /**
    *
    */
    private static final long serialVersionUID = 1L;

    public AgeException() {
    }
    public AgeException(String msg) {
    super(msg);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    public class Person {
    private String name;
    private int age;

    public Person() {
    super();
    }
    public Person(String name, int age) throws AgeException {
    super();
    setName(name);
    setAge(age);
    }

    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) throws AgeException {
    if(age > 0 && age < 150) {
    this.age = age;
    } else {
    //System.out.println("年龄不合理!!!");
    throw new AgeException("年龄不合理!!!");
    }
    }

    @Override
    public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class PersonTest {
    public static void main(String[] args) {
    Person p = null;
    try {
    p = new Person("zhangfei", -30);
    } catch (AgeException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println("p = " + p); // zhangfei 30
    }
    }