Java基础进阶:时间类要点摘要,时间Date类实现格式化与解析源码实现详解,LocalDateTime时间类格式化与解析源码实现详解,Period,Duration获取时间间隔与源码实现,程序异常解析与处理方式
要点摘要
课堂笔记
日期相关
JDK7
日期类-Date
概述
表示一个时间点对象,这个时间点是以1970年1月1日为参考点;
作用
可以通过该类的对象,表示一个时间,并面向对象操作时间;
构造方法
直接利用空参数构造方法,即可获取当前时间对象;
常用方法
getTime()可以获取时间对象对应的毫秒值
格式化类-SimpleDateFormat
概述
专门用于将时间对象与字符串进行相互转换的工具类;
作用
1:可以将时间对象转字符串
2:可以将字符串转成时间对象
构造方法
传递一个字符串实参的构造方法
年: yyyy
月: MM
日: dd
时: HH
分: mm
秒: ss
星期: E
常用方法
parse(字符串) 将字符串转成时间对象
format(Date对象) 将时间对象转字符串
JDK8
日期类
分类
LocalDateTime 包含年月日时分秒信息的对象
LocalDate 包含年月日信息的对象
LocalTime 包含时分秒信息的对象
获取方式
1:利用静态方法 now() 获取当前时间对象
2:利用静态方法of(信息...) 获取指定信息对象
常用方法
1:getXxx() 以get开头的方法都是获取信息,后面可以是年,月,日...
2:plusXxx(数据量) 以plus开头的方法都是增加时间量,可正可负
3:withXxx(信息) 以with开头的方法都是修改对象的信息
4:format(DateTimeFormatter) 按照指定格式格式化该时间对象
5:parse(字符串,DateTimeFormatter) 按照指定格式解析字符串中的信息封装到新的时间对象中
格式化类-DateTimeFormatter
作用
配合JDK8的时间对象,完成格式化日期或解析字符串
获取方式
利用静态方法 ofPattern(String pattern)
常用方法
parse(字符串) 将字符串转成时间对象
format(JDK8时间对象) 将时间对象转字符串
日期间隔对象(时间段)
分类
1:Period 计算年月日
2:Duration 计算时分秒
获取方式
静态方法 between(时间1,时间2)
常用方法
getXxx() 直接获取年月日时分秒信息即可
异常相关
快速入门
概述
异常就是程序出现了不正常的情况
分类
编译时期异常(Exception系列)
运行时期异常(RuntimeException系列)
体系
其实RuntimeException是Exception的子类,但是RuntimeException太特殊了,所以另立门户了;
JVM对异常的默认处理方式
第1步:提示程序中出现异常的位置和原因;
第2步:结束程序;
进阶处理
为什么要处理异常
当程序中出现编译时期异常的时候,我们必须处理,不处理语法编译报错;
当程序中出现运行时期异常的时候,我们可以处理也可以不处理,可以根据自己的实际需求灵活选择,但是如果不处理,真的发生运行时异常时,JVM会按照默认处理方式处理发生的异常,如果我们写出了处理方案,那么JVM就会按照我们给出的处理方案处理异常,处理后,程序不会停止,可以继续执行;
如何处理异常
1:捕获处理
第1步
使用try{}catch(){}对可能发生异常的代码进行包裹
第2步
在catch(){}大括号中给出解决办法
相关API
一般会使用异常对象调用printStackTrace()方法,可以在控制台展示异常信息;(注意仅仅是展示异常信息而已,展示后,程序并不会停止运行)
2:声明抛出
使用throws关键字把这个异常交给方法的调用者处理;(相当于把处理异常的权利交给调用方法的人了)
自定义异常类
为什么要自定义异常类
因为java编写好的异常类不足以描述我们程序中的问题了;
如何自定义异常类
自定义的类继承java异常体系中的任意一个类即可,注意如果继承的是Exception系列,那么我们自定义的异常就属于编译时期异常,如果继承的是RuntimeException,那么我们自定义的异常就属于运行时期异常;(简单记: 喊爹即可)
如何处理自定义异常类
依然按照上面的异常处理方式处理;(参考进阶处理)
注意事项
throws和throw的区别
1:含义不同
throws表示声明异常;重在"声明"二字;
相当于告诉调用方法的人,方法中有发生异常的可能,强调的是一种可能性,所以即使执行了throws的代码,也有可能不发生异常
throw表示抛出异常;重在"抛出"二字;
也就是说一旦执行了这个代码,就一定会抛出一个异常对象,强调的是抛出异常的动作;
2:使用位置不同
throws用在方法声明后面,跟的是异常类名
throw用在方法体内,跟的是异常对象名
源码实现
1.时间日期类
1.1 Date类(应用)
计算机中时间原点
1970年1月1日 00:00:00
时间换算单位
1秒 = 1000毫秒
Date类概述
Date 代表了一个特定的时间,精确到毫秒
Date类构造方法
方法名 说明 public Date() 分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 public Date(long date) 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 示例代码
public class DateDemo01 {
public static void main(String[] args) {
//public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
Date d1 = new Date();
System.out.println(d1);
//public Date(long date):分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date = 1000*60*60;
Date d2 = new Date(date);
System.out.println(d2);
}
}
1.2 Date类常用方法(应用)
常用方法
方法名 说明 public long getTime() 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 public void setTime(long time) 设置时间,给的是毫秒值 示例代码
public class DateDemo02 {
public static void main(String[] args) {
//创建日期对象
Date d = new Date();
//public long getTime():获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
// System.out.println(d.getTime());
// System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
//public void setTime(long time):设置时间,给的是毫秒值
// long time = 1000*60*60;
long time = System.currentTimeMillis();
d.setTime(time);
System.out.println(d);
}
}
1.3 SimpleDateFormat类(应用)
SimpleDateFormat类概述
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
我们重点学习日期格式化和解析
SimpleDateFormat类构造方法
方法名 说明 public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认模式和日期格式 public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 SimpleDateFormat类的常用方法
格式化(从Date到String)
public final String format(Date date):将日期格式化成日期/时间字符串
解析(从String到Date)
public Date parse(String source):从给定字符串的开始解析文本以生成日期
示例代码
public class SimpleDateFormatDemo {
public static void main(String[] args) throws ParseException {
//格式化:从 Date 到 String
Date d = new Date();
// SimpleDateFormat sdf = new SimpleDateFormat();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s = sdf.format(d);
System.out.println(s);
System.out.println("--------");
//从 String 到 Date
String ss = "2048-08-09 11:11:11";
//ParseException
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf2.parse(ss);
System.out.println(dd);
}
}
1.4 时间日期类练习 (应用)
需求
秒杀开始时间是2020年11月11日 00:00:00,结束时间是2020年11月11日 00:10:00,用户小贾下单时间是2020年11月11日 00:03:47,用户小皮下单时间是2020年11月11日 00:10:11,判断用户有没有成功参与秒杀活动
实现步骤
判断下单时间是否在开始到结束的范围内
把字符串形式的时间变成毫秒值
代码实现
public class DateDemo5 {
public static void main(String[] args) throws ParseException {
//开始时间:2020年11月11日 0:0:0
//结束时间:2020年11月11日 0:10:0
//小贾2020年11月11日 0:03:47
//小皮2020年11月11日 0:10:11
//1.判断两位同学的下单时间是否在范围之内就可以了。
//2.要把每一个时间都换算成毫秒值。
String start = "2020年11月11日 0:0:0";
String end = "2020年11月11日 0:10:0";
String jia = "2020年11月11日 0:03:47";
String pi = "2020年11月11日 0:10:11";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
long startTime = sdf.parse(start).getTime();
long endTime = sdf.parse(end).getTime();
// System.out.println(startTime);
// System.out.println(endTime);
long jiaTime = sdf.parse(jia).getTime();
long piTime = sdf.parse(pi).getTime();
if(jiaTime >= startTime && jiaTime <= endTime){
System.out.println("小贾同学参加上了秒杀活动");
}else{
System.out.println("小贾同学没有参加上秒杀活动");
}
System.out.println("------------------------");
if(piTime >= startTime && piTime <= endTime){
System.out.println("小皮同学参加上了秒杀活动");
}else{
System.out.println("小皮同学没有参加上秒杀活动");
}
}
}
2.JDK8时间日期类
2.1 JDK8新增日期类 (理解)
LocalDate 表示日期(年月日)
LocalTime 表示时间(时分秒)
LocalDateTime 表示时间+ 日期 (年月日时分秒)
2.2 LocalDateTime创建方法 (应用)
方法说明
方法名 说明 public static LocalDateTime now() 获取当前系统时间 public static LocalDateTime of (年, 月 , 日, 时, 分, 秒) 使用指定年月日和时分秒初始化一个LocalDateTime对象 示例代码
public class JDK8DateDemo2 {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
System.out.println(localDateTime);
}
}
2.3 LocalDateTime获取方法 (应用)
方法说明
方法名 说明 public int getYear() 获取年 public int getMonthValue() 获取月份(1-12) public int getDayOfMonth() 获取月份中的第几天(1-31) public int getDayOfYear() 获取一年中的第几天(1-366) public DayOfWeek getDayOfWeek() 获取星期 public int getMinute() 获取分钟 public int getHour() 获取小时 示例代码
public class JDK8DateDemo3 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
//public int getYear() 获取年
int year = localDateTime.getYear();
System.out.println("年为" +year);
//public int getMonthValue() 获取月份(1-12)
int month = localDateTime.getMonthValue();
System.out.println("月份为" + month);
Month month1 = localDateTime.getMonth();
// System.out.println(month1);
//public int getDayOfMonth() 获取月份中的第几天(1-31)
int day = localDateTime.getDayOfMonth();
System.out.println("日期为" + day);
//public int getDayOfYear() 获取一年中的第几天(1-366)
int dayOfYear = localDateTime.getDayOfYear();
System.out.println("这是一年中的第" + dayOfYear + "天");
//public DayOfWeek getDayOfWeek()获取星期
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
System.out.println("星期为" + dayOfWeek);
//public int getMinute() 获取分钟
int minute = localDateTime.getMinute();
System.out.println("分钟为" + minute);
//public int getHour() 获取小时
int hour = localDateTime.getHour();
System.out.println("小时为" + hour);
}
}
2.4 LocalDateTime转换方法 (应用)
方法说明
方法名 说明 public LocalDate toLocalDate () 转换成为一个LocalDate对象 public LocalTime toLocalTime () 转换成为一个LocalTime对象 示例代码
public class JDK8DateDemo4 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 12, 12, 8, 10, 12);
//public LocalDate toLocalDate () 转换成为一个LocalDate对象
LocalDate localDate = localDateTime.toLocalDate();
System.out.println(localDate);
//public LocalTime toLocalTime () 转换成为一个LocalTime对象
LocalTime localTime = localDateTime.toLocalTime();
System.out.println(localTime);
}
}
2.5 LocalDateTime格式化和解析 (应用)
方法说明
方法名 说明 public String format (指定格式) 把一个LocalDateTime格式化成为一个字符串 public LocalDateTime parse (准备解析的字符串, 解析格式) 把一个日期字符串解析成为一个LocalDateTime对象 public static DateTimeFormatter ofPattern(String pattern) 使用指定的日期模板获取一个日期格式化器DateTimeFormatter对象 示例代码
public class JDK8DateDemo5 {
public static void main(String[] args) {
//method1();
//method2();
}
private static void method2() {
//public static LocalDateTime parse (准备解析的字符串, 解析格式) 把一个日期字符串解析成为一个LocalDateTime对象
String s = "2020年11月12日 13:14:15";
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime parse = LocalDateTime.parse(s, pattern);
System.out.println(parse);
}
private static void method1() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 12, 13, 14, 15);
System.out.println(localDateTime);
//public String format (指定格式) 把一个LocalDateTime格式化成为一个字符串
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String s = localDateTime.format(pattern);
System.out.println(s);
}
}
2.6 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 时间类添加或者减去时间的方法
*/
public class JDK8DateDemo6 {
public static void main(String[] args) {
//public LocalDateTime plusYears (long years) 添加或者减去年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
//LocalDateTime newLocalDateTime = localDateTime.plusYears(1);
//System.out.println(newLocalDateTime);
LocalDateTime newLocalDateTime = localDateTime.plusYears(-1);
System.out.println(newLocalDateTime);
}
}
2.7 LocalDateTime减少或者增加时间的方法 (应用)
方法说明
方法名 说明 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 时间类减少或者添加时间的方法
*/
public class JDK8DateDemo7 {
public static void main(String[] args) {
//public LocalDateTime minusYears (long years) 减去或者添加年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
//LocalDateTime newLocalDateTime = localDateTime.minusYears(1);
//System.out.println(newLocalDateTime);
LocalDateTime newLocalDateTime = localDateTime.minusYears(-1);
System.out.println(newLocalDateTime);
}
}
2.8 LocalDateTime修改方法 (应用)
方法说明
方法名 说明 public LocalDateTime withYear(int year) 直接修改年 public LocalDateTime withMonth(int month) 直接修改月 public LocalDateTime withDayOfMonth(int dayofmonth) 直接修改日期(一个月中的第几天) public LocalDateTime withDayOfYear(int dayOfYear) 直接修改日期(一年中的第几天) public LocalDateTime withHour(int hour) 直接修改小时 public LocalDateTime withMinute(int minute) 直接修改分钟 public LocalDateTime withSecond(int second) 直接修改秒 示例代码
/**
* JDK8 时间类修改时间
*/
public class JDK8DateDemo8 {
public static void main(String[] args) {
//public LocalDateTime withYear(int year) 修改年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
// LocalDateTime newLocalDateTime = localDateTime.withYear(2048);
// System.out.println(newLocalDateTime);
LocalDateTime newLocalDateTime = localDateTime.withMonth(20);
System.out.println(newLocalDateTime);
}
}
2.9 Period (应用)
方法说明
方法名 说明 public static Period between(开始时间,结束时间) 计算两个“时间"的间隔 public int getYears() 获得这段时间的年数 public int getMonths() 获得此期间的总月数 public int getDays() 获得此期间的天数 public long toTotalMonths() 获取此期间的总月数 示例代码
/**
* 计算两个时间的间隔
*/
public class JDK8DateDemo9 {
public static void main(String[] args) {
//public static Period between(开始时间,结束时间) 计算两个"时间"的间隔
LocalDate localDate1 = LocalDate.of(2020, 1, 1);
LocalDate localDate2 = LocalDate.of(2048, 12, 12);
Period period = Period.between(localDate1, localDate2);
System.out.println(period);//P28Y11M11D
//public int getYears() 获得这段时间的年数
System.out.println(period.getYears());//28
//public int getMonths() 获得此期间的月数
System.out.println(period.getMonths());//11
//public int getDays() 获得此期间的天数
System.out.println(period.getDays());//11
//public long toTotalMonths() 获取此期间的总月数
System.out.println(period.toTotalMonths());//347
}
}
2.10 Duration (应用)
方法说明
方法名 说明 public static Durationbetween(开始时间,结束时间) 计算两个“时间"的间隔 public long toSeconds() 获得此时间间隔的秒 public int toMillis() 获得此时间间隔的毫秒 public int toNanos() 获得此时间间隔的纳秒 示例代码
/**
* 计算两个时间的间隔
*/
public class JDK8DateDemo10 {
public static void main(String[] args) {
//public static Duration between(开始时间,结束时间) 计算两个“时间"的间隔
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 1, 1, 13, 14, 15);
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 1, 2, 11, 12, 13);
Duration duration = Duration.between(localDateTime1, localDateTime2);
System.out.println(duration);//PT21H57M58S
//public long toSeconds() 获得此时间间隔的秒
System.out.println(duration.toSeconds());//79078
//public int toMillis() 获得此时间间隔的毫秒
System.out.println(duration.toMillis());//79078000
//public int toNanos() 获得此时间间隔的纳秒
System.out.println(duration.toNanos());//79078000000000
}
}
3.异常
3.1 异常(记忆)
异常的概述
异常就是程序出现了不正常的情况
异常的体系结构
3.2 编译时异常和运行时异常的区别(记忆)
编译时异常
都是Exception类及其子类
必须显示处理,否则程序就会发生错误,无法通过编译
运行时异常
都是RuntimeException类及其子类
无需显示处理,也可以和编译时异常一样处理
图示
3.3 JVM默认处理异常的方式(理解)
如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
程序停止执行
3.4 查看异常信息 (理解)
控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置
我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码
3.5 throws方式处理异常(应用)
定义格式
public void 方法() throws 异常类名 {
}示例代码
public class ExceptionDemo {
public static void main(String[] args) throws ParseException{
System.out.println("开始");
// method();
method2();
System.out.println("结束");
}
//编译时异常
public static void method2() throws ParseException {
String s = "2048-08-09";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
//运行时异常
public static void method() throws ArrayIndexOutOfBoundsException {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}
}注意事项
这个throws格式是跟在方法的括号后面的
编译时异常必须要进行处理,两种处理方案:try...catch …或者 throws,如果采用 throws 这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理
运行时异常因为在运行时才会发生,所以在方法后面可以不写,运行时出现异常默认交给jvm处理
3.6 throw抛出异常 (应用)
格式
throw new 异常();
注意
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
throws和throw的区别
THROWS THROW 用在方法声明后面,跟的是异常类名 用在方法体内,跟的是异常对象名 表示声明异常,调用该方法有可能会出现这样的异常 表示手动抛出异常对象,由方法体内的语句处理 示例代码
public class ExceptionDemo8 {
public static void main(String[] args) {
//int [] arr = {1,2,3,4,5};
int [] arr = null;
printArr(arr);//就会 接收到一个异常.
//我们还需要自己处理一下异常.
}
private static void printArr(int[] arr) {
if(arr == null){
//调用者知道成功打印了吗?
//System.out.println("参数不能为null");
throw new NullPointerException(); //当参数为null的时候
//手动创建了一个异常对象,抛给了调用者,产生了一个异常
}else{
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
3.7 try-catch方式处理异常(应用)
定义格式
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}执行流程
程序从 try 里面的代码开始执行
出现异常,就会跳转到对应的 catch 里面去执行
执行完毕之后,程序还可以继续往下执行
示例代码
public class ExceptionDemo01 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
} public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你访问的数组索引不存在,请回去修改为正确的索引");
}
}
}注意
如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码
如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码
如果出现的问题没有被捕获,那么程序如何运行?
那么try...catch就相当于没有写.那么也就是自己没有处理.默认交给虚拟机处理.
同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面
3.8 Throwable成员方法(应用)
常用方法
方法名 说明 public String getMessage() 返回此 throwable 的详细消息字符串 public String toString() 返回此可抛出的简短描述 public void printStackTrace() 把异常的错误信息输出在控制台 示例代码
public class ExceptionDemo02 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
} public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
// e.printStackTrace(); //public String getMessage():返回此 throwable 的详细消息字符串
// System.out.println(e.getMessage());
//Index 3 out of bounds for length 3 //public String toString():返回此可抛出的简短描述
// System.out.println(e.toString());
//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 //public void printStackTrace():把异常的错误信息输出在控制台
e.printStackTrace();
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
// at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11) }
}
}
3.9 异常的练习 (应用)
需求
键盘录入学生的姓名和年龄,其中年龄为18 - 25岁,超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止
实现步骤
创建学生对象
键盘录入姓名和年龄,并赋值给学生对象
如果是非法数据就再次录入
代码实现
学生类
public class Student {
private String name;
private int age; public Student() {
} public Student(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
if(age >= 18 && age <= 25){
this.age = age;
}else{
//当年龄不合法时,产生一个异常
throw new RuntimeException("年龄超出了范围");
}
} @Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}测试类
public class ExceptionDemo12 {
public static void main(String[] args) {
// 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁,
// 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
s.setName(name);
while(true){
System.out.println("请输入年龄");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
s.setAge(age);
break;
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
continue;
} catch (AgeOutOfBoundsException e) {
System.out.println(e.toString());
System.out.println("请输入一个符合范围的年龄");
continue;
}
/*if(age >= 18 && age <=25){
s.setAge(age);
break;
}else{
System.out.println("请输入符合要求的年龄");
continue;
}*/
}
System.out.println(s); }
}
3.10 自定义异常(应用)
自定义异常概述
当Java中提供的异常不能满足我们的需求时,我们可以自定义异常
实现步骤
定义异常类
写继承关系
提供空参构造
提供带参构造
代码实现
异常类
public class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
} public AgeOutOfBoundsException(String message) {
super(message);
}
}学生类
public class Student {
private String name;
private int age; public Student() {
} public Student(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
if(age >= 18 && age <= 25){
this.age = age;
}else{
//如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常
throw new AgeOutOfBoundsException("年龄超出了范围");
}
} @Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}测试类
public class ExceptionDemo12 {
public static void main(String[] args) {
// 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁,
// 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
s.setName(name);
while(true){
System.out.println("请输入年龄");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
s.setAge(age);
break;
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
continue;
} catch (AgeOutOfBoundsException e) {
System.out.println(e.toString());
System.out.println("请输入一个符合范围的年龄");
continue;
}
/*if(age >= 18 && age <=25){
s.setAge(age);
break;
}else{
System.out.println("请输入符合要求的年龄");
continue;
}*/
}
System.out.println(s); }
}
1.时间日期类
1.1 Date类(应用)
计算机中时间原点
1970年1月1日 00:00:00
时间换算单位
1秒 = 1000毫秒
Date类概述
Date 代表了一个特定的时间,精确到毫秒
Date类构造方法
方法名 说明 public Date() 分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 public Date(long date) 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 示例代码
public class DateDemo01 {
public static void main(String[] args) {
//public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
Date d1 = new Date();
System.out.println(d1);
//public Date(long date):分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date = 1000*60*60;
Date d2 = new Date(date);
System.out.println(d2);
}
}
1.2 Date类常用方法(应用)
常用方法
方法名 说明 public long getTime() 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 public void setTime(long time) 设置时间,给的是毫秒值 示例代码
public class DateDemo02 {
public static void main(String[] args) {
//创建日期对象
Date d = new Date();
//public long getTime():获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
// System.out.println(d.getTime());
// System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
//public void setTime(long time):设置时间,给的是毫秒值
// long time = 1000*60*60;
long time = System.currentTimeMillis();
d.setTime(time);
System.out.println(d);
}
}
1.3 SimpleDateFormat类(应用)
SimpleDateFormat类概述
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
我们重点学习日期格式化和解析
SimpleDateFormat类构造方法
方法名 说明 public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认模式和日期格式 public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 SimpleDateFormat类的常用方法
格式化(从Date到String)
public final String format(Date date):将日期格式化成日期/时间字符串
解析(从String到Date)
public Date parse(String source):从给定字符串的开始解析文本以生成日期
示例代码
public class SimpleDateFormatDemo {
public static void main(String[] args) throws ParseException {
//格式化:从 Date 到 String
Date d = new Date();
// SimpleDateFormat sdf = new SimpleDateFormat();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s = sdf.format(d);
System.out.println(s);
System.out.println("--------");
//从 String 到 Date
String ss = "2048-08-09 11:11:11";
//ParseException
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf2.parse(ss);
System.out.println(dd);
}
}
1.4 时间日期类练习 (应用)
需求
秒杀开始时间是2020年11月11日 00:00:00,结束时间是2020年11月11日 00:10:00,用户小贾下单时间是2020年11月11日 00:03:47,用户小皮下单时间是2020年11月11日 00:10:11,判断用户有没有成功参与秒杀活动
实现步骤
判断下单时间是否在开始到结束的范围内
把字符串形式的时间变成毫秒值
代码实现
public class DateDemo5 {
public static void main(String[] args) throws ParseException {
//开始时间:2020年11月11日 0:0:0
//结束时间:2020年11月11日 0:10:0
//小贾2020年11月11日 0:03:47
//小皮2020年11月11日 0:10:11
//1.判断两位同学的下单时间是否在范围之内就可以了。
//2.要把每一个时间都换算成毫秒值。
String start = "2020年11月11日 0:0:0";
String end = "2020年11月11日 0:10:0";
String jia = "2020年11月11日 0:03:47";
String pi = "2020年11月11日 0:10:11";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
long startTime = sdf.parse(start).getTime();
long endTime = sdf.parse(end).getTime();
// System.out.println(startTime);
// System.out.println(endTime);
long jiaTime = sdf.parse(jia).getTime();
long piTime = sdf.parse(pi).getTime();
if(jiaTime >= startTime && jiaTime <= endTime){
System.out.println("小贾同学参加上了秒杀活动");
}else{
System.out.println("小贾同学没有参加上秒杀活动");
}
System.out.println("------------------------");
if(piTime >= startTime && piTime <= endTime){
System.out.println("小皮同学参加上了秒杀活动");
}else{
System.out.println("小皮同学没有参加上秒杀活动");
}
}
}
2.JDK8时间日期类
2.1 JDK8新增日期类 (理解)
LocalDate 表示日期(年月日)
LocalTime 表示时间(时分秒)
LocalDateTime 表示时间+ 日期 (年月日时分秒)
2.2 LocalDateTime创建方法 (应用)
方法说明
方法名 说明 public static LocalDateTime now() 获取当前系统时间 public static LocalDateTime of (年, 月 , 日, 时, 分, 秒) 使用指定年月日和时分秒初始化一个LocalDateTime对象 示例代码
public class JDK8DateDemo2 {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
System.out.println(localDateTime);
}
}
2.3 LocalDateTime获取方法 (应用)
方法说明
方法名 说明 public int getYear() 获取年 public int getMonthValue() 获取月份(1-12) public int getDayOfMonth() 获取月份中的第几天(1-31) public int getDayOfYear() 获取一年中的第几天(1-366) public DayOfWeek getDayOfWeek() 获取星期 public int getMinute() 获取分钟 public int getHour() 获取小时 示例代码
public class JDK8DateDemo3 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
//public int getYear() 获取年
int year = localDateTime.getYear();
System.out.println("年为" +year);
//public int getMonthValue() 获取月份(1-12)
int month = localDateTime.getMonthValue();
System.out.println("月份为" + month);
Month month1 = localDateTime.getMonth();
// System.out.println(month1);
//public int getDayOfMonth() 获取月份中的第几天(1-31)
int day = localDateTime.getDayOfMonth();
System.out.println("日期为" + day);
//public int getDayOfYear() 获取一年中的第几天(1-366)
int dayOfYear = localDateTime.getDayOfYear();
System.out.println("这是一年中的第" + dayOfYear + "天");
//public DayOfWeek getDayOfWeek()获取星期
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
System.out.println("星期为" + dayOfWeek);
//public int getMinute() 获取分钟
int minute = localDateTime.getMinute();
System.out.println("分钟为" + minute);
//public int getHour() 获取小时
int hour = localDateTime.getHour();
System.out.println("小时为" + hour);
}
}
2.4 LocalDateTime转换方法 (应用)
方法说明
方法名 说明 public LocalDate toLocalDate () 转换成为一个LocalDate对象 public LocalTime toLocalTime () 转换成为一个LocalTime对象 示例代码
public class JDK8DateDemo4 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 12, 12, 8, 10, 12);
//public LocalDate toLocalDate () 转换成为一个LocalDate对象
LocalDate localDate = localDateTime.toLocalDate();
System.out.println(localDate);
//public LocalTime toLocalTime () 转换成为一个LocalTime对象
LocalTime localTime = localDateTime.toLocalTime();
System.out.println(localTime);
}
}
2.5 LocalDateTime格式化和解析 (应用)
方法说明
方法名 说明 public String format (指定格式) 把一个LocalDateTime格式化成为一个字符串 public LocalDateTime parse (准备解析的字符串, 解析格式) 把一个日期字符串解析成为一个LocalDateTime对象 public static DateTimeFormatter ofPattern(String pattern) 使用指定的日期模板获取一个日期格式化器DateTimeFormatter对象 示例代码
public class JDK8DateDemo5 {
public static void main(String[] args) {
//method1();
//method2();
}
private static void method2() {
//public static LocalDateTime parse (准备解析的字符串, 解析格式) 把一个日期字符串解析成为一个LocalDateTime对象
String s = "2020年11月12日 13:14:15";
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime parse = LocalDateTime.parse(s, pattern);
System.out.println(parse);
}
private static void method1() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 12, 13, 14, 15);
System.out.println(localDateTime);
//public String format (指定格式) 把一个LocalDateTime格式化成为一个字符串
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String s = localDateTime.format(pattern);
System.out.println(s);
}
}
2.6 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 时间类添加或者减去时间的方法
*/
public class JDK8DateDemo6 {
public static void main(String[] args) {
//public LocalDateTime plusYears (long years) 添加或者减去年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
//LocalDateTime newLocalDateTime = localDateTime.plusYears(1);
//System.out.println(newLocalDateTime);
LocalDateTime newLocalDateTime = localDateTime.plusYears(-1);
System.out.println(newLocalDateTime);
}
}
2.7 LocalDateTime减少或者增加时间的方法 (应用)
方法说明
方法名 说明 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 时间类减少或者添加时间的方法
*/
public class JDK8DateDemo7 {
public static void main(String[] args) {
//public LocalDateTime minusYears (long years) 减去或者添加年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
//LocalDateTime newLocalDateTime = localDateTime.minusYears(1);
//System.out.println(newLocalDateTime);
LocalDateTime newLocalDateTime = localDateTime.minusYears(-1);
System.out.println(newLocalDateTime);
}
}
2.8 LocalDateTime修改方法 (应用)
方法说明
方法名 说明 public LocalDateTime withYear(int year) 直接修改年 public LocalDateTime withMonth(int month) 直接修改月 public LocalDateTime withDayOfMonth(int dayofmonth) 直接修改日期(一个月中的第几天) public LocalDateTime withDayOfYear(int dayOfYear) 直接修改日期(一年中的第几天) public LocalDateTime withHour(int hour) 直接修改小时 public LocalDateTime withMinute(int minute) 直接修改分钟 public LocalDateTime withSecond(int second) 直接修改秒 示例代码
/**
* JDK8 时间类修改时间
*/
public class JDK8DateDemo8 {
public static void main(String[] args) {
//public LocalDateTime withYear(int year) 修改年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
// LocalDateTime newLocalDateTime = localDateTime.withYear(2048);
// System.out.println(newLocalDateTime);
LocalDateTime newLocalDateTime = localDateTime.withMonth(20);
System.out.println(newLocalDateTime);
}
}
2.9 Period (应用)
方法说明
方法名 说明 public static Period between(开始时间,结束时间) 计算两个“时间"的间隔 public int getYears() 获得这段时间的年数 public int getMonths() 获得此期间的总月数 public int getDays() 获得此期间的天数 public long toTotalMonths() 获取此期间的总月数 示例代码
/**
* 计算两个时间的间隔
*/
public class JDK8DateDemo9 {
public static void main(String[] args) {
//public static Period between(开始时间,结束时间) 计算两个"时间"的间隔
LocalDate localDate1 = LocalDate.of(2020, 1, 1);
LocalDate localDate2 = LocalDate.of(2048, 12, 12);
Period period = Period.between(localDate1, localDate2);
System.out.println(period);//P28Y11M11D
//public int getYears() 获得这段时间的年数
System.out.println(period.getYears());//28
//public int getMonths() 获得此期间的月数
System.out.println(period.getMonths());//11
//public int getDays() 获得此期间的天数
System.out.println(period.getDays());//11
//public long toTotalMonths() 获取此期间的总月数
System.out.println(period.toTotalMonths());//347
}
}
2.10 Duration (应用)
方法说明
方法名 说明 public static Durationbetween(开始时间,结束时间) 计算两个“时间"的间隔 public long toSeconds() 获得此时间间隔的秒 public int toMillis() 获得此时间间隔的毫秒 public int toNanos() 获得此时间间隔的纳秒 示例代码
/**
* 计算两个时间的间隔
*/
public class JDK8DateDemo10 {
public static void main(String[] args) {
//public static Duration between(开始时间,结束时间) 计算两个“时间"的间隔
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 1, 1, 13, 14, 15);
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 1, 2, 11, 12, 13);
Duration duration = Duration.between(localDateTime1, localDateTime2);
System.out.println(duration);//PT21H57M58S
//public long toSeconds() 获得此时间间隔的秒
System.out.println(duration.toSeconds());//79078
//public int toMillis() 获得此时间间隔的毫秒
System.out.println(duration.toMillis());//79078000
//public int toNanos() 获得此时间间隔的纳秒
System.out.println(duration.toNanos());//79078000000000
}
}
3.异常
3.1 异常(记忆)
异常的概述
异常就是程序出现了不正常的情况
异常的体系结构
3.2 编译时异常和运行时异常的区别(记忆)
编译时异常
都是Exception类及其子类
必须显示处理,否则程序就会发生错误,无法通过编译
运行时异常
都是RuntimeException类及其子类
无需显示处理,也可以和编译时异常一样处理
图示
3.3 JVM默认处理异常的方式(理解)
如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
程序停止执行
3.4 查看异常信息 (理解)
控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置
我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码
3.5 throws方式处理异常(应用)
定义格式
public void 方法() throws 异常类名 {
}示例代码
public class ExceptionDemo {
public static void main(String[] args) throws ParseException{
System.out.println("开始");
// method();
method2();
System.out.println("结束");
}
//编译时异常
public static void method2() throws ParseException {
String s = "2048-08-09";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
//运行时异常
public static void method() throws ArrayIndexOutOfBoundsException {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}
}注意事项
这个throws格式是跟在方法的括号后面的
编译时异常必须要进行处理,两种处理方案:try...catch …或者 throws,如果采用 throws 这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理
运行时异常因为在运行时才会发生,所以在方法后面可以不写,运行时出现异常默认交给jvm处理
3.6 throw抛出异常 (应用)
格式
throw new 异常();
注意
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
throws和throw的区别
THROWS THROW 用在方法声明后面,跟的是异常类名 用在方法体内,跟的是异常对象名 表示声明异常,调用该方法有可能会出现这样的异常 表示手动抛出异常对象,由方法体内的语句处理 示例代码
public class ExceptionDemo8 {
public static void main(String[] args) {
//int [] arr = {1,2,3,4,5};
int [] arr = null;
printArr(arr);//就会 接收到一个异常.
//我们还需要自己处理一下异常.
}
private static void printArr(int[] arr) {
if(arr == null){
//调用者知道成功打印了吗?
//System.out.println("参数不能为null");
throw new NullPointerException(); //当参数为null的时候
//手动创建了一个异常对象,抛给了调用者,产生了一个异常
}else{
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
3.7 try-catch方式处理异常(应用)
定义格式
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}执行流程
程序从 try 里面的代码开始执行
出现异常,就会跳转到对应的 catch 里面去执行
执行完毕之后,程序还可以继续往下执行
示例代码
public class ExceptionDemo01 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
} public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你访问的数组索引不存在,请回去修改为正确的索引");
}
}
}注意
如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码
如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码
如果出现的问题没有被捕获,那么程序如何运行?
那么try...catch就相当于没有写.那么也就是自己没有处理.默认交给虚拟机处理.
同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面
3.8 Throwable成员方法(应用)
常用方法
方法名 说明 public String getMessage() 返回此 throwable 的详细消息字符串 public String toString() 返回此可抛出的简短描述 public void printStackTrace() 把异常的错误信息输出在控制台 示例代码
public class ExceptionDemo02 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
} public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
// e.printStackTrace(); //public String getMessage():返回此 throwable 的详细消息字符串
// System.out.println(e.getMessage());
//Index 3 out of bounds for length 3 //public String toString():返回此可抛出的简短描述
// System.out.println(e.toString());
//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 //public void printStackTrace():把异常的错误信息输出在控制台
e.printStackTrace();
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
// at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11) }
}
}
3.9 异常的练习 (应用)
需求
键盘录入学生的姓名和年龄,其中年龄为18 - 25岁,超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止
实现步骤
创建学生对象
键盘录入姓名和年龄,并赋值给学生对象
如果是非法数据就再次录入
代码实现
学生类
public class Student {
private String name;
private int age; public Student() {
} public Student(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
if(age >= 18 && age <= 25){
this.age = age;
}else{
//当年龄不合法时,产生一个异常
throw new RuntimeException("年龄超出了范围");
}
} @Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}测试类
public class ExceptionDemo12 {
public static void main(String[] args) {
// 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁,
// 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
s.setName(name);
while(true){
System.out.println("请输入年龄");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
s.setAge(age);
break;
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
continue;
} catch (AgeOutOfBoundsException e) {
System.out.println(e.toString());
System.out.println("请输入一个符合范围的年龄");
continue;
}
/*if(age >= 18 && age <=25){
s.setAge(age);
break;
}else{
System.out.println("请输入符合要求的年龄");
continue;
}*/
}
System.out.println(s); }
}
3.10 自定义异常(应用)
自定义异常概述
当Java中提供的异常不能满足我们的需求时,我们可以自定义异常
实现步骤
定义异常类
写继承关系
提供空参构造
提供带参构造
代码实现
异常类
public class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
} public AgeOutOfBoundsException(String message) {
super(message);
}
}学生类
public class Student {
private String name;
private int age; public Student() {
} public Student(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
if(age >= 18 && age <= 25){
this.age = age;
}else{
//如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常
throw new AgeOutOfBoundsException("年龄超出了范围");
}
} @Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}测试类
public class ExceptionDemo12 {
public static void main(String[] args) {
// 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁,
// 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
s.setName(name);
while(true){
System.out.println("请输入年龄");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
s.setAge(age);
break;
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
continue;
} catch (AgeOutOfBoundsException e) {
System.out.println(e.toString());
System.out.println("请输入一个符合范围的年龄");
continue;
}
/*if(age >= 18 && age <=25){
s.setAge(age);
break;
}else{
System.out.println("请输入符合要求的年龄");
continue;
}*/
}
System.out.println(s); }
}
扩展练习
编程题(时间日期相关)
题目1
请在控制台以“xxxx年xx月xx日 xx时xx分xx秒”的格式打印当前系统时间。
要求:
1:使用Date+SimpleDateFormat完成一遍,
2:再使用LocalDateTime+DateTimeFormatter完成一遍;
提示:
获取当前时间对象之后,直接利用格式化工具格式化即可;
参考代码:
package day6.No_1;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class Demo {
public static void main(String[] args) {
Date date =new Date();
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
System.out.println(simpleDateFormat.format(date));
LocalDateTime time = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
System.out.println(time.format(dateTimeFormatter));
}
}
题目2
请输入“您的生日”,格式:yyyy-MM-dd,使用程序计算您已经来到这个世界多少天了。
提示:
本题利用JDK8中的LocalDate加DateTimeFormatter和Period即可实现;
效果演示:
参考代码:
package day6.No_2;
import java.time.LocalDate;
import java.time.Period;
public class Demo {
public static void main(String[] args) {
LocalDate localDate = LocalDate.of(1999, 11, 25);
LocalDate localDate1 = LocalDate.of(2020, 11, 8);
Period between = Period.between(localDate, localDate1);
int years = between.getYears();//获取年
int months = between.getMonths();//获取月
int days = between.getDays();//获取天
System.out.println("你已经来这个世界"+years+"年零 "+months+"月零 "+days+"天");
}
}
题目3
请从控制台分别接收两个“生日”,格式为:yyyy年MM月dd日,用程序比较两个生日表示的人的年龄大小关系并打印出结果;
要求:
1:使用Date+SimpleDateFormat完成一遍,
2:再使用LocalDate+DateTimeFormatter完成一遍;
提示:
注意,生日值越小,证明出生的越早,就意味着年龄越大,不要搞反了呦;
运行结果:
参考代码:
package day6.No_3;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
/*
键盘录入字符串
使用Date/Loca将字符串转换为毫秒
对比二者毫秒值
*/
public class Demo {
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个生日(****年**月**日)");
String s1 = sc.next();
System.out.println("请输入第一个生日(****年**月**日)");
String s2 = sc.next();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
LocalDate localDate = LocalDate.parse(s1, dateTimeFormatter);
LocalDate localDate1 = LocalDate.parse(s2, dateTimeFormatter);
// LocalDate+DateTimeFormatter实现对比
if (localDate.isAfter(localDate1)) {
System.out.println("第二个大");
}
if (localDate.isBefore(localDate1)) {
System.out.println("第一个大");
}if (localDate.isEqual(localDate1)){
System.out.println("一样大");
}
// Date SimpleDateFormat实现对比:
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
try {
long time1 = simpleDateFormat.parse(s1).getTime();
long time2 = simpleDateFormat.parse(s2).getTime();
if (time1 > time2) {
System.out.println("第二个大");
} else if (time1<time2){
System.out.println("第一个大");
}else {
System.out.println("一样大");
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
编程题(异常)
题目1
按要求补全代码,使main方法能够正常执行到结束;
public static void main(String[] args){
int[] arr = new int[0];
//提示:下面这一行代码会导致方法内抛出“空指针异常”,需要你补充一些代码,使让程序继续执行
int n1 = getMax(null);
//提示:下面这一行代码会导致方法内抛出“索引越界异常”,需要你补充一些代码,使让程序继续执行
int n2 = getMax(arr);
int[] arr2 = {1,2,4,24,32,5324,32};
int n3 = getMax(arr2);
System.out.println("程序终于执行完了...");
}
//获取数组最大值
public static int getMax(int[] args){
int max = args[0];
for(int i = 1 ; i < args.length ; i++){
if(max < args[i]){
max = args[i];
}
}
return max;
}
提示:
可以利用异常的技术,捕获程序中的异常,然后可以让程序继续执行;
效果:
参考代码:
package day6.No_4;
public class Demo {
public static void main(String[] args){
int[] arr = new int[0];
//提示:下面这一行代码会导致方法内抛出“空指针异常”,需要你补充一些代码,使让程序继续执行
try {
int n1 = getMax(null);
} catch (NullPointerException e) {
System.out.println("捕获了一个空指针...程序继续运行");
}
//提示:下面这一行代码会导致方法内抛出“索引越界异常”,需要你补充一些代码,使让程序继续执行
try {
int n2 = getMax(arr);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("捕获了索引越界异常...程序继续");
}
int[] arr2 = {1,2,4,24,32,5324,32};
int n3 = getMax(arr2);
System.out.println("程序终于执行完了...");
}
//获取数组最大值
public static int getMax(int[] args){
int max = args[0];
for(int i = 1 ; i < args.length ; i++){
if(max < args[i]){
max = args[i];
}
}
return max;
}
}
题目2
请从控制台接收两个整数并计算两个数的商,使用程序控制,如果用户输入的不是整数,则提示用户重新输入;
提示:
注意:如果我们使用nextInt方法让用户输入整数,但用户实际输入的不是整数的时候,会发生异常,而对于一个键盘输入对象来说,一旦发生异常,即使使用try{}catch(){}语句进行了处理,这个键盘输入对象也无法继续工作了,解决的办法就是重写创建新的键盘输入对象即可;
效果:
参考代码:
package day6.No_5;
import java.math.BigDecimal;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while (true) {
try {
sc=new Scanner(System.in);
System.out.println("请输入第一个整数:");
int i1 = sc.nextInt();
System.out.println("请输入第二个整数:");
int i2 = sc.nextInt();
System.out.println(i1 + "除以" + i2 + "=" + (i1 / i2));
break;
} catch (InputMismatchException e) {
System.out.println("请输入整数");
}
}
}
}
题目3
自定义一个键盘输入的工具类,提供3个静态方法,分别完成让用户输入整数,小数,和字符串的功能,且当用户输入错误的时候,不能结束程序,要给用户重新输入的机会;
提示:
其实就是把上一题中处理异常和键盘输入的代码抽取出来,形成一个独立的工具类即可;
效果:
参考代码:
package day6.No_6;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
int num = Num();
System.out.println("整数为:"+num);
Double xiaoshu = Xiaoshu();
System.out.println("小数为:"+xiaoshu);
String zifu = Zifu();
System.out.println("字符为:"+zifu);
}
public static int Num() {
Scanner sc = new Scanner(System.in);
while (true) {
sc = new Scanner(System.in);
System.out.println("请输入整数:");
try {
int anInt = sc.nextInt();
return anInt;
} catch (Exception e) {
System.out.println("必须为整数");
}
}
}
public static Double Xiaoshu() {
Scanner sc = new Scanner(System.in);
while (true) {
sc = new Scanner(System.in);
System.out.println("请输入小数:");
try {
Double andouble = sc.nextDouble();
return andouble;
} catch (Exception e) {
System.out.println("必须为小数");
}
}
}
public static String Zifu() {
Scanner sc = new Scanner(System.in);
sc = new Scanner(System.in);
System.out.println("请输入字符:");
String s = sc.next();
return s;
}
}
Java基础进阶:时间类要点摘要,时间Date类实现格式化与解析源码实现详解,LocalDateTime时间类格式化与解析源码实现详解,Period,Duration获取时间间隔与源码实现,程序异常解析与处理方式的更多相关文章
- Java基础进阶:内部类lambda重点摘要,详细讲解成员内部类,局部内部类,匿名内部类,Lambda表达式,Lambda表达式和匿名内部类的区别,附重难点,代码实现源码,课堂笔记,课后扩展及答案
内部类lambda重点摘要 内部类特点: 内部类可以直接访问外部类,包括私有 外部类访问内部类必须创建对象 创建内部对象格式: 外部类.内部类 对象名=new外部类().new内部类(); 静态内部类 ...
- Java基础进阶
Java基础进阶J Object类 hashcode() toString() clone() getClass() notify() wait() equals() Random类 生成 随机数 U ...
- 第二十八节:Java基础-进阶继承,抽象类,接口
前言 Java基础-进阶继承,抽象类,接口 进阶继承 class Stu { int age = 1; } class Stuo extends Stu { int agee = 2; } class ...
- Java基础进阶:多态与接口重点摘要,类和接口,接口特点,接口详解,多态详解,多态中的成员访问特点,多态的好处和弊端,多态的转型,多态存在的问题,附重难点,代码实现源码,课堂笔记,课后扩展及答案
多态与接口重点摘要 接口特点: 接口用interface修饰 interface 接口名{} 类实现接口用implements表示 class 类名 implements接口名{} 接口不能实例化,可 ...
- Java基础进阶:继承重点摘要,继承详解,方法重写注意事项,方法重载与重写的区别,抽象类,代码块, 附重难点,代码实现源码,课堂笔记,课后扩展及答案
继承重点摘要 *继承的特点: 子类在初始化之前,一定要先完成父类数据的初始化 子类在初始化之前,一定要先访问父类构造,完成父类数据的初始化 系统在每一个构造方法中默认隐藏了一句super(); 如果我 ...
- java基础进阶一:String源码和String常量池
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8046564.html 邮箱:moyi@moyib ...
- Java基础进阶:APi使用,Math,Arrarys,Objects工具类,自动拆装箱,字符串与基本数据类型互转,递归算法源码,冒泡排序源码实现,快排实现源码,附重难点,代码实现源码,课堂笔记,课后扩展及答案
要点摘要 Math: 类中么有构造方法,内部方法是静态的,可以直接类名.方式调用 常用: Math.abs(int a):返回参数绝对值 Math.ceil(double a):返回大于或等于参数的最 ...
- Java基础进阶整理
Java学习笔记整理 本文档是我个人整理的,首先是想通过完成本文档更加扎实自己的基础加强对java语言的理解,然后就是想给入了门的同志们做下贡献. 当然,本文档主要是对java语言基础(当然还有很多基 ...
- 笔记-迎难而上之Java基础进阶3
统计字符串中每一个不同的字符 import java.util.*; //统计字符串每一个字符出现的字数 public class StringDemo{ public static void mai ...
随机推荐
- mongodb 副本集之入门篇
作者: 凹凸曼-军军 前言:mongodb 因为高性能.高可用性.支持分片等特性,作为非关系型数据库被大家广泛使用.其高可用性主要是体现在 mongodb 的副本集上面(可以简单理解为一主多从的集群) ...
- Contest 1435
A \(x\times-y+y\times x=0\),因为 \(n\) 是偶数,所以两两这样构造即可. 时间复杂度 \(O\left(Tn\right)\). B 有点绕的题,要理清思路. 发现行和 ...
- 经典算法—BF算法(字符串匹配)
前言 字符串的匹配算法也是很经典的一个算法,在面试的时候常常会遇到,而BF算法是字符串模式匹配中的一个简单的算法 1,什么是BF算法 BF算法,即暴力(Brute Force)算法,是普通的模式匹配算 ...
- win10下安装anaconda3+tensorflow
安装了三天终于安装成功了,今天简单写下自己的安装步骤 1.下载可以在Anaconda3官网下载:https://www.anaconda.com/products/individual 也可以通过清华 ...
- rest-framework:频率控制
一 频率简介: 为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次 二 自定义频率类,自定义频率规则: 自定义的逻辑 #(1)取出访问者ip # (2)判断当前ip不在访问字典里,添加 ...
- Error:Execution failed for task ':app:mergeDebugResources'. > Error: Some file crunching failed, see logs for details
android studio中的资源文件命名是不能带有数字的,因为会与R类的资源ID起冲突,所以编译就发生了错误.
- charles功能(二)修改response请求参数
1.接口处 鼠标右击,选择breakpoints(允许本接口使用breakpionts功能) 2.开始设置断点值 4.重新请求接口(charles的界面变为可编辑状态),修改请求参数,执行请求 5.最 ...
- 第三十二章、使用splitDockWidget和tabifyDockWidget嵌套布局QDockWidget的PyQt人机对话案例
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 在第<第三十一章.containers容器类部件QDo ...
- Object.prototype.toString.call()为什么可以用来检测数据类型?
obj.toString()方法是用来干什么的 每一个对象都有一个toString()方法,默认情况下toString()被每一个Object对象继承,如果此方法未被重写,toString()返回&q ...
- PostMan设置环境变量&全局变量
一.设置环境变量 1.点击右上角Manage Environment,进入环境变量设置界面 2.定义环境名称,参数名及参数值 3.将接口地址中服务器地址进行参数化,并选择对应的环境执行 二.设置全局变 ...