异常的处理
异常
- 异常(Exception)是程序运行过程中发生的事件,该事件可以中断程序指令的正常执行流程。
Java异常分为两大类:
- 错误(Error)是指JVM系统内部错误,资源耗尽等严重情况;
- 违例(Exception)则是指其他因编程错误或偶然的外在因素导致的一般性问题,例如对负数开平方根、空指针访问、试图读取不存在的文件以及网络连接中断等。
public class TestException{
public static void main(String[] args) {
String friends[]={"Lisa","Bily","Kessy"};
for(int i=0;i<5;i++) {
System.out.println(friends[i]);
}
System.out.println("\nthis is the end");
}
}
程序运行时错误,输出结果:
Lisa
Bily
Kessy
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:3 at TestException.main(TestException.java:5)
class Person{
public int age;
}
public class TestNullPointerException{
public static void main(String[] args)
{
Person p=null;
System.out.println(p.age);
}
}
程序运行时出错,输出结果:
Exception in thread "main" java.lang.NullPointerException at TestNullPointerException.main(TestNullPointerException.java:8)
异常类层次
常见异常
RuntimeException
- 错误的类型转换
- 数组下标越界
- 空指针访问
IOException
- 从一个不存在的文件中读取数据
- 超过文件结尾继续读取
- 连接一个不存在的URL
异常处理机制
Java异常处理的宗旨
- 返回到一个安全和已知的状态
- 能过使用户执行其他的命令
- 如果可能,则保存所有的工作
- 如果有必要,可以推出以避免造成进一步危害
处理机制
- Java 程序执行过程中如出现异常,系统会监测到并自动生成一个相应的异常类对象,然后再将它交给运行时系统
- 运行时系统再寻找相应的代码来处理这一异常,如果java运行时系统找不到可以处理异常的代码,则运行时系统将终止,相应的java程序也将退出
- 程序员通常对错误(Error)无能为力,因而一般只处理违例(Exception).
try{
...//可能产生异常的代码
}catch(ExceptionName1 e){
...//当产生ExceptionName1型异常时的处置措施
}catch(ExceptionName2 e){
...//当产生ExceptionName2型异常时的处置措施
}finally{
...//无条件执行的语句
}
public class Test{
public static void main(String[] args){
String friends[]={"Lisa","Billy","Kessy"};
try{
for(int i=0;i<5;i++){
System.out.println(friends[i]);
}
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("index err");
}
System.out.println("\n this is--------->end");
}
}
输出结果:
Lisa
Bily
Kessy
index err
this is--------->end
使用finally块
public class Test{
public static void main(String[] args){
String friends[]={"Lisa","Billy","Kessy"};
try{
for(int i=0;i<5;i++){
System.out.println(friends[i]);
}
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("index err");
return;
}finally{
System.out.println("in finally block");
}
System.out.println("\n this is--------->end");
}
}
输出结果:
Lisa
Bily
Kessy
index err
in finally block
追踪运行栈信息
public class A{
public void work(int[] a){
String s = this.contain(a,3);
System.out.println("Result: " + s);
}
public String contain(int[] source, int dest){
String result = "no!";
try{
for(int i=0;i<source.length;i++){
if(source[i] == dest)
result = "yes!";
}
}catch(Exception e){
System.out.println("Exception Message: " + e.getMessage());
System.out.println("Stack Trace:");
e.printStackTrace();
result = "error!";
}
return result;
}
}
public class MyTest{
public static void main(String[] args) {
A tst = new A();
tst.work(null);
}
}
输出结果:
异常信息:null
运行栈信息:
java.lang.NullPointerException at A.contain(A.java:9) at A.work(A.java3) at MyTest.main(Mytest.java:4)
Result:error!
输入/输出异常
import java.io.*;
public class TestIOException{
public static void main(String[] args) {
FileInputStream in=new FileInputStream("myfile.txt");
int b;
b = in.read();
while(b!= -1) {
System.out.print((char)b);
b = in.read();
}
in.close();
}
}
TestIOException.java:4: 未报告的异常 java.io.FileNotFoundException;必须对其进行捕捉或声明以便抛出
FileInputStream in=new FileInputStream("myfile.txt");
^
TestIOException.java:6: 未报告的异常 java.io.IOException;必须对其进行捕捉或声明以便抛出
b = in.read();
^
TestIOException.java:9: 未报告的异常 java.io.IOException;必须对其进行捕捉或声明以便抛出
b = in.read();
^
TestIOException.java:11: 未报告的异常 java.io.IOException;必须对其进行捕捉或声明以便抛出
in.close();
^
4 错误
import java.io.*;
public class TestIOException{
public static void main(String[] args) {
try{
FileInputStream in=new FileInputStream("myfile.txt");
int b;
b = in.read();
while(b!= -1) {
System.out.print((char)b);
b = in.read();
}
in.close();
}catch(FileNotFoundException e){
System.out.println("File is missing!");
}catch(IOException e){
e.printStackTrace();
}
System.out.println("It's ok!");
}
}
声明抛弃异常
声明抛弃异常时java中处理违例的第二种方式,如果一个方法中的代码在运行时可能生成某种异常,但在本方法中不必,或者不能确定如何处理异常时,则可以声明抛弃改异常,此时方法中将不对此类异常进行处理,而是由该方法的调用负责处理。
[<修饰符>]<返回值类型><方法名>(<参数列表>)[throws<异常类型>[,<异常类型>]*]{
[<Java语句>]*
}
import java.io.*;
public class TestThrowsException{
public static void main(String[] args){
TestThrowsException t = new TestThrowsException();
try{
t.readFile();
}catch(IOException e){
System.out.println(e);
}
}
public void readFile()throws IOException {
FileInputStream in=new FileInputStream("myfile.txt");
int b;
b = in.read();
while(b!= -1) {
System.out.print((char)b);
b = in.read();
}
in.close();
}
}
重写方法声明抛弃异常
重写方法不允许抛出比被重写方法范围更大的异常类型:
public class A{
public void ma() throws IOException{
...
}
}
public class B1 extends A{
public void ma() throws FileNotFoundException,EOFExceotion{
...
}
}
public class B2 extends A{
public void ma() throws Exception{//非法
...
}
}
人工抛出异常
- Java异常类对象除了在程序运行出错时由系统自动生出抛出之外,也可根据需要人工创建并抛出
IOException e=new IOException();
throw e;
- 被抛出的必须是Throwable或其子类类型的对象,下述语句在编译时会产生语法错误
throw new String("want to throw");
用户自定义异常
java语言针对常见异常状况已事先定义了相应的异常类型,并在程序运行出错时由系统自动创建相应异常对象并进行抛出,捕获和处理,因此一般不需要用户人工抛出异常对象或定义新的异常类型,针对特殊的需要也可以这样做
public class MyException extends Exception {
private int idnumber;
public MyException(String message, int id) {
super(message);
this.idnumber = id;
}
public int getId() {
return idnumber;
}
}
public class TestCustomizingException{
public void regist(int num) throws MyException {
if (num < 0) {
throw new MyException("人数为负值,不合理",3);
}
System.out.println("登记人数:" + num );
}
public void manager() {
try {
regist(-100);
} catch (MyException e) {
System.out.println("登记失败,出错种类"+e.getId());
}
System.out.print("本次登记操作结束");
}
public static void main(String args[]){
new TestCustomizingException().manager();
}
}
输出结果:
登记失败,出错种类3
本次登记操作结束
断言(Assert)
从JDK1.4版本开始,java语言中引入了断言(Assert)机制——允许java开发者在代码中加入一些检查语句,主要用于程序调试目的:
- 断言机制在用户定义的boolean表达式(判断条件)结果为false时抛出一个Error对象,其类型为AssertionError;
- 当我们需要在约定的条件不成立时中断当前操作的话,可以使用断言
- 作为Error的一种,断言失败也不需要捕获处理或者声明抛出,一旦出现了则终止程序、不必进行补救和恢复。
启用和禁用断言
开启断言功能:
Java运行时环境默认设置为关闭断言功能,因此在使用断言以前,需要在运行Java程序时先开启断言
java-ea MyAppClass //或者
java-enableassertions MyAppClass
关闭断言功能:
java-da MyAppClass //或者
java-disableassertions MyAppClass
assert<boolean表达式>;
public class TestAssertion{
public static void main(String[] args){
new TestAssertion().process(-12);
}
public void process(int age){
assert age>=0;
System.out.println("您的年龄:" + age);
//---
}
}
启用断言时输出结果:(使用命令"java-ea TestAssertion"运行程序)
Exception in thread "main" java.lang.AssertionError
at TestAssertion.process(TestAssertion.java:7)
at TestAssertion.main(TestAssertion.java:3)
关闭断言时输出结果:(使用命令"java TestAssertion" 运行程序)
您的年龄:-12
assert<boolean表达式>:<表达式2>;
public class TestAssertion2{
public static void main(String[] args){
new TestAssertion2().process(-12);
}
public void process(int age){
assert age>=0:"年龄超出合理范围!";
System.out.println("您的年龄:" + age);
//---
}
}
启用断言时输出结果:
Exception in thread "main" java.lang.AssertionError: 年龄超出合理范围!
at TestAssertion2.process(TestAssertion2.java:7)
at TestAssertion2.main(TestAssertion2.java:3)
关闭断言时输出结果:
您的年龄:-12