Java 异常

零、复习昨日

一、作业

package com.qf.homework;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class TestBirthday2 {

    // 变式扩展,输入身份证号确定截止今天是否成年

    /**
     *  思路:
     *  1. 如果年份相减小于17,肯定未成年
     *  2. 如果年份相减大于18,肯定成年
     *  3. 如果年份相减等于18,还需要判断月份和日
     */
    public static void main(String[] args) throws ParseException {
        printInfo("410112200502220104");
    }

    /**
     * 以身份证号输出个人信息
     */
    public static void printInfo(String idStr) throws ParseException {
        // 校验身份证号规则(长度18位)
        if (idStr.length( ) != 18) {
            System.out.println("身份证号有误!");
            return;
        }

        // 410112202210250103
        String birthdayStr = idStr.substring(6, 14);

        // 字符串变日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date birthday = sdf.parse(birthdayStr);

        // 将日期转成日历
        Calendar calendar = Calendar.getInstance( );
        calendar.setTime(birthday);

        // 通过日历信息获得,年月日
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        // System.out.println(year+"-"+month+"-"+day );

        // 获得当前时间
        Calendar now = Calendar.getInstance( );
        int nowYear = now.get(Calendar.YEAR);
        int nowMonth = now.get(Calendar.MONTH) + 1;
        int nowDay = now.get(Calendar.DAY_OF_MONTH);

        // System.out.println(nowYear+"-"+nowMonth+"-"+nowDay );

        boolean flag = false;

        // 先判断年份差值
        if (Math.abs(nowYear - year) > 18) {
            // System.out.println("成年" );
            flag = true;
        } else if (Math.abs(nowYear - year) < 18) {
            //System.out.println("未成年" );
        } else {
            if (month < nowMonth) {
                //System.out.println("成年" );
                flag = true;
            } else if (month > nowMonth) {
                //System.out.println("未成年" );
            } else {
                if (day <= nowDay) {
                    //System.out.println("成年" );
                    flag = true;
                } else {
                    //System.out.println("未成年" );
                }
            }
        }
        if (flag) {
            System.out.println("成年" );
        } else {
            System.out.println("未成年" );
        }
    }
}

计算是否成年, 方案二: 毫秒值计算

变式题: 输入身份证号,计算该人在世多少天

二、异常

2.1 异常的概念

异常:就是程序出现的不正常的情况。

2.2 异常的分类

在Java程序设计中,关于异常有一大类 Throwable
其下又有两个分类:Error,Exception
Error:程序出现的严重问题,且只能抛出(throw),不能试图捕获(try catch)
Exception:是程序出现的问题,可以捕获可以抛出

ps:编译期异常又叫 受检查异常 ,运行时异常又叫 不受检查异常…

目前见过的异常

ArithmeticException 算数异常
ArraysIndexOutOfBoundsException 数组下标越界异常
NullPointerException 空指针异常
ClassCastException	类转换异常
StringIndexOutOfBoundsException 字符串下标越界异常
NumberFormatException 数字格式化错误
ParseException      解析异常

2.3 异常的产生

在代码内部使用 throw 异常对象,来产生异常。
    public static void main(String[] args) {
        test();
    }

    public static void test() {
        System.out.println("xxx" );
        int a = 1;
        if(a > 0) {
            // 抛出一个异常对象
            throw new ArrayIndexOutOfBoundsException(  );
            //throw new ParseException("Unparseable date: ",1);
            //throw new FileNotFoundException( );
            //throw new 异常类();
        }
    }

2.4 编译期异常 & 运行期异常

编译期异常:代码编译时可能会出错,程序中出现编译异常,就会强制要求处理…

运行期异常:代码执行时可能会出错,程序中出现的运行时异常没有强制处理…,默认采取 抛出处理异常 。

2.5 异常的处理

异常的处理只有两种方案:
抛出(throws):被动处理
试图捕获(try catch):主动处理

2.5.1 抛出(throws)

抛出是将异常在方法签名上声明抛出。
public void test() throws 异常类名1,异常类名2…{ …… }
在方法参数列表后,使用 throws 加 异常类名来声明抛出异常,且允许声明多个异常类,中间用逗号隔开

谁调用这个方法,异常就抛给谁,那么这个调用者就要继续在处理异常

抛出异常后的影响:抛出异常后,异常处后续代码不再执行!!

throw

throws

位置

方法内部

方法参数列表后

后面

new 异常对象

异常类名

作用

产生异常

声明可能抛出异常

2.5.2 试图捕获

试图捕获 try…catch
try{
	// 可能会出现异常的代码
} catch(Exception e){
	e.xxx();
}
// try里面包裹代码。如果其中代码出现异常,就会被catch抓住,需要抛出异常和catch异常后生命的异常同一类型才可以抓住,否则抓不住!如果try里面的代码没有任何报错,catch内的代码不执行。

// catch还可以同时声明多个异常类,强调不是同时抓多个异常对象!!因为根本就不可能产生多个异常对象,因为try内部一旦出现异常,try内部的后面就不会执行。

// 虽然可以同时声明多个异常类,但是很麻烦,一般可以直接写一个最大异常Exception

无论try…catch代码有没有错误,其结构后面的代码一定会执行

2.5.3 finally

try{
	// …
} catch(Exception a){
	// …
} finally{
	// …
}
或try{
	// …
} finally{
	// …
}

        // SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        // try{
        //     Date date = sdf.parse("20220101");
        // }catch (ParseException e) {
        //     System.out.println("日期解析出错!" );
        // } finally {
        //     System.out.println("...最终的" );
        // }
        try{
            System.out.println(1 /0);
        } finally {
            System.out.println("...最终的" );
        }
finally这么设计的作用,为了确保某些代码必须能执行到!一般场景是释放资源。
扩展:配合return以实现不同的效果

2.6 异常的应用

应用1:
设计方法时,如果这个方法会经常调用,或者被多次多层调用,尽量自行捕获异常,不要抛出!因为一旦抛出,所欲哦使用者都需要处理该异常!
应用2:
方法重写时子类抛出的异常范围 小于等于 父类的异常范围
特殊的:父类方法没有异常,子类重写是也不能抛出异常!!

2.7 异常的API

最大的父类Throwable类

// 构造方法
Throwable(String message) message就是异常信息
    
// 方法  
String getMessage() 返回此 throwable 的详细消息字符串。 
void printStackTrace()  将此 throwable 及其追踪输出至标准错误流。 
    public static void test7() {
        //throw new ArithmeticException("这是算术异常");
        //System.out.println(1/0 );

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        try {
            sdf.parse("2222/11/21");
        } catch (ParseException e) {
            // 将异常信息打印到控制台
            // e.printStackTrace( );
            String message = e.getMessage( ); // 获得异常信息
            System.out.println(message );
        }
    }

三、自定义异常

只有当对象是Throwable类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出
换句话,自定义异常需要继承Throwable类

一般继承的是Throwable的子类,

继承Error那就是有Error对应的特点,即不能捕获只能抛出!!

继承Exception,就是Exception对应的特点,可以抛出可以捕获!!!

继承RuntimeException那就是运行期异常的特点,可以不用主动处理!!

继承非RuntimeException及其子类那就是编译期异常的特点!

演示: 年龄越界异常
  1. 建类

  1. 继承

  1. 写构造方法

  1. 在方法内部使用异常(产生异常)

  1. 测试

四、总结

关于一场,以后常见的就是Exception
Error基本见不到,一旦见到就是严重问题必须处理
需要分清楚 编译期异有哪些,运行时期异常有哪些
封情书:捕获异常、抛出异常有什么特点
自定义异常,在后续写项目时会用到
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值