Java - 异常处理

异常:在程序运行过程中可能发生的不正常的事件,会中断正在运行的程序。异常是一种特殊的对象,类型为java.lang.Exception或其子类。

Java使用异常处理机制为程序提供了错误处理的能力,通过5个关键字来实现的:try、catch、 finally、throw、throws

  • 捕获异常:try-catch-finally
    • try:执行可能产生异常的代码
    • catch:捕获异常
    • finally:无论是否发生异常,finally中的代码块总会执行,通常用来关闭一些流、数据库连接等物理资源
  • 声明异常:throws:声明方法可能要抛出的各种异常
  • 抛出异常:throw:手动抛出异常

try-catch块:捕获异常

public void method(){
    try {
        // 可能产生异常的 代码段
    } catch (异常类型 ex) {
        // 对异常进行处理的代码段4
    }
    
    // 代码段5
}

多重try-catch块:一段代码可能会引发多种类型的异常,当引发异常时,会按顺序来查看每个 catch 语句,并执行第一个与异常类型匹配的catch语句,执行其中一条 catch 语句后,其后 catch 语句将被忽略。

在安排catch语句的顺序时,首先应该捕获最特殊的异常,  然后再逐渐一般化,即先子类后父类  。

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

 try-catch-finally:try-catch块后加入finally块,可以确保无论是否发生异常,finally块中的代码总能被执行。

//finally块中语句不执行的唯一情况
//异常处理代码中执行System.exit(1)退出Java虚拟机 

try {
    //……省略输入num1和num2的代码
    System.out.println(String.format("%d / %d = %d", num1, num2, num1/ num2));			
} catch (Exception e) {
    System.err.println("出现错误:被除数和除数必须是整数," +"除数不能为零");	
    System.exit(1); // finally语句块不执行的唯一情况	
} finally {
    //……
}

 声明异常:Java语言中通过throws声明某个方法可能抛出的各种异常,可以同时声明多个异常,由逗号隔开。

//divide()方法没有处理异常,而是声明异常
public static void divide() throws Exception {
		//……	
}

//方式1:调用者通过try-catch捕获并处理异常 
public static void main(String[] args) {
		try {
			divide();
		} catch (Exception e) {
            //……
        }
}

//方式2:调用者通过throws继续声明异常 
public static void main(String[] args) throws Exception {
    divide();
}

抛出异常:除了系统自动抛出异常外,有些问题需要程序员自行抛出异常。

public class Person {
		private String sex = "男";// 性别
	   public void setSex(String sex) throws Exception {
		if ("男".equals(sex) || "女".equals(sex))
			this.sex = sex;
		else {
			throw new Exception("性别必须是“男”或者“女”!");   //抛出异常
		}
	}
}

Person person = new Person();
try {
    person.setSex("Male");
    person.print();
} catch (Exception e) {			//捕获异常,或者throws异常
    e.printStackTrace();
}

自定义异常: JDK 中的异常类型不能满足程序的需要时,可以自定义异常类。

使用自定义异常的步骤:

  • 定义异常类:继承Excepion 或者RuntimeException
  • 编写构造方法,继承父类的实现
  • 实例化自定义异常对象
  • 使用throw抛出

异常分类:异常大致分为两类:受检异常和运行时异常

1、受检异常:也叫编译时异常或者非运行时异常,代码在编译的过程中必须处理的异常,不处理就没法运行整个程序。常见的受检异常有:

  • SQLException
  • ClassNotFoundException

2、运行时异常(RuntimeException):在运行时才会发生的异常,常见的运行时异常有:

  • ArithmeticException
  • NullPointException
  • ArrayIndexOutOfBoundsException
  • InputMismatchException

常见的异常类型:

注意:

异常的父类是Exception,所有的异常类都是Exception类的子类。系统提供的异常有时候并不能满足我们的需求,所以我们可以自定义异常

package com.liudm.demo8;

import java.util.Scanner;

public class Demo1 {
	public void div(){
		Scanner sc = new Scanner(System.in);
		
		System.out.println("请输入被除数:");
		int num1 = sc.nextInt();
		System.out.println("请输入除数:");
		int num2 = sc.nextInt();
		
		//System.out.println("结果为:" + num1/num2);
		
		
		try {
			//有可能会发生的异常放在try块中
			System.out.println("结果为:" + num1/num2);
		} catch (Exception e) {
			// TODO: handle exception
			//一旦发生了异常,由catch块去捕捉
			System.out.println("发生异常");
			System.out.println(e.getMessage());
		}
	}
	
	public static void main(String[] args) {
		Demo1 de = new Demo1();
		de.div();
	}
	//当除数为0,会中断程序的运行

}

实验: 要求:编写“技术工程师”类,属性定义为:姓名、年龄,自定义的年龄异常,在setAget方法中进行逻辑处理,如果在调用setAge方法给age属性赋值的时候,年龄不合法(负数或者大于120),则抛出自定义的年龄异常。

自定义年龄:AgeException,让其继承Exception类,在重写的构造器中调用父类有参构造器。

package my.exception;  
public class AgeException extends Exception {  
    public AgeException(String mess) {  
        super(mess);  
    }  
}

Teacher类,在Teacher类中定义name和age属性,我们在setAge的时候,就可以加入逻辑控制,当年龄在0~120之间时,我们认为年龄才合法,否则抛出自定义的AgeException。

package my.exception;  
public class Teacher {  
    private int age;  
    private String name;  
  
    public void setAge(int age) throws Exception {//声明这个方法中有异常  
        if(age>=0&&age<=120){  
            this.age = age;  
        }else{  
            //异常  抛出  
            throw new AgeException("年龄只能在0到120之间。。");  
        }  
    }  
    public int getAge() {  
        return age;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}

测试类:在测试类中,构建一个Teacher对象,从控制台输入年龄,赋值给teacher对象,最后输出年龄的值。

package my.exception;  
  
import java.util.InputMismatchException;  
import java.util.Scanner;  
  
public class Test {  
    public static void main(String[] args) {  
        Scanner sc=new Scanner(System.in);  
        System.out.println("请输入性别  ");  
        int age=sc.nextInt();  
        Teacher tea=new Teacher();  
        // 性别:男和女  --抛出异常   
        try {  
            tea.setAge(age);  
        } catch (InputMismatchException e) {  
            System.out.println("输入的必须是字符串");  
            e.printStackTrace();  
        }catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        System.out.println(tea.getAge());  
    }  
}

在控制台打印信息查看输出相关信息。分析:当我们从控制台输入年龄的时候,有可能输入非数字,所以报出InputMismatchException(输入类型不匹配)异常;但是finally中的代码块还是执行。当我们输入年龄不在0~120之间时,这是不符合常理的,所以会报出自定义的年龄异常。


练习1:需求说明:编程实现两个数的除法运算,使用try-catch捕获并处理异常;运行程序,分别输入400,200和400,B以及400,0三组数字查看程序运行效果。

package com.liudm.demo9;

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

public class Div {
	public static void main(String[] args) {
		int num1,num2;

		try {
			Scanner sc = new Scanner(System.in);
			System.out.println("请输入被除数:");
			num1 = sc.nextInt();
			System.out.println("请输入除数:");
			num2 = sc.nextInt();
			System.out.println("结果是:" + num1/num2);
			
		} catch (InputMismatchException e) {
			// TODO: handle exception
			System.out.println("输入类型不匹配!");
		} catch (ArithmeticException e) {
			// TODO: handle exception
			System.out.println("算数异常!");
		}
	}
}

练习2:需求说明:编写数据转换类,定义数据转换方法,具有String类型的参数,实现将参数转换为整型数据后输出,要求使用多重catch语句处理异常,使用NumberFormatException、Exception异常类型,编写测试类,调用数据类型转换方法,分别传递参数“a”、20。

练习3:需求说明:在setAge(int age) 中对年龄进行判断,如果年龄介于1到100直接赋值,否则抛出异常;在测试类中创建对象并调用setAge(int age)方法,使用try-catch捕获并处理异常;在setSex中堆性别进行判断,性别必须是男或者女,否则抛出异常。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值