Java异常简单理解

Java异常

  1. 什么是异常
  2. 如何处理异常
  • try-catch-finally
  • throw
  • throws
  • 自定义异常
  • 异常链

什么是异常

  • 错误在外面编写程序的过程中经常发生,包括编译期间和运行期间的错误。

编译期间的错误:

  • 括号没有正常的配对
  • 语句结束后少写了分号;
  • 关键字编写错误

运行期间的错误:

使用空的对象引用调用方法
String str = null;
System.out.println(str.length());
数组访问时下标越界
int[] ary={
    
    1,2,3};
for(int i=0;i<=3;i++){
    
    
	System.out.println(ary[i]);
}
算数运算时除数为0
int one=12;
int two=0;
System.out.println(one/two);
类型转换时无法正常转型
class Animal {
    
    
}
class Dog extends Animal {
    
    
}
class Cat extends Animal {
    
    
}
public class Test {
    
    
	public static void main(String[] args){
    
    
		Animal a1 = new Dog();
		Animal a2 = new Cat();
		Dog d1 = (Dog)a1;
		Dog d2 = (Dog)a2;
	}
}

在程序运行过程中,意外发生的情况,背离我们程序本身的意图的表现,都可以理解为异常。

异常分类

Throwable异常分为两种Error、Exception
Error

  • 虚拟机错误 VirtualMachineError
  • 内存溢出 OutOfMemoryError
  • 线程死锁 ThreadDeath

它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的情况

Exception
Exception是程序本身可以处理的异常。异常处理通常指针对这种类型异常的处理。

  • RuntimeException
  • 检查异常 Checked Exception
  • IO异常 IOException
  • SQL异常 SQLException

RuntimeException

  • 空指针异常 NullPointerException
  • 数组下标越界异常 ArrayIndexOutOfBoundsException
  • 算数异常 ArithmeticException
  • 类型转换异常 ClassCastException

异常处理分类

  • 在Java应用程序中,异常处理机制为:抛出异常、捕获异常

异常对象

  • 异常类型
  • 异常出现的时候的程序状态

捕获异常

  • 对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。
    Java规定:
  • 对于可査异常必须捕捉、或者声明抛出
  • 允许忽略不可査的RuntimeException(含子类)和Error(含子类)。

异常处理

捕获异常

  • 通过5个关键字来实现:try、catch、finall、throw、throws
  • try 执行可能产生异常的代码
  • catch 捕获异常
  • finally 无论是否发生异常代码总能执行

声明异常

  • throws 声明可能要抛出的异常

抛出异常

  • 手动抛出异常

try-catch-finall

public void method(){
    
    
	try	{
    
    
		//代码段1
		//产生异常的代码段2
	}catch(异常类型 ex) {
    
    
		// 对异常进行处理的代码段3
	}finally{
    
    
		// 代码段4
	}
}

try块后可接零个或多个catch块,如果没有catch块,则必须跟一个finall块。

public class TryDemoOne {
    
    
	public static void main(String[] args) {
    
    
		// 要求:定义两个整数,输出两数之商
		int one = 12;
		int two = 2;
		System.out.println("one和two的商是:" + (one/two));
		
		//要求:定义两个整数,接受用户的键盘输入,输出两数之商
		Scanner input = new Scanner(System.in);
		System.out.println("====运算开始====");
		System.out.println("请输入第一个整数:");
		try{
    
    
			int one = input.nextInt();
			System.out.println("请输入第二个整数:");
			int two = input.nextInt();
			System.out.println("one和two的商是:" + (one/two));
			
		}catch(Exception e) {
    
    
			e.printStackTrace();//打印错误的堆栈信息
			System.out.println("程序出错啦~~");
		}finally{
    
    
			System.out.println("====运算结束====");
		}
		
	}
}

终止finally执行的方法

public class TryDemoOne {
    
    
	public static void main(String[] args) {
    
    
		// 要求:定义两个整数,输出两数之商
		int one = 12;
		int two = 2;
		System.out.println("one和two的商是:" + (one/two));
		
		//要求:定义两个整数,接受用户的键盘输入,输出两数之商
		Scanner input = new Scanner(System.in);
		System.out.println("====运算开始====");
		System.out.println("请输入第一个整数:");
		try{
    
    
			int one = input.nextInt();
			System.out.println("请输入第二个整数:");
			int two = input.nextInt();
			System.out.println("one和two的商是:" + (one/two));
			
		}catch(ArithmeticException e) {
    
    
			System.exit(1);
			System.out.println("除数不允许为零");
			e.printStackTrace();//打印错误的堆栈信息
		}catch(InputMismatchException e) {
    
    
			System.out.println("请输入整数");
			e.printStackTrace();
		}finally{
    
    
			System.out.println("====运算结束====");
		}
		
	}
}

return关键字在异常处理中的作用

public class TryDemoOne {
    
    
	public static void main(String[] args) {
    
    
		int result = test();
		System.out.println("one和two的商是: "+ result);		
	}
	
	public static int test() {
    
    
		Scanner input = new Scanner(System.in);
		System.out.println("====运算开始====");
		try{
    
    
			System.out.print("请输入第一个整数:");
			int one = input.nextInt();
			System.out.print("请输入第二个整数:");
			int two = input.nextInt();
			return one/two;
		}catch(ArithmeticException e){
    
    
			System.out.println("除数不允许为零");
			return 0;
		}finally{
    
    
			System.out.println("=====运算结束=====");
			return -1000000;
		}
	}
}
//无论怎么运作,最后都是强制执行finally的return。
//如果将finally的return屏蔽掉,就会正常执行。

使用throws声明异常类型

throw & throws

  • 可以通过throws声明将要抛出何种类型的异常,通过throw将产生的异常抛出。

  • throw语句用在方法定义时声明该方法该方法要抛出的异常类型。

public void method() throws Exception1,Exception2,..,ExceptionN {
    
    
	// 可能产生异常的代码
}
  • 当方法抛出异常列表中的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。
public class TryDemoOne {
    
    
	public static void main(String[] args) {
    
    
		try {
    
    
			int result = test();
			System.out.println("one和two的商是: "+ result);		
		} catch (ArithmeticException e) {
    
    
			System.out.println("除数不允许为零");
			e.printStackTrace();
		}
	}
	
	public static int test() throws ArithmeticException{
    
    
		Scanner input = new Scanner(System.in);
		System.out.println("====运算开始====");
			System.out.print("请输入第一个整数:");
			int one = input.nextInt();
			System.out.print("请输入第二个整数:");
			int two = input.nextInt();
			System.out.println("=====运算结束=====");
			return one/two;
	}
}

如果你在处理的时候会出现多种异常的话可以这样做。

第一种方案


public class TryDemoOne {
    
    
	public static void main(String[] args) {
    
    
		try {
    
    
			int result = test();
			System.out.println("one和two的商是: "+ result);		
		} catch (ArithmeticException e) {
    
    
			System.out.println("除数不允许为零");
			e.printStackTrace();
		} catch (InputMismatchException e) {
    
    
			System.out.println("请输入整数");
			e.printStackTrace();
		}
	}
	
	/*通过throws抛出异常时,针对可能出现的多种异常情况,解决方案:
	1、throws后面接多个异常类型,中间用逗号分隔*/
	public static int test() throws ArithmeticException,InputMismatchException{
    
    
		Scanner input = new Scanner(System.in);
		System.out.println("====运算开始====");
			System.out.print("请输入第一个整数:");
			int one = input.nextInt();
			System.out.print("请输入第二个整数:");
			int two = input.nextInt();
			System.out.println("=====运算结束=====");
			return one/two;
	}
}

第二种方案

public class TryDemoOne {
    
    
	public static void main(String[] args) {
    
    
		try{
    
    
			int result = test();
			System.out.println("one和two的商是:" + result);
		} catch(ArithmeticException e){
    
    
			
		} catch(InputMismatchException e){
    
    
			
		} catch(Exception e){
    
    
			
		}
		test();
	}
	
	/*通过throws抛出异常时,针对可能出现的多种异常情况,解决方案:
	1、throws后面接多个异常类型,中间用逗号分隔
	2、throws后面接Exception
	/**
	* 测试接受数据相除结果的方法
	**/

	public static int test() throws ArithmeticException,InputMismatchException{
    
    
		Scanner input = new Scanner(System.in);
		System.out.println("====运算开始====");
			System.out.print("请输入第一个整数:");
			int one = input.nextInt();
			System.out.print("请输入第二个整数:");
			int two = input.nextInt();
			System.out.println("=====运算结束=====");
			return one/two;
	}
}

使用throw抛出异常对象

  • throw用来抛出一个异常
  • 例如:throw new IOException();
  • throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象。
  • 例如:throw new String(“出错啦”); 是错误的

在这里插入图片描述
throw

  1. 规避可能出现的风险
  2. 完成一些程序的逻辑

举个例子:
假如我开了一家宾馆,这家宾馆有一些特殊规定,就是未满18岁的未成年人必须有监护人陪伴,不然不得入住。

方案一:throw抛出异常对象的处理方案,通过try…catch包含throw语句–自己抛出自己处理

public class TryDemoFour {
    
    

	public static void main(String[] args){
    
    
		testAge();
	}

	//描述酒店的入住规则:限定年龄,18岁以下,80岁以上的住客必须由亲友陪同
	public static void testAge() {
    
    

		try {
    
    
			System.out.println("请输入年龄: ");
		Scanner input = new Scanner(System.in);
		int age = input.nextInt();
		if(age<18 || age>80) {
    
    
			throw new Exception("18岁以下,80岁以上的住客必须由亲友陪同");
		}else{
    
    
			System.out.println("欢迎入住本酒店");
		}
	} catch (Exception e) {
    
    
		e.printStackTrace();
	}	
	}
}

//如果我们输入q的话就会抛出格式异常

第二种方案:通过throws在方法所声明出抛出异常类型–谁调用谁处理–调用者可以自己处理,也可以继续向上抛

public class TryDemoFour {
    
    

public static void main(String[] args){
    
    
	try{
    
    
		testAge();
	} catch (Exception e) {
    
    
		e.printStackTrace();
	}
}

public static void testAge() throws Exception{
    
    

		System.out.println("请输入年龄: ");
		Scanner input = new Scanner(System.in);
		int age = input.nextInt();
		if(age<18 || age>80) {
    
    
			throw new Exception("18岁以下,80岁以上的住客必须由亲友陪同");
		}else{
    
    
			System.out.println("欢迎入住本酒店");
		}
	}	
}

自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。
  • 也可以通过自定义异常描述特定业务产生的异常类型。
  • 所谓自定义异常,就是定义一个类,去继承Throwable类或者它的子类。
public class TryDemoFour {
    
    
	public static void main(String[] args){
    
    
		try {
    
    
			testAge();
		} catch(HotelAgeException e) {
    
    
			System.out.println(e.getMessage());
			System.out.println("酒店前台工作人员不允许办理入住登记");
		} catch(Exception e){
    
    
			e.printStackTrace();
		}
	}

public static void testAge() throws HotelAgeException {
    
    
	System.out.println("请输入年龄: ");
	Scanner input = new Scanner(System.in);
	int age = input.nextInt();
	if (age < 18 || age > 80) {
    
    
		throw new HotelAgeException();
	} else {
    
    
		System.out.println("欢迎入住本酒店");
	}
}
}


package com.imooc.test;

public class HoteAgeException extends Exception {
    
    
	public HotelAgeException(){
    
    
		super("18岁以下,80岁以上的住宿必须由亲友陪同");
	}

} 

异常链

  • 有时候我们会捕获一个异常后在抛出另一个异常
public class TryDemoFive {
    
    

	public static void main(String[] args) {
    
    
		testThree();
	}
	
	public static void testOne() throws HoteAgeException {
    
    
		throw new HotelAgeException();
	}

	public static void testTwo() throws Exception {
    
    
	try {
    
    
		testOne();
	} catch (HotelAgeException e) {
    
    
		throw new Exception("我是新产生的异常1",e);
	}
}

	public static void testThree() throws Exception{
    
    
		try {
    
    
			testTwo();
		} catch (Exception e) {
    
    
			Exception e1 = new Exception("我是新产生的异常2");
			e1.initCouse(e);
			throw e1;
			//throw new Exception("我是新产生的异常2",e);
		}
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_45647118/article/details/115078735