Java——异常处理

什么是异常

        非正常的意外事件为异常,即在编译时无法发现错误,运行时才会出现的问题。

Java异常类

        异常类是处理运行时错误的特殊类,每种异常类对应一种特定的运行错误。

        异常类分为:系统定义异常和用户自定义异常。

      系统定义异常

                Java中所有的异常类都是java.lang.Throwable的子类。

                Throwable类有两个直接子类:Error类和Exception类

              Error类

                        Error类描述的是内部系统错误,包括动态链接失败、虚拟机错误等,Java程序不做处理。不由Java程序处理,用户也无法捕获

              Exception类   

                        Exception类描述的是程序和外部环境引起的错误,这些错误能通过程序捕获和处理。Exception出现的原因有:打开文件不存在、网络中断等。

                运行时异常

                        运行时异常是一些可以通过适当处理而避免的异常,在程序中自动由JVM引发,编译时不需要捕获或声明,这类异常是编码时考虑不周产生的,完全可以通过判断来避免的

                非运行时异常

                        非运行时异常通常是由环境因素引起的。Java编译器要求Java程序必须捕获或声明所有的非运行时异常。

Java的异常处理机制

        Java异常处理机制分为三个步骤:

                1、异常的抛出:程序在执行过程中发生异常,Java虚拟机会发现并产生一个异常对象,这个过程就是异常的抛出。可以由系统来抛出异常,也可以由程序员在代码中使用throw强制抛出某种类型的异常。

                2、异常的捕获:出现异常后,Java可以通过try、catch、finally语句来捕获异常,并做相应的处理。

                3、如果没有捕获异常的代码,程序将终止运行。

        try-catch-finally语句

                try和catch实际指:尝试执行这块可能导致异常的代码,如果它执行正常,那么继续执行下面的程序。如果该代码无法执行,捕获该异常并进入catch的代码块运行,由catch代码对它进行处理。最终进入finally语句块中。

                格式:try{//可能产生异常的代码放在此处}

                          catch(异常类名1 异常对象){//在此处处理异常类型1对应的异常}

                          catch(异常类名2 异常对象名){//在此处处理异常类型2对应的异常}

                          finally{//最终的程序出口,往往会写一些清理资源的语句放在此处}

                try-catch-finally语句执行过程

                        1、该语句块把可能产生异常的语句放入try{}语句块中。当try代码块中的语句发生了异常,系统将这个异常发生的代码行号、类别等信息封装到一个对象中,并将这个对象传递给catch代码块。

                        2、在try{}语句后紧跟一个或多个catch块,对try代码块中所产生的异常对象进行处理,每个catch块处理一种可能抛出的特定类型的异常。运行时,如果try{}语句块中产生的异常与某个catch中的异常类型匹配(一场参数类型与实际产生的异常类型一致或者是一个父类),则将停止执行try中的剩余语句,并跳转到catch中执行该catch语句块。

                        3、finally语句是异常处理的最后一步,为异常处理提供一个统一的出口。无论try做指定的程序块中是否抛出异常、抛出哪种异常,finally语句块都要被执行。通常在finally语句中可以进行资源的清楚工作,如:关闭打开的文件,删除文件。

                


public class NullExceptionDemo {
	Bike bike;//bike没有实例化
	public void driveBike() {
		bike.run();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			NullExceptionDemo demo=new NullExceptionDemo();
			demo.driveBike();//会抛出空指针异常
			System.out.println("骑自行车成功");//该处代码不执行
		}catch(NullPointerException e) {
			System.out.println("出现错误"+e.getMessage());
                //getMessage()函数,用于返回有关异常的详细描述性消息,是Throwable类提供的方法,用于得到有关异常事件的信息
                //printStackTrace()函数,输出异常类型、栈层次及出现在程序的位置
		}
		System.out.println("main执行结束");
	}

}
class Bike{
	public void run() {
		System.out.println("开始跑了");
	}
}

异常的抛出及声明

        一个方法中的语句执行时可能生成某种异常,或者语句执行时存在隐患,但是并不确定如何处理或者不想在此方法中处理,则可以将异常抛给调用该方法的程序,此时可以在方法首部声明该异常,表明该方法将不对这些一场进行处理,而是由该方法的调用者负责处理,若调用者仍不处理这些异常,继续抛,知道main方法也无法处理,抛给JVM处理。

        而抛异常用到的是throw和throws

        throws

                [访问修饰符] 返回值类型 方法名 ([形参列表]) throws 异常类列表{...}

        throw

                所有系统定义的异常都可以由系统自动抛出,程序员也可以根据实际情况在程序中抛出一个异常,必须在程序中明确抛出异常。

                throw new 异常类名([参数列表]);  或

                异常类名 对象名=new 异常类名([参数列表]);

                throw 对象名;

public class TestThrow {
	static int divide(int a,int b)throws Exception{
        //divide方法不做异常处理,用throw关键字抛出异常对象给调用者
		if(b==0)
			throw new Exception("除数为零");
		int c=0;
		c=a/b;
		return c;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a=3,b=0,c=0;
		try {
			c=divide(a,b);//divide方法会抛出异常
		}catch(Exception e) {//捕获异常
			System.out.println("调用divide出现错误:"+e.getMessage());
		}
		System.out.println("c="+c);
	}

}

        关于抛出异常,在编写子类继承父类的代码时要注意:一个方法被覆盖时,覆盖它的方法必须抛出跟被覆盖的方法相同的异常或者异常的子类,或者不抛出异常。如果父类抛出多个异常,那么重写(覆盖)的方法必须抛出那些异常的子集,也就是说不能抛出新的异常。

package demo01.test01;

import java.io.IOException;

public class A {
	public void method() throws IOException{	}
}
class B extends A{
	public void method() throws Exception{	}
}//错误,不能抛出IOException的父类
class C extends A{
	public void method() throws IOException, ClassNotFoundException{	}
}//错误,不能抛出新的异常类型
class D extends A{
	public void method(){	}
}//正确,不抛出异常
class E extends A{
	public void method() throws IOException{	}
}//正确,抛出和父类一样的异常
class F{
	public void method() throws IOException,ArithmeticException{	}
}
class G extends F{
	public void method() throws NullPointerException{	}
}//正确,抛出的异常类型是被覆盖方法抛出的异常类型的子集

    自定义异常

            声明的一个新的异常类,这个异常类必须从Java已定义的异常类继承。

            因为Java异常处理机机制只能处理Throwable类或其子类的对象,但在Throwable类的子类中Error说系统内部比较严重的错误,不由程序处理,因此一般由自定义异常类实现。

            Throwable的几个常用方法:1、String getMessage():返回一个异常的描述;

                                                         2、void printStackTrace():把堆栈轨迹输出到指定的输出流;

                                                         3、String getLocalizedMessage():返回一个异常的局部描述

        


public class People {
	private int age;
	private String name;
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) throws AgeException {
		if(age>=300||age<0) {
			throw new AgeException();
		}
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public static void main(String[] args) {
		People pl=new People();
		try {
			pl.setAge(400);
		}catch(AgeException e) {
			System.out.println("给age的赋值错误"+e.getMessage());
		}
	}
}

class AgeException extends Exception{
	public AgeException(){
		//调用父类的构造方法,将“年龄超过范围”赋值给父类的message变量
		super("年龄超过范围");//异常错误信息是固定的
	}
	public AgeException(String message) {
		//调用父类的构造方法,将message传递给父类的message变量
		super(message);//异常错误信息由调用者指定
	}
	
}

         

        

  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值