Java核心技术基础(一):异常

什么是异常

异常本质上是程序上的错误。包括编译时和运行时的错误。
在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及了,这一部分的错误就是我们程序员关注的焦点。

异常的分类

在这里插入图片描述

  • Throwable有Erro和Exception两个子类。
  • Error是程序无法处理的错误,大多错误与代码编写者无关,而表示代码运行时虚拟机出现的错误,如虚拟机运行错误
    。这些错误不在应用程序的控制和处理能力之内,因此我们在编写程序时不需要关注这类异常。
  • Exception是程序本身可以处理的异常,包括编译时异常和运行时异常。
  • 编译时异常(checked Exception)是编译器要求必须处置的异常,否则编译无法通过:是RuntimeException及其子类之外,其他Exception类的子类,常见IOException、SQLException。
  • 运行时错误(unchecked Exception))是编辑器不强制处置的异常,可以选择性进行捕获处理,也可以不处理,照常编译通过:包含是RuntimeException及其子类.。如NullPointerException、IndexOutOfBoundsException。

在java应用程序中,异常处理机制为:1、捕捉异常 2、抛出异常
在这里插入图片描述

try-catch

对于异常捕捉,有以下四种方式。
(1)、catch块空白 不处理

package 异常;

import java.util.Scanner;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (Exception e) {
			/*
			 * 异常处理:java.util.InputMismatchException
			 * 1、空白 不处理
			 * 
			 */

		}

		System.out.println("结束使用");

	}

}

在这里插入图片描述

(2)、自定义异常处理

package 异常;

import java.util.Scanner;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (Exception e) {

			// 2、自定义异常处理
			System.out.println(new Exception("代码有异常!!") );
		}

		System.out.println("结束使用");

	}

}

在这里插入图片描述
(3)、打印异常信息

package 异常;

import java.util.Scanner;


/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (Exception e) {
			// 制造异常:java.lang.ArithmeticException: / by zero

			//3、打印异常
			//System.out.println(e.toString());// java.lang.ArithmeticException: / by zero
			//System.out.println(e.getMessage());// 输出异常后的内容: / by zero
			//System.out.println(e.getClass());// class java.lang.ArithmeticException
			e.printStackTrace();//向控制台输出异常信息
		}

		System.out.println("结束使用");

	}

}

在这里插入图片描述

上述代码,Exception是ArithmeticException的父类,try处抛出的异常对象被catch捕获用Exception e接收,而ArithmeticException是重写了父类的tosString()方法 因此输出:java.lang.ArithmeticException: / by zero

(4)、抛出异常对象

package 异常;

import java.util.Scanner;


/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (Exception e) {
		
			//4、抛出异常:将异常信息抛给调用者 这里虚拟机调用 了main方法
			//因此虚拟机(1)、向控制台输出异常堆栈信息 (2)、中断程序
			throw e;
		}

		System.out.println("结束使用");

	}

}

在这里插入图片描述
上述代码,将异常信息抛给调用者,这里虚拟机调用 了main方法,因此虚拟机(1)、向控制台输出异常堆栈信息 (2)、中断程序

System.out.println(“结束使用”)不打印的情况

什么时候不执行代码最后的System.out.println(“结束使用”)呢?有以下几种情形:
1)、catch语句块里使用throw e处理时,如上。
2)、catch语句块中没有正常捕获到异常
3)、catch语句块出现return

2)、catch语句块中没有正常捕获到异常

package 异常;

import java.util.InputMismatchException;
import java.util.Scanner;
/*
System.out.println("结束使用")什么时候不执行:
(1)、catch语句块里使用throw e处理时
(2)、catch语句块中没有正常捕获到异常
(3)、catch语句块出现return
 * 
 */

/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (InputMismatchException e) {
			e.printStackTrace();
		}

		System.out.println("结束使用");

	}

}

在这里插入图片描述
上述代码,输入制造的是ArithmeticException异常,而try-catch要捕获的是InputMismatchException异常,因此无法进行正确捕获,程序中止。

3)、catch语句块出现return

package 异常;

import java.util.Scanner;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (Exception e) {
			//3)、catch语句块出现return
			return;
		}
	
		System.out.println("结束使用");

	}

}

在这里插入图片描述

try-catch多分支异常捕获

package 异常;

import java.util.InputMismatchException;
import java.util.Scanner;


/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午6:01:36
*/
/*
 * 多分支捕获异常:catch块应按先子类异常再父类异常的顺序捕获
 */
public class try_catch_finally {

	public static void main(String[] args) {
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (InputMismatchException e) {//捕获非整数输入异常
			System.out.println(new Exception("非整数输入异常"));
		}
		catch (ArithmeticException e) {//捕获分母为0的异常
			System.out.println(new Exception("分母为0的异常"));
		}catch (Exception e) {
			System.out.println(new Exception("其他异常"));
			
		}
		System.out.println("结束使用");
	}

}

try语句块出现异常且catch块捕获到
在这里插入图片描述
在这里插入图片描述

try语句块出现异常且catch块没有正确捕获到

package 异常;

import java.util.InputMismatchException;
import java.util.Scanner;


/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午4:00:12
*/
public class try_catch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}catch (InputMismatchException e) {
			e.printStackTrace();
		}

		System.out.println("结束使用");

	}

}

在这里插入图片描述
可以看到,与前面讲的一样,没有正确捕获,后面的“结束使用”语句不输出。

try-catch-finally

如果希望System.out.println(“结束使用”)执行,则可以使用finally关键字。
(1)、不论是否有异常被捕获,都会执行finally语句

package 异常;

import java.util.InputMismatchException;
import java.util.Scanner;


/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午6:01:36
*/
/*
 * 多分支捕获异常:catch块应按先子类异常再父类异常的顺序捕获
 */
public class try_catch_finally {

	public static void main(String[] args) {
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}

		catch (ArithmeticException e) {//捕获分母为0的异常
			System.out.println(new Exception("分母为0的异常"));
		}

		finally {
			System.out.println("结束使用");
		}
	}

}

1)、发生异常,且catch块未正确捕获
在这里插入图片描述
2)、发生异常,且catch块正确捕获
在这里插入图片描述
可以发现,上述代码不论异常是否被正确捕获,finally关键字的内容都会执行。

3)、使用System.exit(1)中止虚拟机调用

package 异常;

import java.util.InputMismatchException;
import java.util.Scanner;


/**
* @author JohnnyLin
* @version Creation Time:2020年9月22日 下午6:01:36
*/
/*
 * 多分支捕获异常:catch块应按先子类异常再父类异常的顺序捕获
 */
public class try_catch_finally {

	public static void main(String[] args) {
		Scanner reader=new Scanner(System.in);
		System.out.println("---------开始使用计算器----------");
		try {
			
			System.out.println("请输入第一个数");
			int a=reader.nextInt();
			System.out.println("请输入第二个数");
			int b=reader.nextInt();
			System.out.println("商:"+a/b);
		}

		//若想两个异常一起写:ArithmeticException |InputMismatchException e
		catch (ArithmeticException e) {//捕获分母为0的异常
			System.out.println(new Exception("分母为0的异常"));
			System.exit(0);//若正确捕获异常 运行至此处执行System.exit(1)执行使得虚拟机中止便不会执行finally的代码
		}

		finally {
			System.out.println("结束使用");
		}
	}

}

在这里插入图片描述

在这里插入图片描述

throws和throw

上面讲到,对于异常可以使用"throw 一个对象"来抛出,也可以用"throws 可能发生异常的类 "来告知调用者可能会发生的异常,由调用者负责对异常进行处理。

检查时异常

(1)、利用throw制造检查时异常,且使用throws抛出异常

package 异常;

import java.util.Scanner;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 上午8:08:58
* 类说明
*/
public class throw_ {
	public static void devide() throws Exception {
		System.out.println("---------开始使用计算器----------");
		Scanner reader=new Scanner(System.in);
		System.out.println("请输入第一个数");
		int a=reader.nextInt();
		System.out.println("请输入第二个数");
		int b=reader.nextInt();
		if(b==0) {

			//(1)制造检查时异常:除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。
			//这种异常编译器要求强制处置,要么try-cathch,要么在方法名后面抛出。 
			throw new Exception();
		}else {
			System.out.println(a/b);
		}
		System.out.println("结束使用");
		
	}

	public static void main(String[] args) throws Exception {
		
		devide();
		System.out.println("-----------");
	}


}

在这里插入图片描述
上面代码中,devide()方法里 使用throw new Exception()制造了编译时异常,所以devide不得不进行 异常机制 处理,这里用了throws关键字将异常抛给了调用者,当然也可以使用try-catch进行捕获,接着调用者mian()继续使用throws Exception将异常抛给了虚拟机,虚拟机无处可抛了,继续要处理,就向控制太输出堆栈异常信息同时中断程序。

(2)、利用throw制造检查时异常,且使用try-catch捕获异常

package 异常;

import java.util.Scanner;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 上午8:08:58
* 类说明
*/
public class throw_ {
	public static void devide() throws Exception  {
		System.out.println("---------开始使用计算器----------");
		Scanner reader=new Scanner(System.in);
		System.out.println("请输入第一个数");
		int a=reader.nextInt();
		System.out.println("请输入第二个数");
		int b=reader.nextInt();
		if(b==0) {	
			throw new Exception();
		}else {
			System.out.println(a/b);
		}
		System.out.println("结束使用");
		
	}

	public static void main(String[] args) {
		
		try {
			devide();
		} catch (ArithmeticException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("-----------");
	}


}

在这里插入图片描述
可以看到 ,在 main()中使用try-catch进行捕获,print("-----------------------")正常输出。

运行时异常

(1)、利用throw制造运行时异常,且使用throws抛出异常

package 异常;

import java.util.Scanner;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 上午8:08:58
* 类说明
*/
public class throw_ {
	public static void devide() throws ArithmeticException{//throws ArithmeticException 可以不加
		System.out.println("---------开始使用计算器----------");
		Scanner reader=new Scanner(System.in);
		System.out.println("请输入第一个数");
		int a=reader.nextInt();
		System.out.println("请输入第二个数");
		int b=reader.nextInt();
		if(b==0) {
			//制造运行时异常:可以根据需要进行异常机制处理 不强制
			throw new ArithmeticException();
		}else {
			System.out.println(a/b);
		}
		System.out.println("结束使用");
		
	}

	public static void main(String[] args) throws ArithmeticException {
		
		devide();
		System.out.println("-----------");
	}


}

在这里插入图片描述

上面代码,devide()使用throws关键字抛出异常,告知调用者可能发生的异常类型,由调用者负责对异常进行处理。由于主函数main()对devide()没有进行异常的机制的捕获,而是抛给了虚拟机,所以当发生异常时就中断了程序。

(2)、利用throw制造运行时异常,且使用try-catch抛出异常

package 异常;

import java.util.Scanner;

/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 上午8:08:58
* 类说明
*/
public class throw_ {
	public static void devide(){
		System.out.println("---------开始使用计算器----------");
		Scanner reader=new Scanner(System.in);
		System.out.println("请输入第一个数");
		int a=reader.nextInt();
		System.out.println("请输入第二个数");
		int b=reader.nextInt();
		if(b==0) {
			//制造运行时异常:可以根据需要进行异常机制处理 不强制
			throw new ArithmeticException();
		}else {
			System.out.println(a/b);
		}
		System.out.println("结束使用");
		
	}

	public static void main(String[] args) {
		try {
			devide();
		}catch (ArithmeticException e) {
			e.printStackTrace();
			
		}
		System.out.println("-----------");
	}


}


}

在这里插入图片描述

上面代码,使用try catch对devide抛出的异常进行捕获机制管理,所以后面的print("------------------")正常输出。

throws和throw区别:
(1)、声明位置不同:throw在方法内抛出异常对象,而throws在方法体抛出异常类型。
(2)、作用不同:
throw:异常出现的源头
throws:在方法的声明处告诉调用者可能发生的异常,由调用者负责处理

重载、重写方法的异常

方法重载,异常不相关。
方法重写,子类异常类型必须是父类异常的或者父类异常的子类。
在这里插入图片描述

自定义异常:

自定义异常类MyException:

package 异常;
/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 下午1:10:35
*/
public class MyException extends Exception {
	public MyException() {
	}
    public MyException(String message) {
        super(message);
        System.out.println("这是自定义异常类MyException!");
    }
}

测试类:Test

package 异常;
/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 下午1:15:04
* 类说明
*/
public class Test {
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	private String name;
	private int age;
	public Test(String n,int a) throws MyException {
		setName(n);
		if(a<0) {
			throw new MyException("年龄不能设置为负数");
		}else
			setAge(a);
	}
	public static void main(String[] args) throws MyException {
		Test test=new Test("JohnnyLin", -1);

	}

}

在这里插入图片描述
因为MyException继承自Exception,为unexcepted Exception,编译器不通过,需强制处理。

自定义异常:MyException2

package 异常;
/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 下午1:22:21
* 类说明
*/
public class MyException2 extends RuntimeException {
	public MyException2() {
		
	}
	public MyException2(String mesage) {
		super(mesage);
		System.out.println("这是自定义异常MyException2");
	}
}

测试类:Test

package 异常;
/**
* @author JohnnyLin
* @version Creation Time:2020年9月23日 下午1:15:04
* 类说明
*/
public class Test {
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	private String name;
	private int age;
	public Test(String n,int a) {
		setName(n);
		if(a<0) {
			throw new MyException2("年龄不能设置为负数");
		}else
			setAge(a);
	}
	public static void main(String[] args) throws MyException {
		Test test=new Test("JohnnyLin", -1);

	}

}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值