日期类&异常类

460759461-zeze / 2024-07-08 / 原文

日期类&异常类

作业:千位数字相乘

public static void main(String[] args) {
        // 两个千位数字相乘
        int[] arr1 = {7,8,9,9,8,9};
        int[] arr2 = {7,9,8,9,6,8};
        // 定义结果的数组
        int[] result = new int[12];
        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr2.length; j++) {
                result[i + j] += arr1[i] * arr2[j];
            }
        }

        // 统一处理进位问题
        for (int i = 0; i < result.length - 1; i++) {
            int temp = result[i];
            result[i] = temp % 10;
            result[i + 1] += (temp / 10);
        }

        System.out.println(Arrays.toString(result));
    }

1 日期类

1.1 Date类

public static void main(String[] args) throws ParseException {
        // 获取当前时间
        Date date = new Date();
        // 设置计算机元年之后的时间
        date.setTime(10000L);
        System.out.println(date);
        // 获取计算机元年到现在的毫秒值
        System.out.println(date.getTime());
        // 计算机元年在中国是 1970年1月1日早上8点
        // 从计算机元年开始加上传入的毫秒值的时间
        Date date1 = new Date(1718937063489L);
        System.out.println(date1);

        // 日期格式化
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        // 把日期转换成字符串
//        String str = simpleDateFormat.format(new Date());
//        System.out.println(str);
        String str = "2035年10月1日 12:12:12";
        // 把字符串转日期
        Date date2 = simpleDateFormat.parse(str);
        System.out.println(date2);
    }

1.2 Calendar类

public static void main(String[] args) throws ParseException {
        // 日历类  获取默认时区的日历
        Calendar calendar = Calendar.getInstance();
        // 设置指定的字段
//        calendar.set(Calendar.YEAR,2050);
//        calendar.set(2050,9,1,12,0,0);
        String str = "2050-10-1 12:12:12";
        // 把字符串转换成日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(str);
        // 设置时间
        calendar.setTime(date);
        System.out.println(calendar);
        // 获取日历的相关信息
        // 年
        int year = calendar.get(Calendar.YEAR);
        System.out.println(year);
        // 月  从0开始  需要加1
        int month = calendar.get(Calendar.MONTH);
        System.out.println(month + 1);
        // 日
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(day);
        // 小时
        int hour = calendar.get(Calendar.HOUR);
        System.out.println(hour);
        // 分
        int minute = calendar.get(Calendar.MINUTE);
        System.out.println(minute);
        // 秒
        int second = calendar.get(Calendar.SECOND);
        System.out.println(second);
        // 毫秒
        int milliSecond = calendar.get(Calendar.MILLISECOND);
        System.out.println(milliSecond);
        // 一年的第几天
        int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
        System.out.println(dayOfYear);
        // 一个月的第几周
        int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);
        System.out.println(weekOfMonth);


    }

课堂练习:假设每个月的第三周的周五股市开放交易。其他时间无法交易。输入一个时间,判断这个时间是否允许交易并且提示:

交易未开始,交易已结束,交易正在进行中

public static void method() throws ParseException {
//        假设每个月的第三周的周五股市开放交易。其他时间无法交易。
//        输入一个时间,判断这个时间是否允许交易并且提示:
//        交易未开始,交易已结束,交易正在进行中
        System.out.println("请输入您想查询的日期");
        Scanner scanner = new Scanner(System.in);
        // 2018-01-01
        String str = scanner.next();
        // 把字符串转换成日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = simpleDateFormat.parse(str);
        // 获取日历类
        Calendar calendar = Calendar.getInstance();
        // 给日历设置时间
        calendar.setTime(date);

        // 获取第几周
        int week = calendar.get(Calendar.WEEK_OF_MONTH);
        // 获取日
        int day = calendar.get(Calendar.DAY_OF_WEEK);

        // 判断交易状态
        if (week == 3 && day == 6){
            System.out.println("交易正在进行中");
        }else if (week < 3 || week == 3 && day < 6){
            System.out.println("交易未开始");
        }else {
            System.out.println("交易已结束");
        }
    }

1.3 time包

jdk1.8之后,对时间体系进行了新的划分,将日期和时间以及其他信息进行分割,从而分出来一个代表时间的包---java.time

1.3.1 LocalDate类

只有日期(年月日),没有时间(时分秒)

public static void main(String[] args) {
        // 获取当前时间
        LocalDate date = LocalDate.now();
        System.out.println(date);
        // 指定日期
        LocalDate date1 = LocalDate.of(2014, 6, 5);
        System.out.println(date1);

        // 添加天数
//        date = date.plusDays(3);
        // 添加月数
//        date = date.plusMonths(3);
        // 添加周的天数
//        date = date.plusWeeks(1);
        // 添加年数
//        date = date.plusYears(3);

         date = date.plus(3, ChronoUnit.DAYS);
        System.out.println(date);

        // LocalDate和String的相互转换
        // 日期时间格式转换器
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        // 将日期转换成字符串
        String str = dateTimeFormatter.format(date);
        System.out.println(str);
        // 将字符串转换成日期
        LocalDate date2 = LocalDate.parse(str, dateTimeFormatter);
        System.out.println(date2);
    }

1.3.2 LocalTime类

只有时间,没有日期。精确到纳秒

private static void demo2() {
        // 获取当前时间
        LocalTime time = LocalTime.now();
        System.out.println(time);
        // 指定时间
//        LocalTime time1 = LocalTime.of(18, 0, 1);
//        System.out.println(time1);

        // 添加时间
        // 添加小时
        time = time.plusHours(3);
        // 添加分钟
//        time.plusMinutes()
        // 添加秒
//        time.plusSeconds();
        // 添加纳秒
//        time.plusNanos();
        time = time.plus(3,ChronoUnit.HOURS);
        System.out.println(time);

        // 减少
        time = time.minus(4,ChronoUnit.HOURS);
        // 减少小时
//        time.minusHours();
        // 减少分钟
//        time.minusMinutes()
        // 减少秒
//        time.minusSeconds()
        // 减少纳秒
//        time.minusNanos();
        System.out.println(time);

        // LocalDate和String的相互转换
        // 日期时间格式转换器
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH-mm-ss-SSS");
        // 将日期转换成字符串
        String str = dateTimeFormatter.format(time);
        System.out.println(str);
        // 将字符串转换成日期
        LocalTime date2 = LocalTime.parse(str, dateTimeFormatter);
        System.out.println(date2);
    }

1.3.3 LocalDateTime类

有日期有时间,精确到纳秒

private static void demo3() {
        // 获取时间
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);
        // 指定时间
        LocalDateTime dateTime = LocalDateTime.of(2027, 12, 12, 5, 6, 7);
        System.out.println(dateTime);

        // 添加时间
        dateTime = dateTime.plus(3,ChronoUnit.CENTURIES);
        System.out.println(dateTime);

        // 减少时间
        dateTime = dateTime.minus(3,ChronoUnit.HOURS);
        System.out.println(dateTime);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss:SSS");
        // 把日期转换成字符串
        String str = formatter.format(dateTime);
        System.out.println(str);
        // 把字符串转换成日期
        LocalDateTime parse = LocalDateTime.parse(str, formatter);
        System.out.println(parse);
    }

1.3.4 Instant

private static void demo4() {
        // 当前北京时间距离世界时间相差8小时
        // 获取当前的北京时间
        Instant now1 = Instant.now(Clock.offset(Clock.systemUTC(), Duration.ofHours(8)));
        System.out.println(now1);
        // 获取当前世界时间
        Instant now = Instant.now();
        System.out.println(now);
        // 添加时间
//        now = now.plus(8,ChronoUnit.HOURS);
//        System.out.println(now);

        // 比较两个时间的差值
        long duration = now.until(Instant.now(), ChronoUnit.HOURS);
        System.out.println(duration);


        // 获取毫秒
        System.out.println(now.get(ChronoField.MILLI_OF_SECOND));
        // 获取微秒
        System.out.println(now.get(ChronoField.MICRO_OF_SECOND));
        // 获取纳秒
        System.out.println(now.get(ChronoField.NANO_OF_SECOND));

        // 将Instant转换成LocalDateTime类型
        // ZoneId.systemDefault() 默认时区
        LocalDateTime localDateTime = LocalDateTime.ofInstant(now, ZoneId.systemDefault());
        System.out.println(localDateTime);
    }

1.3.5 间隔相关的日期类

  • Period 用于计算两个日期间隔
		LocalDate d1 = LocalDate.now();
        LocalDate d2 = LocalDate.of(2022, 12, 12);
        Period between = Period.between(d2, d1);
        System.out.println("相差的年数" + Math.abs(between.getYears()));
        System.out.println("相差的月数" + between.getMonths());
        System.out.println("相差的天数" + between.getDays());
  • Duration:用于计算两个时间间隔
private static void demo6() {
        LocalDateTime t1 = LocalDateTime.now();
        LocalDateTime t2 = LocalDateTime.of(2024, 7, 8, 0, 0, 0);
        Duration between = Duration.between(t1, t2);
        System.out.println("相差的总天数" + between.toDays());
        System.out.println("相差的总小时数" + between.toHours());
        System.out.println("相差的总分钟数" + between.toMinutes());
        System.out.println("相差的总秒数" + between.toSeconds());
    }

2 异常

2.1 异常的基本使用

Throwable是异常的顶级父类。有两大子类:

  • Error 错误 非常严重的问题 需要修改代码才能解决
    • StackOverflowError 栈溢出错误 方法递归没有出口时
    • OutOfMemoryError 堆内存溢出
  • Exception 异常
    • 所有异常的父类,程序中出现了一般性的问题,处理异常后程序会继续执行
    • 异常分为编译时异常和运行时异常
    • 编译时异常在编译阶段需要处理,否则编译不通过
    • 运行时异常在编译阶段不需要处理
    • RuntimeException和它的子类都是运行时异常
    • 其他的异常都是编译时异常
public static void main(String[] args) throws ParseException {
//        m1();
        m(null);
    }

    private static void m1() throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        simpleDateFormat.parse("2010/12/12");
    }

    public static void m(String str) throws ParseException{
        if (str == null)
//            throw new NullPointerException("空指针异常了,哥们");
            throw new ParseException("",0);
        // 出现异常
        // 1. 创建对应的异常对象  new NullPointerException()
        // 2. 程序立即停止,并且在控制台显示异常的信息
        boolean aa = str.equals("aa");
        System.out.println("HelloWorld");
    }

2.2 自定义异常

定义一个类,继承Exception(RuntimeException),然后提供无参构造和有参构造,有参构造中调用父类的构造方法

// 自定义异常
// 除了RuntimeException和它的子类,其他都是编译时异常
class PathNotExistException extends Exception{


    public PathNotExistException(){}

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

class FileFormatException extends Exception{


    public FileFormatException(){}

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

2.3 异常的捕获方式

  • 如果出现了多个异常,并且每一个异常的处理方式都不一样,可以使用多个catch分别捕获分别处理。
        try {
            s = readFile("D:\\a.png");
        } catch (PathNotExistException e) {
            System.out.println("出现异常了");
            // 打印异常栈轨迹
//            e.printStackTrace();
            System.out.println(e.getMessage());
        }catch (FileFormatException e){
            // 处理异常
            System.out.println(e.getMessage());
        }catch (NullPointerException e){
            System.out.println(e.getMessage());
        }
  • 如果所有异常的处理方式都一样,可以捕获这些异常的父类,然后进行统一的处理。
	String s = null;
        try {
            s = readFile("D:\\a.png");
        } catch (Exception e) {
            System.out.println("出现异常了");
            // 打印异常栈轨迹
//            e.printStackTrace();
            System.out.println(e.getMessage());
        }
  • 如果异常的处理进行了分组,那么同一组异常之间用| 隔开,进行分组处理
String s = null;
        try {
            s = readFile("D:\\a.png");
        } catch (FileFormatException | PathNotExistException e){// 分组捕获
            // 处理异常
            System.out.println(e.getMessage());
        }catch (NullPointerException e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        }

注意点: 捕获异常的时候应该先捕获子类异常,再捕获父类异常

2.4 异常对方法重写和重载的影响

异常对方法的重载没有影响

class A{
    public void m()throws IOException{

    }

    public void m(int i) throws Exception{

    }
}

子类抛出的编译时异常不能超过父类对应方法的编译时异常的范围。

运行时异常对于重写没有影响

重写:重写是指在父子类中存在方法签名一致的非静态方法。在构成重写的时候,要求子类重写的方法的权限修饰符的范围要大于等于父类对应方法的权限修饰符范围。如果父类方法的返回值类型是基本数据类型/void,那么子类方法的返回值类型要保持一致。如果父类方法的返回值类型是引用数据类型,那么要求子类方法的返回值类型要么和父类一致,要么是父类方法返回值类型的子类。另外,子类重写的方法抛出的编译时异常不能超过父类对应方法的编译时异常的范围。

重写本身是一种运行时多态。

3 finally

finally修饰代码块,表示无论是否出现异常都会执行的代码块

结果是3

public static int demo1(){
        try {
            return 1;
        }finally {
            try {
                return 2;
            }finally {
                return 3;
            }
        }
    }

结果是5,7

        System.out.println(demo2());// 5
    }

    public static int demo2(){
        int i = 5;
        try {
            // 先进入到try中,执行return i++;  i是5,先return 5 再 i++
            // i 变成6
            // 由于有finally,所以不能理解结束方法,执行finally中的i++
            // i 变成 7,打印
            // 然后方法整体结束,返回5
            return i++;
        }finally {
            i++;
            System.out.println("i = " + i);// 7
        }
    }

返回蔡依林 44

public static Person demo3(){
        Person person = new Person();
        try {
            person.setName("周杰伦");
            person.setAge(45);
            // 因为返回的是对象,是内存中的一块地址
            // 由于有finally,继续执行,把上面的地址中的属性值2改成蔡依林 44
            // 所以最终结果就是 蔡依林 44
            return person;
        }finally {
//            person = new Person();  如果这行代码不注释,返回的是周杰伦45
            person.setName("蔡依林");
            person.setAge(44);
        }
    }

返回的是abc

public static String m(){
        String str;
        try {
            str = "abc";
            return str;
        }finally {
            // 地址已经发生了改变
            str = "def";
        }
    }