0
点赞
收藏
分享

微信扫一扫

时间类(Date、LocalDateTime...)、异常类(try..catch、throw、throws、throwable)

穆风1818 2022-02-15 阅读 240
java

时间类

        Date

        SimpleDateFormat

        JDK8新增日期类

异常类

        异常概述

        异常处理方式

        自定义异常

时间

生活中的时间
    每个国家的时间, 没有一个统一的标准, 都自己算自己的, 行不行?
    答案是不行的
    
世界标准时间
    格林尼治时间/格林威治时间 (Greenwich Mean Time), 简称GMT
    是有误差的, 目前已经不作为依据

原子钟
    两年万年误差一秒钟
    
我国的标准时间
    北京时间, 要在世界标准时间+8小时 (我们在东8区)
    
时间换算公式
    1秒 = 1000毫秒 (常用)
    1毫秒 = 1000微妙
    1微妙 = 1000纳秒
    
计算机中的时间原点 (也可以理解为起始时间)
    1970年1月1月 00:00:00
   
原因
    1960年8月, 贝尔实验室的程序员使用B语言在老旧的PDP-7机器上开发出了Unix的一个版本
    随后改进了B语言, 开发了C语言, 重写了UNIX
    所以认为1970年1月1日是C语言的生日, Java延续了这一传统
    
以下代码获得的毫秒值, 就是从1970年1月1日到代码运行时经过的毫秒值

Date

Date代表了一个特定的时间, 精确到毫秒

Date成员方法

时间日期类-SimpleDateFormat

API中字母及对应关系如下
    y    年
    M    月
    d    日
    H    时
    m    分
    s   秒
    
常见格式示例

SimpleDateFormat构造方法

SimpleDateFormat格式化和解析方法

// //public SimpleDateFormat(); 构造一个SimpleDateFormat对象, 使用默认格式
public class Demo01 {
public static void main(String[] args) {
//SimpleDateFormat sdf = new SimpleDateFormat(); //使用默认格式
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");

//格式化时间, 使用默认格式
String format = sdf.format(new Date());
System.out.println(format);
/*
指定不同的格式进行格式化
2022/2/8 下午4:40
2022-02-08 16:42:37
2022年02月08日
*/

}
}

// public Date parse(String source); 从指定格式解析为日期对象
public class Demo02 {
public static void main(String[] args) throws ParseException {
//提供解析文本
String s = "2022年1月1日 11:11";

//public Date parse(String source); 从指定格式解析为日期对象
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd日 HH:mm");
/*
如果指定的格式和要解析的格式不一样, 报错:
java.text.ParseException
*/


SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
Date date = sdf.parse(s);

System.out.println(date); //Sat Jan 01 11:11:00 CST 2022
}
}

练习

/*
开始时间 2020年11月11日 0:0:0
结束时间 2020年11月11日 0:10:0

张三 2020年11月11日 0:03:47 (秒杀成功)
李四 2020年11月11日 0:10:11 (秒杀失败)

时间节点
*/

public class Demo {
public static void main(String[] args) throws ParseException {
//解析格式相同
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

//解析开始和结束时间, 并获取毫秒值
long startTime = sdf.parse("2020年11月11日 0:0:0").getTime();
long endTime = sdf.parse("2020年11月11日 0:10:0").getTime();

//解析张三和李四的时间, 并获取毫秒值
long zhangsan = sdf.parse("2020年11月11日 0:03:47").getTime();
long lisi = sdf.parse(" 2020年11月11日 0:10:11").getTime();

//判断
if(zhangsan >= startTime && zhangsan <= endTime){
System.out.println("张三同学秒杀成功!");
}else {
System.out.println("张三同学秒杀失败!");
}

if(lisi >= startTime && lisi <= endTime){
System.out.println("李四同学秒杀成功!");
}else {
System.out.println("李四同学秒杀失败!");
}
}
}

JDK8时间类

在JDK8中, 将Date对象进行了拆分
    1. LocalDate: 表示日期 (年月日)
    2. LocalTime: 表示时间 (时分秒)
    3. LocalDateTime: 表示时间+日期 (年月日时分秒)

 //public static LocalDateTime now(); 获取当前系统时间
 LocalDateTime date1 = LocalDateTime.now();
 System.out.println(date1); //2022-02-08T18:19:10.196345700

 //public static LocalDateTime of(年,月,日,时,分,秒); 按照参数初始化LocalDateTime对象
 //LocalDateTime date2 = LocalDateTime.of(2022, 15, 2, 22, 22, 22);
            /*
           月份超出了规定范围, 报错:
           java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 15
             */


LocalDateTime date2 = LocalDateTime.of(2022, 2, 2, 22, 22, 22);
System.out.println(date2); //2022-02-02T22:22:22

LocalDateTime获取方法

    public int getYear(); 获取年
    public int getMonthValue(); 获取月份(1-12)
    * Month getMonth(); 获取月份返回值为枚举
    public int getDayOfMonth(); 获取月份中的第几天(1-31)
    public int getDayOfYear(); 获取一年中的第几天(1-366)
    public DayOfWeek getDayOfWeek(); 获取星期几
    public int getMinute(); 获取分钟
    public int getHour(); 获取小时

        //创建时间对象
LocalDateTime date = LocalDateTime.of(2022, 11, 11, 11, 11, 11);

//public int getYear(); 获取年
System.out.println(date.getYear()); //2022
//public int getMonthValue(); 获取月份(1-12)
System.out.println(date.getMonthValue()); //11
//* Month getMonth(); 获取月份返回值为枚举
System.out.println(date.getMonth()); //NOVEMBER
//public int getDayOfMonth(); 获取月份中的第几天(1-31)
System.out.println(date.getDayOfMonth()); //11
//public int getDayOfYear(); 获取一年中的第几天(1-366)
System.out.println(date.getDayOfYear()); //315
//public DayOfWeek getDayOfWeek(); 获取星期
System.out.println(date.getDayOfWeek()); //FRIDAY
//public int getMinute(); 获取分钟
System.out.println(date.getMinute()); //11
//public int getHour(); 获取小时
System.out.println(date.getHour()); //11

JDK8时间类-转换方法

        从LocalDateTime对象转为LocalDate和LocalTime
                    public LocalDate toLocalDate();
                    public LocalTime toLocalTime();

            //创建时间对象
LocalDateTime date = LocalDateTime.of(2022, 2, 2, 22, 22, 22);

//public LocalDate toLocalDate();
System.out.println(date.toLocalDate()); //2022-02-02

//public LocalTime toLocalTime();
System.out.println(date.toLocalTime()); //22:22:22

JDK8时间类-格式化和解析

 

JDK8时间类-plus系列的方法

    LocalDateTime增加和减少时间的方法
    public LocalDateTime plusYears(long years); 增加或减去年
    public LocalDateTime plusMonths(long months); 增加或减去月
    public LocalDateTime plusDays(long days); 增加或减去日
    public LocalDateTime plusHours(long hours); 增加或减去时
    public LocalDateTime plusMinutes(long minutes); 增加或减去分
    public LocalDateTime plusSeconds(long seconds); 增加或减去秒
    public LocalDateTime plusWeeks(long weeks); 增加或减去周

注意事项 : 传递正数是增加, 传递负数是减去

JDK8时间类-minus系列的方法(和plus系列相反 )

    public LocalDateTime minusYears(long years); 增加或减去年
public LocalDateTime minusMonths(long months); 增加或减去月
public LocalDateTime minusDays(long days); 增加或减去日
public LocalDateTime minusHours(long hours); 增加或减去时
public LocalDateTime minusMinutes(long minutes); 增加或减去分
public LocalDateTime minusSeconds(long seconds); 增加或减去秒
public LocalDateTime minusWeeks(long weeks); 增加或减去周

JDK8时间类-with系列的方法

    public LocalDateTime withYears(long years); 直接修改年
public LocalDateTime withMonths(long months); 直接修改月
public LocalDateTime withDays(long days); 直接修改日
public LocalDateTime withHours(long hours); 直接修改时
public LocalDateTime withMinutes(long minutes); 直接修改分
public LocalDateTime withSeconds(long seconds); 直接修改秒
public LocalDateTime withWeeks(long weeks); 直接修改星期

JDK8时间类-时间间隔对象

时间间隔对象Period(年月日)
            public static Period between(开始时间,结束时间); 计算两个"时间"的间隔, 包含年月日
                getYears(); 获取年
                getMonths(); 获取月
                getDays(); 获取日

            //创建时间日期对象
LocalDate date1 = LocalDate.of(2022, 1, 1);
LocalDate date2 = LocalDate.of(2023, 12, 12);
//获取时间间隔对象
Period between = Period.between(date1, date2);
System.out.println(between);
/*
P1Y11M11D
P: 时间间隔对象Period
1Y: 1年
11M: 11个月
11D: 11天
*/

//获取年月日
System.out.println(between.getYears()); //1
System.out.println(between.getMonths()); //11
System.out.println(between.getDays()); //11
//获取总月数
System.out.println(between.toTotalMonths()); //23

时间间隔对象Duration(秒,毫秒,纳秒)
            public static Duration between(开始时间,结束时间); 计算两个"时间"的间隔, 包含秒,毫秒,纳秒
                toSeconds(); 获取秒
                toMillis(); 获取毫秒
                toNanos(); 获取纳秒

            //创建时间对象
LocalDateTime date1 = LocalDateTime.of(2022, 1, 1, 12, 0, 0);
LocalDateTime date2 = LocalDateTime.of(2023, 12, 12, 12, 30, 30);
//获取时间间隔对象
Duration duration = Duration.between(date1, date2);
System.out.println(duration);
/*
PT17040H30M30S
PT: 时间间隔对象
17040H: 17040个小时
30M: 30分钟
30S: 30秒
*/

//获取秒,毫秒,纳秒
System.out.println(duration.toSeconds()); //61345830
System.out.println(duration.toMillis()); //61345830000
System.out.println(duration.toNanos()); //61345830000000000

小结:

异常 

什么是异常?
    异常就是用来描述代码中出现的问题
    
注意!
    语法错误不算在异常体系中
    
异常体系?
    - Throwable
                - Error: 严重错误, 比如内存溢出


                - Exception: 异常类, 表示程序本身可以处理的问题
                            - RuntimeException: 运行时异常(例如空指针异常,索引越界异常)
                            - 除RuntimeException外所有异常: 编译时异常(编译期必须处理的异常,否则通不过编译,例如格式化异常)

        int[] arr = {1,2,3};
//System.out.println(arr[3]); //java.lang.ArrayIndexOutOfBoundsException

arr = null;
//System.out.println(arr[0]); //java.lang.NullPointerException

SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
//sdf.parse("2020-1月1日"); //java.text.ParseException

虚拟机默认处理异常的方式

throws声明异常

异常处理方式1: throws :       throws 异常类名

注意: 写在方法的定义处, 表示声明一个异常 (调用我有可能出现这个异常

public class Demo {
public static void main(String[] args) throws ParseException {
//2. 此时调用者没有处理,还是交给JVM处理
//method01(); //java.lang.NullPointerException

//4. throws ParseException: 表示调用者也没有处理,最终还是交给JVM做默认处理
method02(); //java.text.ParseException
}

//3. throws ParseException: 表示该方法有可能出现异常,交给调用者处理
private static void method02() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
sdf.parse("2020-1月1日");
}

//1. throws NullPointerException: 表示该方法有可能出现异常,交给调用者处理
private static void method01() throws NullPointerException {
int[] arr = null;
System.out.println(arr[0]); //java.lang.NullPointerException
}
}

声明异常的注意事项

跟进NullPointerException发现它继承自RuntimeException, 所以是一个运行时异常
跟进ParseException发现它继承自Exception, 所以是一个编译时异常

声明异常的注意事项
    如果是运行时异常:可以省略不写 -> method01省略throws NullPointerException没有报错
    如果是编译时异常:必须显示声明, 否则代码继续报错 -> method02省略throws                                    ParseException报错

public class Demo {
public static void main(String[] args) throws ParseException {
method01();
method02();
}
// 编译时异常不能省略不写
private static void method02() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
sdf.parse("2020-1月1日");
}

private static void method01(){
int[] arr = null;
System.out.println(arr[0]); //java.lang.NullPointerException
}
}

throw抛出异常

思考?
    以前出现了异常, 虚拟机帮我们创建一个异常对象, 抛给调用者
    但是如果我们需要自己手动创建一个异常对象, 该如何实现?

异常处理方式2: throw
    throw new 异常();

注意: 这个格式是在方法内的, 表示当前代码手动抛出一个异常, 下面的代码就不再执行了

throws和throw的区别
    1. throws: 用在方法声明后, 跟的是异常类名, 表示声明异常, 调用该方法有可能出现该异常
    2. throw: 用在方法体内, 跟的是异常对象名(new出来), 表示手动抛出异常, 由方法体内的语句处理

public class Demo01 {
public static void main(String[] args) {
System.out.println("家里有一个貌美如花的老婆");
System.out.println("还有一个当官的兄弟");
System.out.println("自己还有一个买卖");
System.out.println("这样的生活你要不要?");
/*
手动抛出(创建)异常,暂时交给调用者处理
下面的代码就不会执行了
*/

throw new RuntimeException();
//System.out.println("武大郎的标准生活");
}
}

为什么要抛出异常? 因为要将执行结果给调用者进行反馈

public class Demo02 {
public static void main(String[] args) {
int[] arr = null;
printArr(arr);
//4. 调用者如果不处理, 还是抛给了JVM做默认处理
//5. 控制台打印异常信息: java.lang.NullPointerException
//6. 接下来学习, 如果处理异常!
}
public static void printArr(int[] arr){
if(arr== null){
//1. 问题: 调用者知道成功打印了吗?
//2. 回答: 不知道, 因为方法只是将结果打印在控制台,并没有反馈一个结果给调用者
//System.out.println("参数不能为null");

//3. 代码改进: 手动抛出异常, 抛给调用者, 调用者就得到回馈了
throw new NullPointerException();
}else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}

try...catch自己处理异常

异常处理方式3: try...catch
    try{
        可能出现异常的代码;
    }catch(异常类名 变量名){
        处理异常的代码;
    }

快捷键: Ctrl + Alt + T, 选择对应操作, 修改对应的代码

        public static void main(String[] args) {
int[] arr = null;
//2. 手动处理异常
try {
printArr(arr);//可能出现异常的代码
} catch (NullPointerException e) {
System.out.println("参数不能为null"); //处理异常的代码
}

//3. 该方式的优点: 让可能出现异常的后面, 正确代码可以继续运行!
System.out.println("看看我们能不能执行...");
}

public static void printArr(int[] arr){
if(arr== null){
//1. 抛出异常给调用者处理
throw new NullPointerException();
}else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}

try...catch的常见问题

try...catch的常见问题
    1. 如果try中没有遇到问题, 怎么执行?
        会将try中所有代码执行完毕, 不会执行catch中的代码
        继续执行后面的正确代码

    2. 如果try中遇到了问题, 那么try下面的代码还会执行吗?
        try中哪里遇到问题在哪里停下, 直接进入对应的catch执行代码
        继续执行后面的正确代码

    3. 如果出现的问题没有被捕获, 那么程序如何运行?
        try...catch相当于没有写, 异常交给调用者处理
        JVM进行默认处理方式(控制台报错)

    4. 同时有可能出现多个异常怎么处理?
        书写多个catch捕获可能出现的不同异常即可
        
        注意: 如果多个异常出现子父类关系, 父类要写在下面
        原因: 代码会按照catch的书写顺序排错, 如果父类在上面, 就可以接收到子类异常了
        
        问题? 能不能只写一个catch直接捕获父类异常Exception
        不建议! 因为针对不同异常, 我们通常解决方案是不一样的!


try {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的年龄:");
String line = sc.nextLine();
//第一个异常
int age = Integer.parseInt(line);
System.out.println(age);
//第二个异常
System.out.println(2 / 0);
} catch (NumberFormatException e) {
System.out.println("格式化异常..."); //catch可以写多个, 捕获不同的异常
} catch (ArithmeticException e) {
System.out.println("数学运算异常..."); //catch可以写多个, 捕获不同的异常
}
System.out.println("我是try...catch后面的代码...");


try {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的年龄:");
String line = sc.nextLine(); //输入错误数据: aaa
int age = Integer.parseInt(line);
System.out.println(age);
System.out.println("我是try中的代码..."); //不执行
} catch (NullPointerException e) {
//出现的问题没有被捕获, try...catch相当于没有写, JVM进行默认处理方法
System.out.println("我是catch中的代码..."); //不执行
}
System.out.println("我是try...catch后面的代码..."); //不执行

try {
Scanner sc= new Scanner(System.in);
System.out.println("请输入你的年龄:");
String line = sc.nextLine(); //输入错误数据: aaa
int age = Integer.parseInt(line);
System.out.println(age);
System.out.println("我是try中的代码..."); //不执行
} catch (NumberFormatException e) {
System.out.println("我是catch中的代码..."); //执行
}
System.out.println("我是try...catch后面的代码..."); //执行

try {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的年龄:");
String line = sc.nextLine(); //输入正确数据: 18
int age = Integer.parseInt(line);
System.out.println(age);
System.out.println("我是try中的代码..."); //执行
} catch (NumberFormatException e) {
System.out.println("我是catch中的代码...");
}
System.out.println("我是try...catch后面的代码..."); //执行
}

throwable成员方法

throwable成员方法
    1. public String getMessage(); 返回详细消息字符串
    2. public String toString(); 返回简短描述
    3. public void printStackTrace(); 将异常错误信息打印在控制台(红色字体,注意这里的JVM默认处理方式不一样!)

public static void main(String[] args) {
try {
int[] arr = {1,2,3};
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException e) {
//1. public String getMessage(); 返回详细消息字符串
//String message = e.getMessage();
//System.out.println(message); //Index 3 out of bounds for length 3

//2. public String toString(); 返回简短描述
//String s = e.toString();
//System.out.println(s);
//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

//3. public void printStackTrace();
//将异常错误信息打印在控制台(红色字体,注意这里的JVM默认处理方式不一样!)
e.printStackTrace();
}
System.out.println("看我执行了吗?如果我执行了,那么就和JVM默认的处理方式不同哟!");
}

异常的小练习

自定义异常

自定义异常的步骤
    1. 定义异常类, 类名见名知意
    2. 继承关系, 一般继承运行时异常
    3. 提供空参和带参构造
    
代码示例

public class AgeOutOfBoundsException extends RuntimeException{
public AgeOutOfBoundsException() {
}

public AgeOutOfBoundsException(String message) {
super(message);
}
}
举报

相关推荐

0 条评论