Day22-异常

异常

概念

程序在运行过程中出现的特殊情况,需要处理。防止出现不必要的损失

分类

Throwable:可抛出的,一切错误或异常的父类

  • Error:JVM、硬件、执行逻辑错误,无需动手解决

  • Exception:程序在运行和配置中产生的问题,可处理

    • RuntimeException:运行时异常,可处理,可不处理
    • [CheckedException]:检查时异常,必须处理。java中没有这个异常,它是一类异常的统称

常见的运行时异常

异常 描述
NullPointerException 空指针异常
ArrayIndexOutOfBoundsException 数组下标越界异常
ClassCastException 类型转换异常
NumberFormatException 数字格式化异常
ArithmeticExcepton 算数异常

如下:

/**
 *常见的运行时异常
 */
public class TestException {
	public static void main(String[] args) {
		
		//空指针异常
		String str = null;
		System.out.println(str.equals("Hello"));
		
		//数组下标越界异常
		int [] nums = new int [2];
		nums[2] = 22;
		
		//类转换异常
		Object obj = "hello";
		System.out.println(obj);
		Integer integer = (Integer)obj;
		
		//数字格式化异常
		String str1 = "hello";
		Integer.parseInt(str1);
	}
	
}

import java.util.Scanner;
/**
 * 演示时运行时异常
 */
public class TestException1 {
	public static void main(String[] args) {
		//算数异常 8 0 被除数不为0
		//录入类型不匹配异常 2.2 2.2
		Scanner input = new Scanner(System.in);
		System.out.println("请输入一个数字:");
		int num1 = input.nextInt();
		System.out.println("请输入一个数字:");
		int num2 = input.nextInt();
		int result = num1/num2;
		System.out.println("结果是"+result);
		System.out.println("程序结束");
	}
}

/**
 * Error
 */
public class TestException3 {
	//栈溢出
	public static void main(String[] args) {
		m1();
	}
	public static void m1() {
		System.out.println("HelloWorld");
		m1();
	}
}

异常的产生

自动抛出异常:运行时遇到不符合规范的代码或结果时,会产生异常

手动抛出异常:语法:throw new 异常类型("实际参数");

产生异常的结果:相当于遇到return语句,导致程序因异常而终止

异常的传递

按照方法的调用链反向传递,若始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)并中断程序

import java.util.Scanner;

/**
 *异常的传递
 *	按照方法的调用链反向传递,若始终没有处理异常
 *	最终会由JVM进行默认异常处理(打印堆栈跟踪信息)并中断程序
 */
public class TestException4 {
	public static void main(String[] args) {//JVM虚拟机
		System.out.println("主方法开始");
		divide();
		System.out.println("主方法结束");
		
	}
	public static void divide() {
		//输入 8 0
		Scanner input = new Scanner(System.in);
		System.out.println("请输入一个数字:");
		int num1 = input.nextInt();
		System.out.println("请输入一个数字:");
		int num2 = input.nextInt();
		int result = num1/num2;
		System.out.println("结果是"+result);
		System.out.println("divide方法结束");
	}
}

异常的处理

关键字:try、catch、finally、throw、throws

try:执行可能产生异常的代码 。
catch:捕获异常 ,并处理。
finally:无论是否发生异常,代码总能执行。
throw: 手动抛出异常 。
throws:声明方法可能要抛出的各种异常。

try {
	//可能出现异常的代码
} catch(异常类型 异常类型对象名) {
	//异常处理的相关代码
    //捕获异常,相关处理方法1、自定义处理2、e.printStackTrace()打印栈的跟踪信息3、e.getMessage()获取错误信息
} finally{
    //无论是否发生异常都需要运行的代码,常用于资源释放
}

/**
 *自处理
 *异常处理结果
 *try{可能发生异常的代码}catch(){捕获处理异常}
 *出现异常才走catch代码块,捕获异常
 */

import java.util.Scanner;

public class TestException {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		try {
			//可能发生异常的代码
			System.out.println("请输入一个数字:");
			int num1 = input.nextInt();
			System.out.println("请输入一个数字:");
			int num2 = input.nextInt();
			int result = num1/num2;
			System.out.println("结果是"+result);
		} catch (Exception e) {//new ArithmeticException();
			//Exception e = new ArithmeticException();
			//捕获处理异常
			System.out.println("出现错误");
			
			//打印堆栈跟踪信息
			e.printStackTrace();
			
			//打印错误信息
			System.out.println("错误信息:" + e.getMessage());
		}
		System.out.println("程序结束");
	}
}

import java.util.InputMismatchException;
import java.util.Scanner;
/**
 * 多重捕获,类似if-else
 * 注意,多重捕获每个catch互斥,子类在前,父类在后(一般把Exception放后)
 * 也可以catch(ArithmeticException e | Exception e){}这样写
 */
public class TestException2 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
			try {
				System.out.println("请输入一个数字:");
				int num1 = input.nextInt();
				System.out.println("请输入一个数字:");
				int num2 = input.nextInt();
				int result = num1/num2;
				System.out.println("结果是"+result);
			} catch (ArithmeticException e) {
				System.out.println("分母不能为0");
			}catch (InputMismatchException e) {				
				System.out.println("输入有问题");
			}catch (Exception e) {
				System.out.println("有其他异常问题");				
			}
		System.out.println("程序结束");
	}
}

import java.util.Scanner;

/**
 * 异常处理
 * 	try{可能出现异常的代码}catch{异常处理的相关代码}finaly{无论是否发生异常都需要运行的代码}
 * 	try{}finally{}只做资源释放
 */
public class TestException3 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
//		try {
//			System.out.println("请输入一个数字:");
//			int num1 = input.nextInt();
//			System.out.println("请输入一个数字:");
//			int num2 = input.nextInt();
//			int result = num1/num2;
//			System.out.println("结果是"+result);
//		} catch (Exception e) {
//			System.out.println("有问题...");
//		}finally {
//			//无论是否发生异常都需要运行的代码
//			System.out.println("程序结束");
//		}
		
		try {
			System.out.println("请输入一个数字:");
			int num1 = input.nextInt();
			System.out.println("请输入一个数字:");
			int num2 = input.nextInt();
			int result = num1/num2;
			System.out.println("结果是"+result);
		} finally {
			//无论是否发生异常都需要运行的代码
			System.out.println("程序结束");
		}
		
	}
}

/**
 * finally唯一不执行的情况->退出虚拟机时
 */
import java.util.Scanner;

public class TestException4 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		try {
			System.out.println("请输入一个数字:");
			int num1 = input.nextInt();
			System.out.println("请输入一个数字:");
			int num2 = input.nextInt();
			int result = num1/num2;
			System.out.println("结果是"+result);
			//退出虚拟机,不会执行finally
			System.exit(0);
		} catch (Exception e) {
			System.out.println("有问题...");
			//退出虚拟机,不会执行finally 无论对错,都不会显示程序结束
			System.exit(0);
		}finally {
			System.out.println("程序结束");			
		}
	}
}

import java.util.Scanner;

/**
 * 面试题
 *	try{}、 catch{}、 finally{}中是否可以包含return语句?如果try{}里有一个
 * return语句,那么紧跟在这个try后的finally{}里的代码会不会执行?
 * 
 * 可以包含return语句,但不建议在finally块添加return,会导致运行结果与实际结果不一致。
 * 	如果try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会执行,先走
 * finally代码块再跳回return关键字处
 * 如果try中包含System.exit(0);则不再执行finally代码块
 */
public class TestException5 {
	public static void main(String[] args) {
		System.out.println(devide());
	}
	public static int devide() {
		Scanner input = new Scanner(System.in);
		try {
			System.out.println("请输入一个数字:");
			int num1 = input.nextInt();
			System.out.println("请输入一个数字:");
			int num2 = input.nextInt();
			int result = num1/num2;
			System.out.println("结果是"+result);
			return 0;
		} catch (Exception e) {
			System.out.println("有问题");
			return 1;
		} finally {
			System.out.println("程序结束");
			//return 2;
		}
	}
}

/**
 * 面试题
 * 结果是10,如果finally语句块中的代码为 return num++;结果为11
 * 先try再finally然后执行try代码块里的return
 * 自增运算,num++,先赋值后++
 */
public class TestExpection6 {
	public static void main(String[] args) {
		System.out.println(getNum());
	}
	public static int getNum() {
		int num = 10;
		try {
			return num++;
		} catch (Exception e) {
			return num++;
		}finally {
			num++;//10
			//return num++; 11
		}
	}
}

throws关键字 声明异常

使用原则:底层代码向上声明或者抛出异常,最上层一定要处理异常,否则程序中断

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

/**
 * 如果在一个方法体中抛出了异常,如何通知调用者?
 * throws关键字,声明异常
 */
public class TestThrows {
	public static void main(String[] args) {
		
			try {
				devide();
			} catch (InputMismatchException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ArithmeticException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (RuntimeException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
	}
	//声明异常:告诉调用者可能会出现的异常
	//声明检查时异常,调用者必须进行处理,或抛出
	//声明运行时异常,调用者可处理可不处理
	public static void devide() throws RuntimeException,ArithmeticException,InputMismatchException{
		Scanner input = new Scanner(System.in);
		System.out.println("请输入一个数字:");
		int num1 = input.nextInt();
		System.out.println("请输入一个数字:");
		int num2 = input.nextInt();
		int result = num1/num2;
		System.out.println("结果是"+result);
		System.out.println("程序结束");
	}
}

自定义异常

概念

需继承Exception或Exception的子类,代表特定问题的异常

步骤

1、需继承Exception或Exception的子类,代表特定问题。

2、常用构造方法:

​ 无参构造方法

​ String message参数的构造方法

经验:异常类型名称望文生义,可以在发生特定问题时抛出对应的异常

public class Student {
	private int stuNo;
	private String name;
	private int age;
	private String sex;
	
	public Student() {
		super();
	}
	

	public Student(int stuNo, String name, int age, String sex) throws Exception {
		super();
		this.stuNo = stuNo;
		this.name = name;
		this.setAge(age);
		this.setSex(sex);
	}
	
	public int getStuNo() {
		return stuNo;
	}
	
	public void setStuNo(int stuNo) {
		this.stuNo = stuNo;
	}
	
	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=18;
		//抛出异常
//		throw new Exception("年龄不符合要求"); 需要抛Exception异常
//		throw new RuntimeException("年龄不符合要求");
		if (age > 0 && age <150) {
			this.age = age;			
		}else {
			//抛出异常
			throw new AgeException("年龄不符合要求");
		}
	}
	
	public String getSex() {
		return sex;
	}
	
	public void setSex(String sex){
		if ("男".equals(sex) || "女".equals(sex)) {
			this.sex = sex;			
		}else {
			throw new RuntimeException("只能输入男或女!");
		}
	}
	
	@Override
	public String toString() {
		return "Student [stuNo=" + stuNo + ", name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
}

public class AgeException extends RuntimeException{

	
	public AgeException() {
		super();
	}

	
	public AgeException(String message) {
		super(message);
	}
	
}

public class TestStudent {
	public static void main(String[] args) {
		try {
			Student xm = new Student(1001,"小明",18,"hh");
			System.out.println(xm);
		} catch (Exception e) {
			//用户看的
			System.out.println(e.getMessage());
			
			//程序员看的
			//e.printStackTrace();
		}
	}
}

异常方法重写

带有异常声明的方法重写

方法名、参数列表、返回值类型必须和父类相同
子类的访问修饰符和父类相同或比父类更宽
子类的方法,不能抛出比父类更多、更宽的检查时异常

集合

概念

对象的容器,定义了多个对象进行操作的常用方法。可实现数组的功能

和数组区别

数组长度固定,集合长度不固定

数组可以存储基本类型和引用类型,集合只能存储引用类型

Collection集合

Collection父接口,该体系结构的根接口,代表一组对象,称为”集合“,每个对象都是该集合的”元素“

List接口的特点:有序(有下标),元素可重复

Set接口特点:无序(无下标),元素不可重复(唯一)

迭代器 Iterator

提供了一套对集合进行遍历的统一方法

未完待续...

posted @ 2021-08-02 22:15  CN_Darren  阅读(54)  评论(0)    收藏  举报