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
提供了一套对集合进行遍历的统一方法
未完待续...

浙公网安备 33010602011771号