勇敢的Java新世界的定义特征之一是Java空间中构建器模式的日益普及。 Groovy似乎是JVM上最流行的替代语言(对于Java),以在核心库以及Groovy支持的库和框架中大量使用Builder而闻名。 乔希布洛赫与覆盖带来的图案为Java开发者社区心态前列模式在项目#2他的极具影响力的第二版的有效的Java 。 JDK中已经添加了几个构建器,包括J2SE 1.7中添加了Locale.Builder 。 在本文中,我将简要介绍JDK 8附带的 Calendar.Builder 。

如今,Java开发人员通常通过以下任一方法填充Calendar类的实例:
调用其中一个接受实例的冗长内容列表的“ set”方法之一,或者通过在该实例上一个接另一个地调用各个“ set”方法。 接下来的两个代码清单中演示了这两种填充Calendar实例的典型方法。

使用单个“设置”方法填充日历

/*** Demonstrate pre-JDK 8 method of instantiating Calendar instance using* "set" method for main fields.*/
public static void demoCalendarWithSingleSet()
{final Calendar calendar =Calendar.getInstance(TimeZone.getTimeZone(timeZoneId),ENGLISH);calendar.set(2013, APRIL, 6, 15, 45, 22);out.println("Calendar via Constructor: " + stringifyCalendar(calendar));
}

使用多个单独的“设置”方法填充日历

/*** Demonstrate pre-JDK 8 method of instantiating Calendar instance using* individual "set" calls for each pair of field names and values.*/
public static void demoCalendarWithIndividualSets()
{final Calendar calendar =Calendar.getInstance(TimeZone.getTimeZone(timeZoneId),ENGLISH);calendar.set(YEAR, 2013);calendar.set(MONTH, APRIL);calendar.set(DATE, 6);calendar.set(HOUR, 3);calendar.set(MINUTE, 45);calendar.set(SECOND, 22);calendar.set(AM_PM, PM);out.println("Calendar via set methods: " + stringifyCalendar(calendar));
}

旁注:在以上两个示例中,我都使用了现代Java另一个日益流行的功能 : static import 。 诸如ENGLISH , YEAR和SECOND之类的常量实际上是从Locale和Calendar之类的类中静态导入的。 正如我之前所写 ,静态导入在Java开发人员中似乎越来越流行,特别是考虑到流畅接口的趋势。

上面显示的两种“传统”方法显示了填充Calendar实例的不同方法。 一种极端情况是分别设置每个单独的字段,而另一种极端情况是使用单个“设置”方法设置所有重要字段。 每种方法都有其优势。 与多集方法相比,单个“集”方法具有“未完成”对象的状态更少,但是多集方法更具可读性,因为基于每个“集”的第一个参数,被设置值的名称是明确的“ 方法。 单集方法有点笨拙,因为它需要六个整数,可以很容易地将它们按顺序混合起来,因为除了隐式阶数之外,没有明显的方法可以区分哪个整数是哪个整数。

Calendar.Builder利用Bloch所描述的Builder的广告收益:消除了“在[对象]构造过程中出现不一致状态的情况”。 下一个代码清单对此进行了演示。

Calendar.Builder允许具有可读设置的单语句实例化

/*** Demonstrate using JDK 8's Calendar.Builder to instantiate an instance of* Calendar using the set methods to set each field individually based on* field name and value.*/public static void demoCalendarWithCalendarBuilderSetFields(){final Calendar calendar =new Calendar.Builder().set(YEAR, 2013).set(MONTH, APRIL).set(DATE, 6).set(HOUR, 15).set(MINUTE, 45).set(SECOND, 22).setTimeZone(TimeZone.getTimeZone(timeZoneId)).setLocale(ENGLISH).build();out.println("Calendar via Calendar.Builder 'set' Fields: "+ stringifyCalendar(calendar));}

在上面的代码清单中,创建了Calendar实例并将其填充到一条语句中,从而消除了使对象在多个语句中处于不一致状态的风险。 此示例保留了传统的单个“集合”方法方法[ set(int,int) ]的可读性,并具有在实例化时立即完全填充对象的附加安全性。

对于希望提供较少的单个“设置”方法的开发人员, Calendar.Builder另一个机会是使用setDate(int,int,int)和setTimeOfDay(int,int,int)方法,如下面的代码清单所示。

Calendar.Builder将日期和时间设置为两个呼叫

/*** Demonstrate using JDK 8's Calendar.Builder to instantiate an instance of* Calendar using the "setDate" and "setTimeOfDay" builder methods.*/
public static void demoCalendarWithCalendarBuilderSetDaySetTime()
{final Calendar calendar =new Calendar.Builder().setDate(2013, APRIL, 6).setTimeOfDay(15, 45, 22).setTimeZone(TimeZone.getTimeZone(timeZoneId)).setLocale(ENGLISH).build();out.println("Calendar via Calendar.Builder setDate/setTimeOfDay: "+ stringifyCalendar(calendar));
}

用这种方法键入的字符和行数较少,但是它部分地重新引入了一个缺点,即由于两个方法中的每一个都使用三个整数,因此无意间切换了整数参数的可能性(或者setTimeOfDay()的重载版本将占用一个整数setTimeOfDay()代表毫秒的第四个整数)。

对于希望在实例化过程中指定Calendar参数时具有最大灵活性的开发人员, Calendar.Builder提供了setFields(int…)方法,该方法采用任意长度的整数对,其中整数对的第一个整数表示要设置的字段,第二个整数表示要设置的字段表示该字段值的一对整数。 下一个代码清单中使用了此方法。

通过Calendar.Builder的setFields方法指定日历字段

/*** Demonstrate using JDK 8's Calendar.Builder to instantiate an instance of* Calendar using the setFields method that allows providing of Calendar* fields as key/value pairs.*/public static void demoCalendarWithCalendarBuilderSetPairs(){final Calendar calendar =new Calendar.Builder().setFields(YEAR, 2013, MONTH, APRIL, DATE, 6, HOUR, 15, MINUTE, 45, SECOND, 22).setTimeZone(TimeZone.getTimeZone("timeZoneId")).setLocale(ENGLISH).build();out.println("Calendar via Calendar.Builder setPairs: "+ stringifyCalendar(calendar));}

setFields(int ...)方法带来更大的风险,可能会破坏用于实例化Calendar新实例的整数的顺序,但是使用静态导入的Calendar常数确实可以提高可读性,并减少不正确混合整数的可能性。 如果提供了奇数个整数(意味着存在不完整的对),则抛出IllegalArgumentException 。

尽管Calendar.Builder在实例化和填充Calendar实例方面提供了一些便利,但是幸运地采用JDK 8的任何人都可以访问新的日期/时间API ,因此可能会问“为什么使用Calendar.Builder?”。 也许最好的答案是,有成千上万行使用和期望使用Calendar实例的现有代码,库和框架,因此可能需要很长时间才能完全消除对Calendar的需求(如果有的话)。 幸运的是, Calandar.Builder使得可以通过CalendarBulder.setInstant(long)轻松将Instant ( 新Java数据/时间API的一部分)实例转换成Calendar 。 下一个代码清单对此进行了演示。

使用Calendar.Builder将Instant转换为Calendar

/*** Demonstrate using JDK 8's Calendar.Builder to instantiate an instance of* Calendar based on "now" Instant.*/public static void demoCalendarWithCalendarBuilderInstant(){final Calendar calendar =new Calendar.Builder().setInstant(Instant.now().toEpochMilli()).setTimeZone(TimeZone.getTimeZone(timeZoneId)).setLocale(ENGLISH).build();out.println("Calendar via Calendar.Builder and Instant: " + stringifyCalendar(calendar));}

请注意, setInstant方法的重载版本接受Date来实例化Calendar 。 在这两种情况下,无论是使用setInstant(long)还是setInstant(Date)实例化,都不应调用Calender.Builder上的其他“ set”方法来避免IllegalStateException 。

使用Calendar.toInstant()可以很容易地朝另一个方向(从Calendar获取Instant ) 。 JDK 1.8的Calendar引入的其他方法与提供当前实例的日历类型 (作为字符串)或可用日历类型的集合(字符串的集合)有关。 当我在系统上运行Calendar.getAvailableCalendarTypes()时,看到以下三个字符串:“ gregory ”,“ Japanese ”和“ buddhist ”(与“ Supported Calendars”中记录的三个日历相同)

结论

与许多Java开发人员一样 ,我期待标准Java开发套件中内置的改进的Java数据/时间API。 但是,我也意识到,尤其是在大型代码库中,以及在使用期望使用CalendarDate库和框架时,我将在一段时间内无法摆脱CalendarDate的困扰。 JDK 8中Calendar.Builder的引入减轻了这一负担。

参考:来自JCG合作伙伴 Dustin Marx的JDK 8的Calendar.Builder,来自Inspired by Actual Events博客。

翻译自: https://www.javacodegeeks.com/2013/05/jdk-8s-calendar-builder.html

JDK 8的Calendar.Builder相关推荐

  1. jdk8 calendar_JDK 8的Calendar.Builder

    jdk8 calendar 勇敢的Java新世界的定义特征之一是Java空间中构建器模式的日益普及. Groovy是JVM上最流行的替代语言(对于Java),以在核心库以及Groovy支持的库和框架中 ...

  2. JDK 8的启发性Javadoc

    标准JDK 8 API文档的一个不错的功能之一就是能够查看所有或不同类别的方法,正如我在博客文章JDK 8 Javadoc Tweaked For Methods Listings中所讨论的那样. 尽 ...

  3. 设计模式 笔记4 | 简单工厂模式 在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式

    文章目录 一.Calendar 日历类 1.1 内部属性 1.2 设置时间属性值 1.3 获取时间属性 1.4 使用 Calander 计算时间 二.Calender 类中的设计模式 2.1 简单工厂 ...

  4. java localdate_Java 时间类-Calendar、Date、LocalDate/LocalTime

    1.Date 类 java.util.Date是一个"万能接口",它包含日期.时间,还有毫秒数,如果你只想用java.util.Date存储日期,或者只存储时间,那么,只有你知道哪 ...

  5. Calendar类(日历)

    Calendar类(日历) Calendar:它为特定瞬间与一组诸如 YEAR.MONTH.DAY_OF_MONTH.HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日 ...

  6. 日历Calendar类

    Candendar类是一个抽象类,提供了一些获取当前时间,或者指定的时间的字段和一些方法,我们可以通过一些方法与字段对他进行获取当前天或者当月的一些信息. 创建一个Candendar对象 我们都知道创 ...

  7. joda-time 文档的部分翻译

    Why Joda Time? The standard date and time classes prior to Java SE 8 are poor(标准日期和时间类在jdk1.8之前是极差的) ...

  8. javaSE基础全覆盖

    面向对象 概念: 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做. 面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做.类:对一类事物的描述,是抽象的.概念上的定义 对象:是实 ...

  9. C++/java设计模式汇总

    一.概述 二.创建型 1. 单例(Singleton) 2. 简单工厂(Simple Factory) 3. 工厂方法(Factory Method) 4. 抽象工厂(Abstract Factory ...

最新文章

  1. MESI缓存一致性协议
  2. sendto成功返回
  3. php7 参数类型限定,PHP参数类型限制 - Corwien的博客 - OSCHINA - 中文开源技术交流社区...
  4. 微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面
  5. 【转】 看IT人才最容易犯的17个错误
  6. 【转】【真正福利】成为专业程序员路上用到的各种优秀资料、神器及框架
  7. 加载elementor时出现问题_在使用聚氨酯发泡机时出现问题的解决方法!
  8. linux命令跨进程拷贝文件,linux scp命令安全远程文件复制程序
  9. Yii2修改默认控制器
  10. 医药网订单对接ERP软件订单接口
  11. 苍穹影视双端千月app源码,全新后台
  12. 嵌入式linux加入nes模拟器,成功运行于 ARM 上的 NES模拟器(InfoNES)
  13. 2、spss做均值比较分析
  14. Kubernetes之secrets使用
  15. Linux环境变量PSI指什么,psi是什么单位?
  16. python 回溯法 01背包问题_Python基于回溯法解决01背包问题实例
  17. 华清远见重庆分中心——前端阶段技术个人总结
  18. vscode卡在Setting up SSH Host XX:Copying VS Code Server to host with scp
  19. SVN安全证书问题解决方案
  20. TWEEN动画、JQUERY、ES6 — 1、定时器和TWEEN动画

热门文章

  1. apache shiro怎么升级_Springboot整合Shiro之授权
  2. 优先队列——斐波那契堆(without source code)
  3. (实模式+保护模式)模式切换的过程步骤(代码+文字解析)
  4. junit 测试目录_JUnit 5测试中的临时目录
  5. 世界是沙粒还是宇宙_看到一个沙粒世界:再一次你好世界
  6. 缓冲池java_了解Java缓冲池
  7. 英文连词_连词我们…讨厌
  8. java lambda::_书评:精通Lambda:多核世界中的Java编程
  9. Selenium脚本编写技巧和窍门
  10. antlr4 代码 语法树_使用ANTLR4,用于代码镜像和基于Web的DSL的Primefaces扩展