Java 异常处理详解

Java 异常处理

目录

Java 异常处理

1、概述

2、异常分类

3、异常处理方案

3.1 try…catch…finally处理异常

3.2 throws 处理异常 throw 异常处理

3.3 自定义异常

3.4 finally 和 return

4、异常注意事项


1、概述

异常:异常就是Java程序在运行过程中出现的错误。

异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象。其实就是Java对不正常情况进行描述后的对象体现。

2、异常分类

Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类。

Throwable又派生出Error类和Exception类。

(1)错误Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。因此,程序员应该关注Exception为父类的分支下的各种异常类。

(2)异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件可以被Java异常处理机制使用,是异常处理的核心。

总体上我们根据Java对异常的处理要求,将异常类分为2类。

(1)非检查异常(unckecked exception):Error 和 RuntimeException 以及他们的子类。javac在编译时,不会提示和发现这样的异常,不要求在程序处理这些异常。所以如果愿意,我们可以编写代码处理(使用try…catch…finally)这样的异常,也可以不处理。对于这些异常,我们应该修正代码,而不是去通过异常处理器处理 。这样的异常发生的原因多半是代码写的有问题。如除0错误ArithmeticException,错误的强制类型转换错误ClassCastException,数组索引越界ArrayIndexOutOfBoundsException,使用了空对象NullPointerException等等。

(2)检查异常(checked exception):除了Error 和 RuntimeException的其它异常。javac强制要求程序员为这样的异常做预备处理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,否则编译不会通过。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下,而程序员无法干预用户如何使用他编写的程序,于是程序员就应该为这样的异常时刻准备着。如SQLException , IOException,ClassNotFoundException 等。

需要明确的是:检查和非检查是对于javac来说的,这样就很好理解和区分了。
 

3、异常处理方案

3.1 try…catch…finally处理异常

       语法格式:

   try {

          可能出现问题的代码;

    }catch(异常名 变量) {

           针对问题的处理;

   }

        一个样例:

public class ExceptionDemo {
	public static void main(String[] args) {
		int a = 10;
		int b = 0;
		try{
			System.out.println(a / b);
		}catch(Exception e){
			System.out.println("代码出错了哦!");
		}
		System.out.println("over");
	}
}

       运行结果

代码出错了哦!
over

 要是有多个异常呢?

解决方案:

写一个try,多个catch

语法格式

 try{
  可能出现异常的代码 ...
     }catch(异常类名 变量名) {
   捕获异常
     }
 catch(异常类名 变量名) {
捕获异常
   }
在catch语句中不要把父类异常写在最前面,否则后面的异常处理就会出错

public class ExceptionDemo2 {
	public static void main(String[] args) {
		method4();
	}
	public static void method4() {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };
		try {
			System.out.println(a / b);
			System.out.println(arr[3]);
			System.out.println("这里出现了一个异常,你不太清楚是谁,该怎么办呢?");
		} catch (ArithmeticException e) {
			System.out.println("除数不能为0");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("你访问了不该的访问的索引");
		} catch (Exception e) {
			System.out.println("出问题了");
		}
 
		System.out.println("over");
	}
}


 

3.2 throws 处理异常 throw 异常处理

1、throws处理异常:

throws声明:如果一个方法内部的代码会抛出检查异常(checked exception),而方法自己又没有完全处理掉,则javac保证你必须在方法的签名上使用throws关键字声明这些可能抛出的异常,否则编译不通过

throws是另一种处理异常的方式,它不同于try…catch…finally,throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。

采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责。

public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN

{

     //foo内部可以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的子类的异常对象。

}


例子:

public class ExceptionDemo{
	public static void main(String[] args) throws Exception  {
		int a = 10;
		int b = 0;
		System.out.println(a / b);
		System.out.println("over");
	}
}

2、throw 处理异常

throw 异常抛出语句
       throw exceptionObject

       程序员也可以通过throw语句手动显式的抛出一个异常。throw语句的后面必须是一个异常对象

       throw 语句必须写在函数中,执行throw 语句的地方就是一个异常抛出点,它和由JRE自动形成的异常抛出点没有任何差别。

public class ExceptionDemo {
	public static void main(String[] args) {
		try {
			method2();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 
	public static void method2() throws Exception {
		int a = 10;
		int b = 0;
		if (b == 0) {
			throw new ArithmeticException();
		} else {
			System.out.println(a / b);
		}
	}
}

3、throws和throw的区别

     (1)throws用在方法声明后面,跟的是异常类名;可以跟多个异常类名,用逗号隔开;表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
     (2)throw用在方法体内,跟的是异常对象名;只能抛出一个异常对象名;表示抛出异常,由方法体内的语句处理;throw则是抛出了异常,执行throw则一定抛出了某种异常

3.3 自定义异常

如果要自定义异常类,则扩展Exception类即可,因此这样的自定义异常都属于检查异常(checked exception)。

如果要自定义非检查异常,则扩展自RuntimeException。

       样例:

package com.zps.test
/**
    自定义异常通常都是通过继承一个异常类来实现;
    自定义异常的实现是:提供构造方法,异常对象本身是没有实际功能,只是一个有意义的标识提示
    1、Throwable
    2、Exception
    3、RuntimeException
    
    实现用户输入用户名和密码,并校验用户名和密码有无输错,如果输错抛出自定义的错误异常信息,正确后输出用户的信息,
*/
//自定义异常的类的实现就写好
public class MyException extends Exception {
    public MyException(){
        super();
    }
    public MyException(String message){
        super(message);
    }
}
package com.zps.test;
//用户业务类,验证用户输入用户名和密码是否正确,然后返回用户对象信息

public class UserService {
    public User login(String username,String password)throws MyException{ //所以登录方法返回的是用户对象信息;前提是创建User这个类
        if(!"admin".equals(username)){                                    //引用自定义的错误类型
            throw new MyException("用户名错误");  //当有异常抛出时程序就会结束了
        }
        if(!"12345".equals(password)){
            throw new MyException("密码错误");   //当有异常抛出时程序就会结束了
        }
        User user = new User("admin","12345","男",18); //创建对象时如果要传参,那么构造方法里必须是有传参的写法
        return user;
    }

}

3.4 finally 和 return

首先一个不容易理解的事实:在 try块中即便有return,break,continue等改变执行流的语句,finally也会执行

finally:是异常处理的一部分,用于释放资源。

return:返回一个值,方法结束。

public class ExceptionDemo{
	public static void main(String[] args) throws Exception  {
		System.out.println(getInt());
	}
	@SuppressWarnings("finally")
	public static int getInt() {
		int a = 10;
		try {
			System.out.println(a / 0);
			a = 20;
		} catch (ArithmeticException e) {
			a = 30;
			return a;
			/*
			 * return a在程序执行到这一步的时候,这里不是return a而是return 30;这个返回路径就形成了。
			 * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40
			 * 再次回到以前的返回路径,继续走return 30;
			 */
		} finally {
			a = 40;
		}
		return a;
	}
}

结果返回的是30。那么如果finally里含有返回呢?

public class ExceptionDemo{
	public static void main(String[] args) throws Exception  {
		System.out.println(getInt());
	}
	@SuppressWarnings("finally")
	public static int getInt() {
		int a = 10;
		try {
			System.out.println(a / 0);
			a = 20;
		} catch (ArithmeticException e) {
			a = 30;
			return a;
		} finally {
			a = 40;
			return a;//如果这样结果就是40了。
		}
	}
}

结果是40。

注意:

(1)不要在fianlly中使用return。
(2)不要在finally中抛出异常。
(3)减轻finally的任务,不要在finally中做一些其它的事情,finally块仅仅用来释放资源是最合适的。
(4)将尽量将所有的return写在函数的最后面,而不是try … catch … finally中。
 

4、异常注意事项

(1)子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类
(2)如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
(3)如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws.

参考:

https://blog.csdn.net/ShyTan/article/details/81434219

发布了78 篇原创文章 · 获赞 53 · 访问量 8139

猜你喜欢

转载自blog.csdn.net/qqq3117004957/article/details/105249870