1.什么是异常
异常是在程序中导致程序中断运行的一种指令流。
例如:
x和y接收的是一个整数,如果用户输入一个字符,程序就会出现异常。
public class Demo {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int x=scanner.nextInt();
int y=scanner.nextInt();
int a=10;
int b=0;
int z=a/b;
}
}
运行结果:
2.异常的种类(Exception)
- 受检异常
当程序写好后,编译器会自动对所写代码进行检测,如果有问题,代码将会飘红线。
例如:SQLException,IOException,ClassNotFoundException等 - 非受检异常
编译器无法对所写代码异常进行检测,程序将在会在运行时报错。
例如:NullPointException,ArithmethicException,ClassCastException,ArrayIndexOutOfBundException等
两种异常的处理方式相同
3.异常处理
语法
try{
// 有可能发生异常的代码段
}catch(异常类型1 对象名1){
// 异常的处理操作
}catch(异常类型2 对象名2){
// 异常的处理操作
} …
finally{
// 异常的统一出口
}
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
test1();
test2();
test2();
System.out.print("程序执行完毕");
}
// 异常处理格式1
public static void test1(){
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个数字");
int x = scanner.nextInt();
System.out.println("请输入一个数字");
int y = scanner.nextInt();
System.out.println("计算结果为"+(x / y));
}catch (InputMismatchException e){
System.out.println("你输入的不是数字!");
test1();
}catch(ArithmeticException e){
System.out.println("除数不能为0");
test1();
}
}
// 异常处理格式2
public static void test2(){
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个数字");
int x = scanner.nextInt();
System.out.println("请输入一个数字");
int y = scanner.nextInt();
System.out.println("计算结果为"+(x / y));
}catch (InputMismatchException | ArithmeticException e){
System.out.println("你输入有误!");
test2();
}
}
// 异常处理格式3(使用父类,扩大异常形态形态的范围)
public static void test3(){
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个数字");
int x = scanner.nextInt();
System.out.println("请输入一个数字");
int y = scanner.nextInt();
System.out.println("计算结果为"+(x / y));
}catch (RuntimeException e){
System.out.println("你输入有误!");
test3();
}
}
//异常处理格式4(使用finally)
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个数字");
int x = scanner.nextInt();
System.out.println("请输入一个数字");
int y = scanner.nextInt();
System.out.println("计算结果为"+(x / y));
}catch (RuntimeException e){
System.out.println("你输入有误!");
test4();
}finally{
//finally作为异常统一处理的出口必然执行
//无论是否发生异常,finally必然执行
//及时没有发生异常,try中有return语句,finally仍然会执行
System.out.println("finally最终执行了");
}
}
}
4.关键词 finally
- finally作为异常统一处理的出口必然执行
- 无论是否发生异常,finally必然执行
- 及时没有发生异常,try中有return语句,finally仍然会执行
1.引用类型
在try代码块中,return返还前,引用对象s的地址会被复制备份,然后执行finally代码块,修改了对象s中的变量studentid,然后根据备份的地址返还Student类型的对象。
public class Demo2 {
public static void main(String[] args){
Student s=test();
System.out.println("学生的学生号是:"+s.studentid);
}
public static Student test(){
Student s = new Student();
try{
s.studentid=1000;
return s;
}catch(Exception e){
System.out.println("抛出异常");
}finally{
s.studentid=10;
}
return s;
}
static class Student{
int studentid;
}
}
运行结果:
2.基本数据类型
在try代码块中,return返还前,基本数据类型变量student的值1000会被被复制备份,然后执行finally代码块,修改了原有变量studentid的值变成了10,然后根据备份值返还变量student的值,仍然是1000。
public class Demo3 {
public static void main(String[] args){
int studentid=test();
System.out.println("学生的学生号是:"+studentid);
}
public static int test(){
int studentid=1000;
try{
return studentid;
}catch(Exception e){
return 0;
}finally {
studentid=10;
}
}
}
运行结果:
3.当jvm退出时finally不执行
public class Demo4 {
public static void main(String[] args) {
}
public void test(){
try{
int a=10;
int b=0;
int c=a/b;
}catch(RuntimeException e){
//退出JVM
System.exit(0);
}finally {
System.out.println("finally代码块被执行了");
}
}
}
5.throws关键字
因为传递的参数问题可能导致异常,如果不对异常进行处理,就使用throws抛出异常交给调用者处理。
import java.io.IOException;
public class Demo5 {
public static void main(String[] args) {
test("abc","456");
}
public static void test(String a,String b)throws IOException{
int c=Integer.parseInt(a)+Integer.parseInt(b);
System.out.println("和为:"+c);
}
}
6.throw关键字
throw关键字表示在程序中人为的抛出一个异常,当异常产生后,实际上抛出一个异常就是抛出一个异常的实例化对象,那么可以通过throw关键字将此对象抛出。
public class Demo6 {
public static void main(String[] args) {
Person p = new Person();
p.setAge(210);
}
public static class Person {
private int age;
public void setAge(int age) {
if(age<0||age>200){
RuntimeException e = new RuntimeException("你输入的年龄不合理");
throw e;
}else{
this.age = age;
}
}
public int getAge() {
return age;
}
}
}
运行结果
7.自定义异常
编写一个类,继承Exception/RuntimeException,并重写其一参构造方法。
class MyException extends Exception{ // 继承Exception,表示一个自定义异常类
public MyException(String text){
super(text) ; // 调用Exception中有一个参数的构造
}
};