一 包装类
1.1 包装类简介
java语言是面向对象的语言,但是其中的八大基本数据类型不符合面向对象的特征。因此java为了弥补这样的缺点,为这八种基本数据类型专门设计了八种符合面向对象特征的的类型,这八种具有面向对象特征的类型,统称为包装类,英文单词:Wrapper Class。
包装类,就是在类的内部,维护了一个基本数据类型的成员变量,以及其他方法,常量等。比如int对应的包装类Integer的部分源码如下:
public final class Integer extends Number implements Comparable<Integer> {
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;
private final int value;
public Integer(int value) {this.value = value;}
public Integer(String s) throws NumberFormatException {this.value = parseInt(s, 10);}
public static String toHexString(int i) {}
public static String toOctalString(int i) {}
public static String toBinaryString(int i) {}
public static int parseInt(String s) throws NumberFormatException {}
public static Integer valueOf(String s) throws NumberFormatException {}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
public int compareTo(Integer anotherInteger) {}
public static int max(int a, int b) {
return Math.max(a, b);
}
public static int min(int a, int b) {
return Math.min(a, b);
}
//.....
}
所有的基本数据类型和包装类型的对比,参考如下:
基本数据类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
1.2 装箱与拆箱
- 装箱boxing : 由基本数据类型转型为包装类型。
- 调用包装类的构造器,进行装箱
- 调用valueOf()静态方法,进行装箱
- 拆箱 unboxing: 由包装类型转型为基本数据类型。
- 调用xxxValue()非静态方法,进行拆箱
1.3 自动装箱与自动拆箱
为了方便获取包装类对象,从jdk1.5以后,提供了一个自动装箱的操作,也提供了一个包装类到基本数据类的自动拆箱操作。
- 自动装箱 : 直接使用一个基本数据类型的变量或字面值给一个包装类型的引用进行赋值即可
- 自动拆箱 : 直接使用一个包装类型的引用给一个基本数据类型的变量进行赋值即可
- 自动的装箱 : 省略掉的是 valueOf 方法 自动的拆箱 : 省略掉的是 xxValue 方法
package com.day13.box;
/**
* 自动拆装箱操作
*/
public class _04Box {
public static void main(String[] args) {
/**
* 自动装箱
* 其实在编译期间,会变成如下代码
* Integer i = Integer.valueOf(10); 即,自动调用了装箱方法
*/
Integer i = 10; //
System.out.println(i);
Character c = '中'; //底层转成了调用 Chatacter.valueOf('中') 进行装箱
/**
*
* 自动拆箱
*
* int n2 = n1.intValue();
*/
Integer n1 = new Integer(100);
int n2 = n1; // 底层会转成调用intValue()方法,进行自动拆箱操作
Long m1 = new Long(10000);
long m2 = m1; // 自动拆箱
System.out.println(m2);
}
}
public static void main(String[] args) {
// 使用实参区分调用不同的重载方法
// 在调用方法的时候, 10默认是int类型的,因此会先找有没有int参数的重载方法
// 如果有int参数的重载方法,调用
// 如果没有int参数的重载方法,装箱调用Integer参数的
showNumber(10);
}
public static void showNumber(int a) {
System.out.println("showNumber(int)");
}
public static void showNumber(Integer a) {
System.out.println("showNumber(Integer)");
}
1.4 包装类常量池
对于装箱操作后的包装类的对象,jvm在堆中,维护了一个常量池,该常量池适用于调用了valueOf()方法产生的包装类对象,以及自动装箱的包装类对象。不适用于new关键字创建的包装类对象。
Byte, Short, Integer, Long 这 4 种包装类默认创建了数值 [-128, 127] 的相应类型的缓存数据,
Character 创建了数值在 [0, 127] 范围的缓存数据,
Boolean 直接返回 true 或 false。
两种浮点数类型的包装类 Float, Double 并没有实现常量池技术。
package com.day13.box;
/**
* 针对于装箱操作后的包装类的对象的常量池
* Integer: -128~127
*/
public class _03Box {
public static void main(String[] args) {
int num = 127;
Integer i1 = Integer.valueOf(num); //装箱操作
Integer i2 = Integer.valueOf(num);
//使用 == 来判断是否是同一个对象
System.out.println(i1==i2); //true,同一个对象
// Double和Float两个包装类并没有提供常量池
double d1 = 3.14;
Double d2 = Double.valueOf(d1);
Double d3 = Double.valueOf(d1);
System.out.println(d2==d3);
boolean f = true;
Boolean f1 = Boolean.valueOf(f);
Boolean f2 = Boolean.valueOf(f);
System.out.println(f1==f2);
char c1 = 97; // 'a'
Character c2 = Character.valueOf(c1);
Character c3 = Character.valueOf(c1);
System.out.println(c2==c3); //true
}
}
1.5 包装类其他常用方法
package com.day13.box;
/**
* Integer.parseInt();
* Integer.toBinaryString(); 转成二进制
* Integer.toHexString(); 转成16进制
* Integer.toOctalString() 转成8进制
*
* public static int parseInt(String str):
* public static Integer valueOf(String str):
* 上述两个方法都用Integer类名调用,
* 作用相似:都是将字符串转成整形,一个是转成int类型,一个是转成Integer类型
*/
public class _05Box {
public static void main(String[] args) {
/* Integer.parseInt(String str); 将字符串变成数字
*
* 将字符串line中的数字截取出来,然后转成整形
*
*
*
* NumberFormatException: For input string: "89w"
*
* 数字格式异常: 即将字符串变成数字时,字符串中有非数字字符。
* */
String line = "hello89world";
String sub = line.substring(5,7);
int num = Integer.parseInt(sub);
System.out.println(num);
Integer i = 100;
String str = Integer.toBinaryString(i); //参数是int类型,但是传了Integer,因此自动拆箱操作了
System.out.println("100的二进制:"+str);
System.out.println("100的八进制:"+Integer.toOctalString(i));
System.out.println("100的十六进制:"+Integer.toHexString(i));
}
}
二 BigDecimal/BigInteger
2.1 简介
因为使用八大基本数据类型做运算时,尤其是浮点数的运算时,容易精度不准确,所以java语言提供了BigDecimal这个类来完善这类运算,可以非常精确,可以精确到小数点后无数位。BigDecimal 通常支持任意位数的小数部分,用来对超过16位有效位的数进行精确的运算,(float可以精确到7左右,double是15位左右)
自学知识点:
BigInteger: 表示大整数。一般用来处理非常大的数字,大到long也表示不了的数字。
2.2 常用构造器
BigDecimal(int val) 创建一个具有参数所指定整数值的对象。
BigDecimal(double val) 创建一个具有参数所指定双精度值的对象。不推荐使用,因为存在精度丢失问题
BigDecimal(long val) 创建一个具有参数所指定长整数值的对象。
BigDecimal(String val) 创建一个具有参数所指定以字符串表示的数值的对象。 推荐使用
2.3 常用方法
注意:BigDecimal进行运算时必须要保证对象本身不能是null,否则就会抛空指针异常。
package com.day13.box;
import java.math.BigDecimal;
/**
* BigDecimal 大精度类型,弥补float和double的精度低的情况。
* 可以精确到小数点后无数位。
*
*
* /**
* * 11.1 --->3.5
* * 11.01 --->3.25
* * 11.11---->3.75
* * 11.001--->3.125
* * 11.0001-->3.0625
* * 11.00001--->3.03125
*
b1.add();
b1.subtract();
b1.multiply();
b1.divide();
*/
public class _06BigDecimalDemo {
public static void main(String[] args) {
/*
* 常用的构造器
*/
BigDecimal b1 = new BigDecimal(5);
BigDecimal b2 = new BigDecimal(10l);
BigDecimal b3 = new BigDecimal(15.0);
BigDecimal b4 = new BigDecimal("20");
/*
* 常用的方法
* add(BigDecimal) BigDecimal对象中的值相加,返回BigDecimal对象
* subtract(BigDecimal) BigDecimal对象中的值相减,返回BigDecimal对象
* multiply(BigDecimal) BigDecimal对象中的值相乘,返回BigDecimal对象
* divide(BigDecimal) BigDecimal对象中的值相除,返回BigDecimal对象。该方法可能会遇到无限精度问题,会抛出异常,使用时需注意
* abs() 将BigDecimal对象中的值转换成绝对值
* doubleValue()
* floatValue()
* longValue()
* intValue() 上述四个方法 将BigDecimal对象中的值转换成相应的基本数据类型
* compareTo(BigDecimal val) 比较大小,返回int类型。0(相等) 1(大于) -1(小于)
* toString() 有必要时使用科学计数法。
*/
BigDecimal add = b1.add(b2);
BigDecimal subtract = b3.subtract(b2);
BigDecimal multiply = b2.multiply(b3);
BigDecimal divide = b3.divide(b1);
System.out.println(add+","+subtract+","+multiply+","+divide);
int i = b3.compareTo(b2);
System.out.println("1表示前面大于后面,-1表示前面小于后面,0表示相等\t"+i);
}
}
2.4 常用的舍入模式
BigDecimal.setScale()方法用于格式化小数点
- setScale(1)表示保留一位小数,默认用四舍五入方式
- setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3
- setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4
- setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4
- setScaler(1,BigDecimal.ROUND_HALF_DOWN)四舍五入,2.35变成2.3,如果是5则向下舍
- setScaler(1,BigDecimal.ROUND_CEILING)接近正无穷大的舍入
- setScaler(1,BigDecimal.ROUND_FLOOR)接近负无穷大的舍入,数字>0和ROUND_UP作用一样,数字<0和ROUND_DOWN作用一样
- setScaler(1,BigDecimal.ROUND_HALF_EVEN)向最接近的数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
1、ROUND_UP,向远离0的方向舍入,在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。
注意,此舍入模式始终不会减少计算值的大小。
eg: 保留1位小数 1.60->1.6 1.61->1.7 1.66->1.7 , -1.62->-1.7
2、ROUND_DOWN,向接近0的方向舍入,在丢弃某部分之前,始终不增加数据(即,截断),该方式是只减不加。
eg: 保留1位小数 1.60->1.6 1.61->1.6 1.66->1.6 , -1.62->-1.6
3、ROUND_CEILING,向正无穷方向舍入,如果数值为正,舍入方式与ROUND_UP一致,如果为负,舍入方式与ROUND_DOWN一致,该模式始终不会减少计算数值。
eg: 保留1位小数 1.60->1.6 1.61->1.7 1.66->1.7 , -1.62->-1.6
4、ROUND_FLOOR,向负无穷方向舍入,如果数值为正,舍入行为与 ROUND_DOWN 相同;如果为负,则舍入行为与 ROUND_UP 相同。该模式始终不会增加计算数值。
eg: 保留1位小数 1.60->1.6 1.61->1.6 1.66->1.6 , -1.62->-1.7
5、ROUND_HALF_UP,向“最接近的”数字舍入,也就是四舍五入。
eg: 保留1位小数 1.61->1.6 1.65->1.7 1.66->1.7 , -1.62->-1.6
6、ROUND_HALF_DOWN,向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式,也就是五舍六入。
eg: 保留1位小数 1.61->1.6 1.65->1.6 1.66->1.7 , -1.62->-1.6
7、ROUND_HALF_EVEN,向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。如果前一位为奇数,则入位,否则舍去。以下例子为保留小数点1位,那么这种舍入方式下的结果。
eg. 1.15->1.2, 1.25->1.2
8、ROUND_UNNECESSARY,计算结果是精确的,不需要舍入模式。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
2.5 BigDecimal常见问题
坑一:创建 BigDecimal精度丢失的坑
在BigDecimal 中提供了多种创建方式,可以通过new 直接创建,也可以通过 BigDecimal.valueOf 创建。这两种方式使用不当,也会导致精度问题。如下:
public static void main(String[] args) throws Exception {
BigDecimal b1= new BigDecimal(0.1);
System.out.println(b1);
BigDecimal b2= BigDecimal.valueOf(0.1);
System.out.println(b2);
BigDecimal b3= BigDecimal.valueOf(0.111111111111111111111111111234);
System.out.println(b3);
}
0.1000000000000000055511151231257827021181583404541015625
0.1
0.1111111111111111
上面示例中两个方法都传入了double类型的参数0.1但是 b1 还是出现了精度的问题。造成这种问题的原因是 0.1 这个数字计算机是无法精确表示的,送给 BigDecimal 的时候就已经丢精度了,而BigDecimal.valueOf 的实现虽然底层调用的是形参是字符串的构造器,但是在赋值的过程中也有可能精度损失。如下源码所示:
public static BigDecimal valueOf(double val) {
return new BigDecimal(Double.toString(val));
}
结论:尽量使用BigDecimal的字符串形参构造函数,而非浮点类型的构造函数;
坑二:等值比较的坑
一般在比较两个值是否相等时,都是用equals 方法,但是,在BigDecimal 中使用equals可能会导致结果错误,BigDecimal 中提供了 compareTo 方法,在很多时候需要使用compareTo 比较两个值。如下所示:
public static void main(String[] args){
BigDecimal b1 = new BigDecimal("1.0");
BigDecimal b2 = new BigDecimal("1.00");
System.out.println(b1.equals(b2));
System.out.println(b1.compareTo(b2));
}
执行结果
false
0
出现此种结果的原因是,equals不仅比较了值是否相等,还比较了精度是否相同。示例中,由于两个值的精度不同,所有结果也就不相同。而 compareTo 是只比较值的大小。返回的值为-1(小于),0(等于),1(大于)。
坑三:无限精度的坑
BigDecimal 并不代表无限精度,当在两个数除不尽的时候,就会出现无限精度的坑,如下所示:
public static void main(String[] args){
BigDecimal b1 = new BigDecimal("1.0");
BigDecimal b2 = new BigDecimal("3.0");
b1.divide(b2);
}
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1693)
at com.demo.controller.Test.main(Test.java:29)
大致意思就是,如果在除法(divide)运算过程中,如果商是一个无限小数(如 0.333…),而操作的结果预期是一个精确的数字,那么将会抛出ArithmeticException异常。
此种情况,只需要在使用 divide方法时指定结果的精度即可:
public static void main(String[] args){
BigDecimal b1 = new BigDecimal("1.0");
BigDecimal b2 = new BigDecimal("3.0");
System.out.println(b1.divide(b2,2, RoundingMode.HALF_UP));//0.33
}
在使用BigDecimal进行(所有)运算时,尽量指定精度和舍入模式。
三 传统的日期处理类型 方法
3.1 Date日期类型
3.1.1 简介
- 是一个用来表示时间、日期的类,这个类在 java.util 包中,在使用 Date的时候,一定要注意 : 在 java.sql 包中,也有一个Date,千万不要导错包了。
- java中的时间使用标准类库的Date类型来表示,是用距离某一个固定时间点的毫秒数表达的一个特定的时间点:
- 固定时间点:1970年1月1日00:00:00
- UTC(Universal Time Coordinated世界调整时间)与GMT(Greenwich Mean Time格林威治时间)一样,是一种具有实际目的的科学标准时间。
- Date类的大多数用于进行时间分量计算的方法已经被Calendar取代。
3.1.2 常用API
1)构造器
- Date() :获取当前系统时间
- Date(long time):设置一个距离固定点的指定毫秒数的时间点。
2)方法
- long getTime()
- void setTime(long time)
- String toString() 格式: Thu May 24 19:32:14 CST 2018
3.2 SimpleDateFormat类型
3.2.1 简介
java.text.SimpleDateFormat是一个用来格式化和解析日期的具体类,它允许进行格式化(日期 ->文本)、解析(文本 -> 日期)和规范化
- 将一个Date对象转成一个指定格式的字符串
- 将一个自定格式的字符串转成一个Date对象
3.2.2 常用构造器和方法
1)构造器
- SimpleDateFormat()
- SimpleDateFormat(String pattern):指定一个日期格式符号来构造对象
2)方法
- final String format(Date date) DateàString
- Date parse(String source) throws ParseException
3)日期模式匹配字符
字符 | 含义 | 案例 |
---|---|---|
y | 年 | yyyy年—2018年;yy-18年 |
M | 月 | MM月—05月;M月—5月 |
d | 日 | dd日—06日;d日—6日 |
E | 星期 | E-星期日(Sun) |
a | 上下午(AM、PM) | a—下午(PM) |
H | 24小时制 | a h时--------下午 10时 HH:mm:ss------12:21:34 hh(a):mm:ss------12(PM):21:34 |
h | 12小时制 | |
m | 分钟 | |
s | 秒 |
3.2.3 案例演示
1)Date格式化成String
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-d HH:mm:ss");
Date d1 = new Date();
String pattern = sdf.format(d1);
System.out.println(pattern);
输出:
18-05-24 19:51:06
2)String格式化成Date
String pattern = "2018-5-6 11-30-48";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date date = sdf.parse(pattern);
System.out.println(date);
输出:
Sun May 06 11:30:48 CST 2018
3.3 Calendar类型
3.3.1 简介
Calendar: 日历,是用来表示时间、日期的类。在Date类中,有很多的方法都已经废弃了,使用 Caneldar中的某些方法进行实现。
java.util.Calendar类用于封装日历信息,其主要作用在于其方法可以对时间分量进行运算。
Calendar是抽象类型,其具体子类是针对不同国家的日历系统,其中应用最广泛的是GregorianCalendar(格里高利历,即通用的阳历),对应世界上绝大多数国家/地区使用的标准日历系统
3.3.2 常用方法
1)getInstance方法
Calendar提供了一个类方法getInstance,以获取此类型的一个通用的对象
此方法返回一个Calendar对象,其日历字段已经由当前日期和时间初始化
2)日期与时间分量方法
- Calendar提供的get方法与一些常量合用可以获取日期及时间分量
- Calendar提供的set方法与一些常量合用可以设置日期及时间分量
- 常量
- static int YEAR 指定年份的字段数字
- static int MONTH 指定月份的字段数字,0为一月
- static int DATE 指示一个月份中的第几天
- static int DAY_OF_WEEK 指定一个星期中的某天,1为星期日
- static int WEEK_OF_MONTH 指定一个月中的第几周
- static int WEEK_OF_YEAR 指定一年中的第几周
3)其他方法
- getActualMaximum方法
- int getActualMaximum(int field)
- 作用:指定一个时间常量,返回指定日历分量可能拥有的最大值。
- 注意:要保证年月日的日数字小于等于28
- add方法
- void add(int field , int mount)
- 作用:指定一个时间常量,在此时间分量上增加指定的数值,若为负值,则是减去指定的数值。
- getTime与setTime
- Date getTime()
- 作用:返回一个Date类型来描述日期
- void setTime(Date d)
- 作用:用Calendar表示Date所描述的日期
四 新的日期处理类型
4.1 Date类型的不足
- 时区问题:
Date
类不处理时区信息,它只表示一个时间点,通常默认为 GMT(格林威治标准时间)。这导致了很多时区相关的问题,因为日期和时间需要根据时区进行转换和显示。 - 线程不安全性:
Date
类是可变的,这意味着你可以修改它的值。由于 Java 中的日期和时间操作通常需要是线程安全的,这种可变性可能导致并发问题。
因为上述问题,Java 引入了新的日期和时间 API,如 java.time
包,它提供了更强大和安全的日期和时间处理能力。如果你在项目中需要处理日期和时间,建议使用新的日期和时间 API,如 LocalDateTime
、ZonedDateTime
等,以避免 Date
类的问题。同时,这些新 API 在代码中更容易理解和维护,因为它们遵循了更直观的命名规则,而不需要像 Date
那样存在历史遗留问题。
4.2 LocalDateTime类简介
java.time.LocalDateTime
类是 Java 8 引入的日期时间类,它解决了许多java.util.Date
类存在的问题,并提供了更好的方式来处理日期和时间信息。以下是关于 LocalDateTime
为什么更好的一些原因:
- 线程安全性:
java.time.LocalDateTime
是不可变的,这意味着一旦创建了对象,它的值不能被修改。这保证了在多线程环境中使用时不会出现并发问题,与java.util.Date
的可变性形成鲜明对比。 - 时区支持:
LocalDateTime
提供了更好的时区支持。它存储日期和时间信息,但不包含时区信息。这允许你在需要时将日期时间信息与特定时区相关联,而不会像java.util.Date
那样受限于默认时区(通常是 GMT)。你可以使用ZoneId
来将LocalDateTime
转换为特定时区的时间,例如:LocalDateTime localDateTime = LocalDateTime.now(); ZoneId zoneId = ZoneId.of("America/New_York"); ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
这样,你可以更灵活地处理全球不同时区的日期和时间。
- 更丰富的功能:
java.time
包中提供了一整套用于日期时间操作的类和方法,使日期时间处理更加方便和功能丰富。你可以轻松进行日期的加减、格式化、比较等操作,而无需手动编写复杂的代码。 - 清晰的命名:
java.time
类使用了更直观和清晰的命名,不再存在像java.util.Date
中那样的命名混乱,例如getYear()
和getMonth()
方法的问题。
总之,java.time.LocalDateTime
提供了更强大、更安全、更灵活的日期时间处理方式,是 Java 8 引入的重要改进,推荐在现代 Java 应用程序中使用它来替代传统的 java.util.Date
类。
4.3 LocalDateTime常用操作
4.3.1 日期加减
使用 Date
进行日期加减操作通常需要使用 Calendar
类,而使用 LocalDateTime
更简单,例如:
// Date 加减
Date currentDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(currentDate);
calendar.add(Calendar.DAY_OF_MONTH, 1); // 增加一天
Date tomorrow = calendar.getTime();
// LocalDateTime 加减
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime nextDay = currentDateTime.plusDays(1); // 增加一天
4.3.2 格式化和解析
使用 Date
进行格式化和解析通常需要使用 SimpleDateFormat
,而 LocalDateTime
内置了格式化和解析功能:
// Date 格式化和解析
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = dateFormat.format(currentDate);
Date parsedDate = dateFormat.parse(dateStr);
// LocalDateTime 格式化和解析
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateTimeStr = currentDateTime.format(formatter);
LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeStr, formatter);
4.3.3 转换
你可以在 Date
和 LocalDateTime
之间进行相互转换,例如:
// Date 转换为 LocalDateTime
Date date = new Date();
Instant instant = date.toInstant();
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
// LocalDateTime 转换为 Date
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
Date date = Date.from(zonedDateTime.toInstant());
这里需要注意的是,转换时需要考虑时区的影响,因为 Date
不包含时区信息,而 LocalDateTime
存储的是本地时间。所以,转换时需要确定时区信息以保持一致性。
总之,LocalDateTime
提供了更简单和直观的日期时间操作,同时也可以与 Date
进行转换,以兼容传统的日期时间处理方式。然而,使用 LocalDateTime
更推荐,尤其在新的 Java 8+ 应用中,因为它更强大、更安全,同时提供了更多的功能。