mapengpeng1999@163.com java之异常

异常处理

一、异常及异常分类

在使用计算机语言进行程序开发的过程中,即使技术再牛,代码写再完善,在程序的运行过程中总会遇到一些问题,因为很多问题不是靠代码就能够解决的,比如客户端输入的数据格式有问题,读取某个文件不存在,需要联网的程序网络不畅通等等。我么现在可以给异常下一个定义:在JAVA语言中,将程序执行过程中发生的不正常的情况叫做异常。
Java的异常可以分为两类:

  • Error : 表示错误,Java虚拟机无法解决的严重问题,比如JVM内部的错误,系统资源的耗尽等等严重情况,这种情况下程序一般不写针对性的代码。
  • Exception:表示异常,其他因编程错误或者外在的因素导致的一般性的问题,可以使用针对性的代码进行处理,比如之前遇到过的Exception有空指针异常,数组下标(索引)越界异常,算数异常等。

异常:程序在运行时发生错误,导致程序中断运行。
在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行。

异常机制其实是帮助我们找到程序中的问题,异常的根类是 java.lang.Throwable ,其下有两个子类: java.lang.Error 与 java.lang.Exception ,平常所说的异常指 java.lang.Exception 。

异常的体验:当用户输入0或者用户输入的内容非数字,出现异常

package com.wanbangee.exceptiondemo;
import java.util.Scanner;
public class ExceptionDemo01 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int x = 100;
		System.out.println("请输入被除数:");
		int y = scanner.nextInt();
		System.out.println("结果为:" + (x/y) );
	}
}

对于这些错误,一般有两种解决方案,一种就是遇到错误程序终止运行,另外一种就是程序员在编写程序的时候,就考虑到错误的检测,错误消息的提示,以及错误的处理。我们现在要学习的就是第二种解决方案,错误的处理方式有两种,一种叫做捕获异常,二中叫做抛出异常。捕获异常最理想的时期应该是在程序编译期间,但是有的错误只有在运行时才会发生,比如说被除数为0,数组下标越界等。
这个时候我们可以将异常进行分类:

  • 编译时异常(受检查的异常) ,比如 FileNotFindException,在程序编译期间,提示需要强制处理异常,Exception的所有的子类及其后代类(不包含RuntimeException及其后代)都是编译时异常。
  • 运行时异常(不受检查的异常),比如ArithmeticException,在程序编译期间,没有任何问题,但是在运行过程中可能出现异常导致程序终止运行,不受检查的异常包含RuntimeException这个异常类及其后代类异常都属于运行时异常。
    在这里插入图片描述

二、常见异常

在这里插入图片描述

三、异常的处理

在开发中,对于异常来说,一般都要进行处理,处理异常的方式有两种:

  • 捕获异常,try catch捕获异常
  • 抛出异常,throws不停的往上抛异常,最后交给JVM虚拟机处理

3.1 异常的捕获【抓异常】

在这里插入图片描述

异常捕获一,try catch
捕获异常的语法:
try{
  可能出现异常的代码;
}catch(可能出现的异常对象){
  异常出现之后的处理
}

public static void main(String[] args) {
		try {
			//可能出现异常的代码
			System.out.println("算术异常出现之前");
			System.out.println(1/0);
			System.out.println("算术异常出现之后");
		} catch (ArithmeticException e) {//可能出现的异常的对象
			//出现异常之后的处理
			System.out.println("出现了算术异常");
		}
	}

再次说明:如果try中出现异常,则try中的代码终止运行,并且执行catch中的代码,如果try中没有出现异常,则将try中的代码运行结束,并且不会执行catch中的代码。需要强调的是,catch中可能出现的异常的对象,可以是可能出现的异常对象,也可以是可能出现的异常的父类或者祖先类对象,异常的最高父类就是Exception,表示可以处理所有可能出现的异常,在开发中,经常使用Exception处理异常。

异常捕获二,一try 多catch

一try 多catch,如果可能出现的异常有多种,而且不想使用Exception处理所有的异常,而是单个异常单个catch,这个时候就可以使用多重的catch。

try{
  可能出现异常的代码;
}catch(可能出现的异常对象1){
  出现异常对象1的处理
}catch(可能出现的异常对象2){
  出现异常对象2的处理
}catch(可能出现的异常对象3){
  出现异常对象3的处理
}

	public static void main(String[] args) {
		try {
			//可能出现异常的代码
			System.out.println("算术异常出现之前");
			System.out.println(1/1);
			System.out.println("算术异常出现之后");
			
			System.out.println("数组下标越界异常出现之前");
			int arr[] = new int[] {1,2,3};
			System.out.println(arr[5]);
			System.out.println("数组下标越界异常出现之后");
			
		} catch (ArithmeticException e) {//可能出现的异常的对象
			//出现异常之后的处理
			System.out.println("出现了算术异常");
		} catch (IndexOutOfBoundsException e) {//可能出现的异常的对象
			System.out.println("出现了数组下标越界异常");
		}
		
	}

在开发中一般都是用最高的异常父类Exception处理所有的异常。

还有一种情况:比如try中可能出现多种异常,而两种异常我希望单独的使用catch处理,而其他的异常统统交给统一的父类Exception处理,使用Exception的catch就必须放在最后。

	public static void main(String[] args) {
		try {
			//可能出现异常的代码
			System.out.println("算术异常出现之前");
			System.out.println(1/1);
			System.out.println("算术异常出现之后");
			
			System.out.println("数组下标越界异常出现之前");
			int arr[] = new int[] {1,2,3};
			System.out.println(arr[5]);
			System.out.println("数组下标越界异常出现之后");
			
			System.out.println("空指针异常出现之前");
			Person p = null;
			System.out.println(p.getName());
			System.out.println("空指针异常出现之后");
			
		}  catch (ArithmeticException e) {//可能出现的异常的对象
			//出现异常之后的处理
			System.out.println("出现了算术异常");
		} catch (IndexOutOfBoundsException e) {//可能出现的异常的对象
			System.out.println("出现了数组下标越界异常");
		} catch(Exception e) {
			System.out.println("出现了非算术异常及非越界异常");
		}
		
	}
异常捕获三,try catch finally

try catch finally,在实际开发中,比如IO操作,数据库操作,程序运行不管有没有出现异常,我们都必须关闭IO流和数据库连接。这就意味着不管有没有出现异常,都要执行关闭操作。这个时候就可以使用try catch finally。

try{
  可能出现异常的代码;
}catch(可能出现的异常对象){
  异常出现之后的处理
} finally{
  不管有没有异常都会执行的代码(一般进行资源的释放)
}

	public static void main(String[] args) {
		try {
			//可能出现异常的代码
			System.out.println("算术异常出现之前");
			System.out.println(1/1);
			System.out.println("算术异常出现之后");
			
			/*
			 * System.out.println("数组下标越界异常出现之前"); int arr[] = new int[] {1,2,3};
			 * System.out.println(arr[5]); System.out.println("数组下标越界异常出现之后");
			 * 
			 * System.out.println("空指针异常出现之前"); Person p = null;
			 * System.out.println(p.getName()); System.out.println("空指针异常出现之后");
			 */
		}  catch (ArithmeticException e) {//可能出现的异常的对象
			//出现异常之后的处理
			System.out.println("出现了算术异常");
		} catch (IndexOutOfBoundsException e) {//可能出现的异常的对象
			System.out.println("出现了数组下标越界异常");
		} catch(Exception e) {
			System.out.println("出现了非算术异常及非越界异常");
		} finally {
			System.out.println("不管有没有异常都会执行的代码");
		}
		
	}

在开发中,经常在catch中,使用一个方法,来进行异常的打印:public void printStackTrace(),打印异常的方法一般放在catch后,出现异常后怎么处理,打印异常,还有就是syso输出异常提示语句,这个方法在Throwable类中定义,所有的异常的对象都可以调用方法。
catch(Exception e) {
e.printStackTrace();
System.out.println(“出现了什么什么异常”);
}

	public static void main(String[] args) {
		try {
			//可能出现异常的代码
			System.out.println("算术异常出现之前");
			System.out.println(1/0);
			System.out.println("算术异常出现之后");
			
		} catch (ArithmeticException e) {//可能出现的异常的对象
			//出现异常之后的处理
			System.out.println(出现了算术异常);
			e.printStackTrace();
			//打印异常,开发中使用较多,可以更快速的找到异常出现的位置
		} finally {
			System.out.println("不管有没有异常都会执行的代码");
		}
		
	}

3.2 异常的抛出【抛异常】

异常的抛出使用throws关键字,抛出的异常有两种类型:
- Java中已经定义的异常
- 自定义异常
通过throws 关键字,表示向上抛出异常,意思就是本方法中不处理抛出的异常类型,而是交给调用此方法的代码中处理(要么抛要么抓,如果main方法继续向上抛的话,表示将异常交给Java虚拟机处理)。

在使用throws关键字抛出异常的时候,如果此方法中有多个异常,只要抛出这些异常的共同的父类异常,则就可以抛出此方法中可能出现的所有的异常了。在实际开发中,不管是何种异常,都可以使用throws Exception,表示抛出所有的异常。

package com.wanbangee.exceptiondemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class ExceptionDemo04 {
	/**
	 * 	如果main方法中抛出异常,表示交给Java虚拟机处理
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		readFile();
	}
	/**
	 * 	
	 * @throws IOException 抛出的是IO异常
	 */
	public static void readFile() throws IOException {
		// 编译时异常采用异常处理中的 抛 的方案
		File file = new File("C:\\Users\\Administrator\\Desktop\\新1.txt");
		InputStream in = new FileInputStream(file);
		byte b[] = new byte[(int) file.length()];
		in.read(b);// 将流中的内容读取到字节数组中
		String s = new String(b);
		System.out.println("读取的内容:" + s);
		in.close();
	}
}

自定义异常

自定义异常:在开发中使用并不多,但是在以后自己去开发属于一个自己的框架,要定义一些自己的异常。
自定义异常在开发中只需编写一个异常类,继承异常就可以了。

package com.wanbangee.exteption;
public class ExceptionDemo03{
	public static void main(String[] args) {
		throw new MyException("自定义的异常"); 
		//通过throw关键字调用自定义的异常
	}
}
//自定义异常,extends最高异常父类Exception也行
class MyException extends RuntimeException{
	public MyException(String message) {
		super(message);//调用父类的构造方法
	}
}

自定义异常对象使用throw关键字调用,对于throw关键字和throws关键一定要区别好来。throws关键字用于方法声明处抛异常。

try{ 
throw new  RuntimeException(); //自定义异常,可能出现异常的代码
}catch(Exception e){ //定义异常类型对象
System.out.println("出现了异常");
//出现异常后的处理,输出打印异常信息提示
e.printStackTrace();//打印异常
}finally{
不管有没有异常都会执行的代码(一般进行资源的释放)
}

总结:

  1. 程序在编译或者运行时出现的问题,我们叫做异常,分为两类
  • 错误
  • 异常
    Throwable是异常和错误的最高父类。
    2.异常是指程序编译或者运行时出现的错误,导致程序中断,分为两类:
  • 编译时异常:程序编译不通过,编译时异常又称为受检查的异常
  • 运行时异常:程序编译通过,运行时才出现的异常,运行时异常又称为不受检查的异常
    Exception是异常的最高父类
    3.异常的捕获使用try catch代码块,try中声明可能出现异常的代码,catch中表示异常出现之后的处理,try中如果出现异常则中断程序运行,执行catch的语句,try中如果没有出现异常,则将try中的代码执行完成,并且不执行catch中的语句。
    4.可以使用多重catch处理不同类型的异常,如果多重catch中存在有异常最高父类Exception,则放在最后的catch中
    5.可以使用try catch finally来处理异常,其中finally块中的语句表示不管有没有出现异常,都会执行的代码
    6.throws关键字用于方法声明处,表示本方法不处理异常,交个调用本方法的程序处理异常,如果main方法也使用throws关键字抛出异常,则最终异常交给JVM处理
    7.throw关键字用于声明自定义异常,在开发中,使用比较少。

练习:
键盘输入一个int类型的整数。如果录入整数过大,给以提示“录入整数过大,请重新输入一个整数”;如果录入的是小数,给提示“录入的是小数,请重新输入一个整数”;如果录入的其他字符,请提示“录入的是非法字符,请输入一个整数”。

package com.wanbangee.exteption;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;

public class ExceptionDemo04 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		do {
			System.out.print("请输入数字:");
			String line = sc.next();//接收输入的一行内容
			try {
				int input = Integer.parseInt(line);
				//如果转换没有出现异常,则表示输入的是整数
				System.out.println("您输入的数字是整数");
				break;
			} catch (Exception e) {
				//BigInteger 超出了的Integer范围的整数
				try {
					new BigInteger(line);//转换成大整数,表示超出了整数范围
					System.out.println("您输入的内容是大整数,超出了范围");
				} catch (Exception e2) {
					try {
						new BigDecimal(line);//表示一个大数字
						System.out.println("您输入的是大数字,超出了范围");
					} catch (Exception e3) {
						System.out.println("您输入的是非法内容");
					}
				}
			}
		}while(true);
	}
}

在这里插入图片描述
Exception又包含了运行时异常(RuntimeException, 又叫非检查异常)和编译时异常(又叫检查异常)

  • Error是程序无法处理了, 如果OutOfMemoryError、OutOfMemoryError等等, 这些异常发生时, java虚拟机一般会终止线程。
  • 编译时异常(受检查的异常) ,比如 FileNotFindException,在程序编译期间,提示需要强制处理异常,Exception的所有的子类及其后代类(不包含RuntimeException及其后代)都是编译时异常。
  • 运行时异常(不受检查的异常),比如ArithmeticException,在程序编译期间,没有任何问题,但是在运行过程中可能出现异常导致程序终止运行,不受检查的异常包含RuntimeException这个异常类及其后代类异常都属于运行时异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值