为什么java date要强转_在Java中,你真的会日期转换吗

1.什么是SimpleDateFormat

在java doc对SimpleDateFormat的解释如下:

SimpleDateFormat是用于以对语言环境敏感的方式格式化和解析日期的具体类。它允许格式化(日期→文本),解析(文本→日期)和规范化。

SimpleDateFormat是一个用来对位置敏感的格式化和解析日期的实体类。他允许把日期格式化成文本,把文本解析成日期和规范化。

1.1使用SimpleDateFormat

simpleDateFormat的使用方法比较简单:9b2f28592bd0a2658c40ca99a07f2502.png

1.首先需要定义一个日期的模式,这里我们定义的是“ yyyy-mm-dd HH:mm:ss”,也就是我们这个simpleDateFormat不管是格式化还是解析都需要按照这个模式。

2.对于format需要传递Date的对象,会返回一个String类型,这个String会遵循我们上面的格式生成。

3.对于parse需要传递一个遵循上述模式的样式,如果传递错误的模式会引发java.text.ParseException异常,如果传递正确的会生成一个日期对象。f6dd944452c39d380b80fd15162c7e51.png

2.SimpleDateFormat的隐患

很多初学者,或者一些一些经验比较浅的java开发工程师,用SimpleDateFormat会出现一些奇奇怪怪的BUG。

1.结果值不对:转换的结果值经常会出人意料,和预期不同,经常让很多人摸不着头脑。

2.内存泄漏:由于转换的结果值不对,后续的一些操作,如一个循环,累加一天处理一个东西,但是生成的日期如果异常导致很大的话,则使这个循环变成一个类似死循环一样导致系统内存泄漏,重新触发gc,造成系统不可用。

为什么会出现这么多问题呢?因为SimpleDateFormat线程不安全,很多人都会写一个Util类,然后把SimpleDateFormat定义成一对的一个常量,所有线程都共享这个常量:28206f5c0e8ec4899ce1369ac631174f.png

为什么SimpleDateFormat会线程不安全呢,在SimpleDateFormat源码中,所有的格式化和解析都需要通过一个中间对象进行转换,那就是Calendar,而这个也是我们出现线程不安全的罪魁祸首,试想一下当我们有多一个线程操作同一个日历,当时的线程会覆盖先来线程的数据,那最后实际上返回的是后来线程的数据,这样就导致我们上面所述的BUG的产生:4d10966028aeba8c0a95848976a93aea.png

ec33681ad92497349b64b5efcbf45f05.png

3.如何避坑

对于SimpleDateFormat的解决方法有以下几种:

3.1新建SimpleDateFormat

上面出现错误的原因是因为所有线程都共享一个SimpleDateFormat,这里有个比较好解决的方法,每次使用的时候都创建一个新的SimpleDateFormat,我们可以在DateUtils中将创建SimpleDateFormat放在方法内部:59989d20b0f8c9c74a0cb8c92e7b03a1.png

上面这个方法虽然能解决我们的问题但是约会了另外一个问题就是,如果这个方法使用量比较大,有可能会替换造成Young gc,整个系统还是会受一定的影响。

3.2使用ThreadLocal

使用ThreadLocal能避免上面的重新造成的年轻gc,我们对每个线程都使用ThreadLocal进行保存,由于ThreadLocal是线程之间隔离开的,所以不会出现线程安全问题:ef3ff4dd891ade82ea4debd193e05893.png

3.3使用第三方工具包

虽然上面的ThreadLocal能解决我们出现的问题,但是第三方工具包提供的功能更强大,在java中有两个类库比较出名一个是Joda-Time,一个是Apache common包

3.3.1推荐(Joda-Time)

对于我们复杂的操作都可以使用Joda-Time操作,下面我两个两个例子,对于把日期加上90天,如果使用原生的Jdk我们需要这样写:532108c987ae1b3255de5088b9a692ca.png

但是在我们的joda-time中只需要两句话,并且api也比较通俗易懂,所以你为什么不用Joda-Time呢?4cf450adbab1751a9a8f559f0ad8de5a.png

3.3.2 common-lang包

在common-lang包中有个类叫FastDateFormat,由于common-lang这个包基本被很多Java项目都会引用,所以你可以不用专门去引用处理时间包,即可处理时间,在FastDateFormat中每次处理时间的当时会创建一个日历,使用方法比较简单代码如下所示:1d6d7da26fe6c229d5d537e3e0d4d8b3.png

3.4升级jdk8(推荐)

在java8中Date这个类中的很多方法包括构造方法都被打上了@不建议使用废弃的注解,取而代之的是LocalDateTime,LocalDate LocalTime这三个类:

LocalDate无法包含时间;

LocalTime无法包含日期;

LocalDateTime能同时包含日期和时间。

如果你是Java8,那你一定要使用他,在日期的格式化和解析方面不用考虑线程安全性,代码如下:30bffeb4dd4781d5262ed9fd0bb513b1.png

当然localDateTime是java8的一大亮点,当然不仅仅只是解决了线程安全的问题,同样也提供了一些其他的运算变量加减天数:ba0a1682a1fe1fd3284e55c235f24f2f.png

最后,如果您担心使用LocalDateTime合并您现有的代码产生很大的改变的话,那你可以将他们两进行互转:a6e502f1fb900610f2f3a4f80c80c634.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值