1. JDK7-Date类
我们先来看时间的相关知识点
-
世界标准时间:
格林尼治时间/格林威治时间(Greenwich Mean Time)简称GMT。目前世界标准时间(UTC)已经替换为:原子钟
-
中国标准时间: 世界标准时间+8小时
时间单位换算:
-
1秒=1000毫秒
-
1毫秒=1000微秒
-
1微秒=1000纳秒
Date类
Date类是一个JDK写好的Javabean类,用来描述时间,精确到毫秒。
- 利用空参构造创建的对象,默认表示系统当前时间。
- 利用有参构造创建的对象,表示指定的时间。
我们给出一些常用的方法和构造方法:
- 构造方法
方法 | 说明 |
---|---|
public Date() | 创建Date对象,表示当前时间 |
public Date(long date) | 创建Date对象,表示指定时间 |
- 成员方法
方法 | 说明 |
---|---|
public void setTime(long time) | 设置/修改毫秒值 |
public long getTime() | 获取时间对象的毫秒值 |
代码示例:
Date d1 = new Date();
System.out.println(d1);
//表示一个指定的时间
Date d2 = new Date(1000L);
System.out.println(d2);
//设置一个时间
d2.setTime(1000L);//从时间原点开始设置
System.out.println(d2);
//获取当前时间的毫秒值
long time = d2.getTime();//返回值为long类型
System.out.println(time);
输出结果为:
这里给上其他例子:
- 获取时间原点一年以后的时间
- 随机创建两个时间对象并比较
代码示例:
System.out.println("--------------------");
//时间原点一年以后的时间
long time1 = 1000L * 60 * 60 * 24 * 365;
Date d3 = new Date(time1);
System.out.println(d3);
System.out.println("--------------------");
//获取两个随机时间
Random r = new Random();
Date d4 = new Date(Math.abs(r.nextInt()));
Date d5 = new Date(Math.abs(r.nextInt()));
System.out.println(d4);
System.out.println(d5);
//时间的比较使用gettime方法即可
2. JDK7-SimpleDateFormat类
这个类主要有两个作用:
- 把时间变成我们想要的格式
- 把字符串表示的时间变成Date对象
下面我们介绍构造方法和常用的成员方法:
#构造方法
public SimpleDateFormat() : 默认格式
public SimpleDateFormat(String pattern) : 指定格式
#成员方法
public final String format(Date date) : 格式化(日期对象->字符串)
public Date parse(String source) : 解析(字符串->日期对象)
public SimpleDateFormat(String pattern)
中的pattern
是这个类的一个成员变量,表述时间的格式。
- 如果使用空参构造那么格式化的时候就会是:年/月/日/ 上午/下午 时:分:秒
- 使用带参数构造方法:传入格式
传入的格式:(常用格式-来自黑马程序员)
代码示例:
//1.利用空参构造创建SimpleDateFormat对象,默认格式
SimpleDateFormat sdf1 = new SimpleDateFormat();
Date d1 = new Date(OL);
String str1 = sdf1.format(d1);|
System.out.println(str1);//1970/1/1 1:48:00
//2.利用带参构造创建SimpleDateFormat对象,指定格式
SimpleDateFormat sdf2 = new SimpleDateFormat(pattern:"yyyy|MM]ddHH:mm:ssEE");
String str2 = sdf2.format(d1);
System.out.println(str2);//1970年01月01日 08:00:00
parse(String source)
: 字符串->时间对象
//1.定义一个字符串表示时间
String str = "2023-11-11 11:11:11";
//2.利用空参构造创建SimpleDateFormat对象
//细节:
//创建对象的格式要跟字符串的格式完全一致
SimpleDateFormat sdf = new SimpleDateFormat( pattern: "yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(str);
//3.打印结果
System.out.println(date.getTime());//1699672271000
3.JDK7-Calendar类
Calendar
代表了系统当前时间的日历对象,可以单独修改、获取时间中的年,月,日
细节:Calendar是一个抽象类,不能直接创建对象。
获取Calendar
日历类对象的方法
public static Calendar getInstance() 获取当前时间的日历对象的子类对象
常用方法:
方法名 | 说明 |
---|---|
public final Date getTime() | 获取日期对象 |
public final setTime(Date date) | 给日历设置日期对象 |
public long getTimeInMillis() | 拿到时间毫秒值 |
public void setTimeInMillis(long millis) | 给日历设置时间毫秒值 |
public int get(int field) | 取日历中的某个字段信息 |
public void set(int field, int value) | 修改日历的某个字段信息 |
public void add(int field, int amount) | 为某个字段增加/减少指定的值 |
- 获取日历对象
- 细节: Calendar是一个抽象类,不能直接new,而是通过一个静态方法获取到子类对象
- 会根据系统的不同时区来获取不同的日历对象,默认表示当前时间。
- 把会把时间中的纪元,年,月,日,时,分,秒,星期,等等的都放到一个数组当中
Calendar c = Calendar.getInstance();
- 修改一下日历代表的时间
Date d = new Date(OL);
c.setTime(d);
System.out.println(c);
3.get(int field)
首先我们要知道在日历对象数组中数字的意义:
- 月份:范围0~11 如果获取出来的是0.那么实际上是1月。
- 星期: 数字表示略有不同
- 1(星期日)
- 2(星期一)
- 3(星期二)
- 4(星期三)
- 5(星期四)
- 6(星期五)
- 7(星期六)
方法的参数field
值为:0,1,2,3,4,5,6,,,16
其中:
- 0 - 纪元
- 1 - 年
- 2 - 月
- 3 - 一年中的第几周
- 4 - 一个月中的第几周
- 5 - 一个月中的第几天
- …
代码示例:
Calendar c = Calendar.getInstance();
System.out.println(c);
System.out.println(c.get(1) + "年" + (c.get(2) + 1) + "月" + c.get(5) + "日");
输出结果为:2024年11月29日
注意:这里月份加一:
(c.get(2) + 1)
set(int field, int value)
和add(int field, int amount)
使用获取的日历对象调用
在set
方法中,field 表示的和上面get
方法中的 field一样
后面value表示要修改的值
在add
方法中field表示和上述相同,amount表示要增加或者删去的数。
- 要注意的时月份在编译器中的范围是:0-11
- amount为正数表示增加,为负数表示减少
3.JDK8相关时间类
a.为什么要学习JDK8的时间类
- JDK8 的时间类相比于JDK7 在代码上更为简洁和方便
- 更为的安全,JDK8的时间日期对象都是不可变的,解决了多线程环境下导致的环境安全问题
b.JDK8时间相关类的分类
我们按照对比JDK7时间类的方法进行分类:
- 和JDK7中的
Date
类相照应:ZoneId
:时区Instant
:时间戳ZoneDateTime
:带时区的时间
- 和
SimpleDateFormat
相对应DateTimeFormatter
:用于时间格式化和解析
- 和
Calendar
类相对应LocalDate
:年、月、日LocalTime
:时、分、秒LocalDateTime
:年、月、日、时、分、秒
- 工具类
Duration
: 用于计算两个“时间”间隔(秒,纳秒)Period
: 用于计算两个“日期”间隔(年、月、日)ChronoUnit
: 用于计算两个“日期”间隔(使用范围更广,要熟练掌握)
c.类的成员方法
-
ZoneId
static Set<String> getAvailableZoneIds()———获取Java中支持的所有时区static ZoneId systemDefault()———获取系统默认时区static ZoneId of(String zoneId)——获取一个指定时区
代码示例:
//获取所有时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds);
//获取当前系统默认时区
ZoneId systemDefault = ZoneId.systemDefault();
System.out.println(systemDefault);
//获取一个指定时区
ZoneId of = ZoneId.of("US/Indiana-Starke");
System.out.println(of);
值得注意的是getAvailableZoneIds()
的返回类型是一个集合,这个集合的泛型式String
当然对于第二个默认时区我们可以在电脑的设置上进行修改
- 时间戳
Instant
时间戳获取的式标准时间不带时区
方法 | 说明 |
---|---|
static Instant now( ) | 获取当前时间的Instant对象(标准时间) |
static Instant ofXxxx(long epochMilli) | 根据(秒/毫秒/纳秒)获取Instant对象 |
ZonedDateTime atZone(ZoneId zone) | 指定时区 |
boolean isXxx(Instant otherInstant) | 判断系列的方法 |
Instant minusXxx(long millisToSubtract) | 减少时间系列的方法 |
Instant plusXxx(long millisToSubtract) | 增加时间系列的方法 |
上面的
Xxxx
表示这个方法有很多的不同的类型
我们给出代码示例:
Instant now = Instant.now();
System.out.println(now);
//根据传入的时间获取对象(相对于时间原点)
Instant instant = Instant.ofEpochMilli(1000L);
Instant instant1 = Instant.ofEpochSecond(1L);
Instant instant2 = Instant.ofEpochSecond(1L, 1000000000L);
System.out.println(instant);
System.out.println(instant1);
System.out.println(instant2);
//获取指定时区的时间戳
ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
//1.返回类型式zonedDateTime
//2.需要Instant对象调用
//3.传入的参数式zoneId类型的时区
System.out.println(zonedDateTime);
//判断时间前后
boolean after = instant.isAfter(instant1);
boolean before = instant.isBefore(instant2);
System.out.println(after);
System.out.println(before);
//减少时间
Instant instant3 = instant.minusSeconds(1L);
System.out.println(instant);
System.out.println(instant3);
ZoneDateTime
:带时区的时间
方法:
方法 | 说明 |
---|---|
static ZonedDateTime now() | 获取当前时间的ZonedDateTime对象(带时区) |
static ZonedDateTime ofXxxx( ) | 获取指定时间的ZonedDateTime对象(带时区) |
ZonedDateTime withXxx(时间) | 修改时间系列的方法 |
ZonedDateTime minusXxx(时间) | 减少时间系列的方法 |
ZonedDateTime plusXxx(时间) | 增加时间系列的方法 |
需要我么注意的是有一个和Instant
搭配的用法,我们前面也讲过:
//获取指定时区的时间戳
ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
//1.返回类型式zonedDateTime
//2.需要Instant对象调用
//3.传入的参数式zoneId类型的时区
System.out.println(zonedDateTime);
同时修改时间的方法可以针对性的修改年份、月份、时、秒等
Instant
和ZoneDateTime
都是时间对象,主要区别在于前者时获取标准时间对象,后者表示带时区的时间对象
DateTimeFormatter
:用于时间格式化和解析
方法 | 说明 |
---|---|
static DateTimeFormatter ofPattern(格式) | 获取格式对象 |
String format(时间对象) | 按照指定方式格式化 |
代码示例:
//获取时间对象
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
// 解析/格式化器
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm: ss EE a");
// 格式化
System.out.println(dtf1.format(time));
LocalDateTime
及相关
方法名 | 说明 |
---|---|
static XXX now() | 获取当前时间的对象 |
static XXX of(. . . ) | 获取指定时间的对象 |
get开头的方法 | 获取日历中的年、月、日、时、分、秒等信息 |
isBefore, isAfter | 比较两个 LocalDate |
with开头的 | 修改时间系列的方法 |
minus开头的 | 减少时间系列的方法 |
plus开头的 | 增加时间系列的方法 |
同时LocalDateTime
可以转换成LocalDate
和LocalTime
方法:
方法名 | 说明 |
---|---|
public LocalDate toLocalDate() | LocalDateTime转换成一个LocalDate对象 |
public LocalTime toLocalTime() | LocalDateTime转换成一个LocalTime对象 |
4.包装类
a.什么是包装类
包装类是基本数据类型对应的引用数据类型(对象)
使用包装类是为了数据的统一,因为只有引用数据类型才能使用集合,也只有类才可以使用Object
来接收数据
public void show(Object obj){//代码
}
实际上内存原理是:
- 使用一个类的成员变量来记录数值
- 操作数据的方法
内存图:
b. 包装类的分类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
只有int和char的包装类命名比较特殊,其他都是首字母大写
c.创建一个包装类对象
1.JDK5之前的创建方法
方法 | 说明 |
---|---|
public Integer(int value) | 根据传递的整数创建一个Integer对象 |
public Integer(String s) | 根据传递的字符串创建一个Integer对象 |
public static Integer valueOf(int i) | 根据传递的整数创建一个Integer对象 |
public static Integer valueOf(String s) | 根据传递的字符串创建一个Integer对象 |
public static Integer valueOf(String s, int radix) | 根据传递的字符串和进制创建一个Integer对象 |
上面的方法中两个构造方法和三个静态方法,我们介绍它们的区别
Integer i1 = new Integer(1);
Integer i2 = new Integer("2");
//
Integer i3 = Integer.valueOf(1);
Integer i4 = Integer.valueOf("3");
Integer i5 = Integer.valueOf("123", 8);
System.out.println(i1);
System.out.println(i2);
System.out.println("---------------");
System.out.println(i3);
System.out.println(i4);
System.out.println(i5);
- 在Java内部对
valueof
进行了优化,传入的数值在-128 ~ 127之间时会返回一个固定的对象,对象的地址值是固定的 - 而使用构造方法
new
是一定会创建一个新的对象
当然这都是过时的方法,现在不常用了
2. 当前创建包装类对象
我们使用上述的方法创建的包装类在进行运算的时候比较麻烦需要经历以下步骤:
- 把包装类转换为基本数据类型
- 使用基本数据类型进行运算
- 把运算的结果转换为包装类型
在JDK5之后,Java做了优化,把上述的过程直接在底层实现了。我们可以直接使用包装类进行赋值
Integer i = 10;
Integer j = 11;
Integer sum = i + j;
d.Integer类成员方法详解
方法 | 说明 |
---|---|
public static String toBinaryString(int i) | 得到二进制 |
public static String toOctalString(int i) | 得到八进制 |
public static String toHexString(int i) | 得到十六进制 |
public static int parseInt(String s) | 将字符串类型的整数转成int类型的整数 |
前面三种方法的返回值都是String
类型,原因:
- 用基本数据类型长度可能不够
- 返回二进制时候返回的值可能是负数。例如:01101,但是基本数据类型0不可以作为开头
这里详细讲一下字符串转换:
int i = Integer.parseInt( s: "123");
System.out.println(i);
System.out.println(i + 1);//124
String str = "true";
boolean b = Boolean.parseBoolean(str);
System.out.println(b);
java是一种强类型语言(每种数据在java中都有各自的数据类型)在计算的时候,如果不是同一种数据类型,是无法直接计算的。
值得注意的是parseInt(String s)
的两点:
- 在类型转换的时候,括号中的参数只能是数字不能是其他,否则代码会报错
- 8种包装类当中,除了Character都有对应的parseXxx的方法,进行类型转换
e.键盘录入nextLine
我们之前使用Scanner
对象进行键盘录入的时候会有一点的弊端:
- 比如:nextInt, nextDouble, next等
- 在进行录入的时候如果遇到空格, 回车,制表符时候就停止了
所以在以后我们建议使用nextLine
:可以录入一整行的数据,遇到回车停止
- 返回值是
String
类型 - 可以使用类型转换的方法,把录入的
String
类型的数据转换为我们需要的数据
代码示例:
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符串");
String s = scanner.nextLine();
int i = Integer.parseInt(s);
System.out.println(i);