总结
就写到这了,也算是给这段时间的面试做一个总结,查漏补缺,祝自己好运吧,也希望正在求职或者打算跳槽的 程序员看到这个文章能有一点点帮助或收获,我就心满意足了。多思考,多问为什么。希望小伙伴们早点收到满意的offer! 越努力越幸运!
金九银十已经过了,就目前国内的面试模式来讲,在面试前积极的准备面试,复习整个 Java 知识体系将变得非常重要,可以很负责任的说一句,复习准备的是否充分,将直接影响你入职的成功率。但很多小伙伴却苦于没有合适的资料来回顾整个 Java 知识体系,或者有的小伙伴可能都不知道该从哪里开始复习。我偶然得到一份整理的资料,不论是从整个 Java 知识体系,还是从面试的角度来看,都是一份含技术量很高的资料。
然后调用**formatTo(temporal, buf)**方法
public void formatTo(TemporalAccessor temporal, Appendable appendable) {
Objects.requireNonNull(temporal, “temporal”);
Objects.requireNonNull(appendable, “appendable”);
try {
DateTimePrintContext context = new DateTimePrintContext(temporal, this);
if (appendable instanceof StringBuilder) {
printerParser.format(context, (StringBuilder) appendable);
} else {
// buffer output to avoid writing to appendable in case of error
StringBuilder buf = new StringBuilder(32);
printerParser.format(context, buf);
appendable.append(buf);
}
} catch (IOException ex) {
throw new DateTimeException(ex.getMessage(), ex);
}
}
**formatTo(temporal, buf)**方法也是先判断两个入参空处理。
然后,Instant对象被封装在一个新new的DateTimePrintContext对象
运行demo有问题,进行排查
//根据特定格式格式化日期
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(“yyyy-MM-dd”);
String dateStr = DateUtil.format(new Date(),dtf);
System.out.println(dateStr);
到这里已经是jdk的源码了DateTimeFormatter.format
从上面可知,会调用 NumberPrinterParser.format() NumberPrinterParser是在DateTimeFormatterBuilder类中的。
到这一步会报错
为什么会报错呢,我们来看下context.getValue(field)发生了什么:
从上面代码可行,temporal实际上是Instant对象,Instant.getLong只支持四种字段类型。。
NANO_OF_SECOND
MICRO_OF_SECOND
MILLI_OF_SECOND
INSTANT_SECONDS
如果不是上面这几种字段类型,则抛出异常
DateUtil.format当遇到DateTimeFormatter会将Date对象首先转换为Instant,因为缺少时区,导致报错。
解决方案:
/**
-
根据特定格式格式化日期
-
@param date 被格式化的日期
-
@param format
-
@return 格式化后的字符串
-
@since 5.0.0
*/
public static String format(Date date, DateTimeFormatter format) {
if (null == format || null == date) {
return null;
}
Instant instant = date.toInstant();
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
return format.format(localDateTime);
}
先把date类型转化为LocalDateTime类型,然后再进行DateTimeFormatter.format(LocalDateTime)的格式化
测试demo
//根据特定格式格式化日期
String str = “2021-07-25 20:11:25”;
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:dd”);
Date date = DateUtil.parse(str);
String dateStr = DateUtil.format(date,dtf);
System.out.println(dateStr);
Assert.assertEquals(str, dateStr);
============================================================================================
DateTimeFormatter 的所有格式化器都是用DateTimeFormatterBuilder 建造器类创建的。
看下面两个ofPattern 源码:
//DateTimeFormatter
public static DateTimeFormatter ofPattern(String pattern) {
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
}
public static DateTimeFormatter ofPattern(String pattern, Locale locale) {
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale);
}
官方提供了四种解析风格的配置,如下枚举 SettingsParser :
static enum SettingsParser implements DateTimePrinterParser {
// 大小写敏感
SENSITIVE,
// 大小写不敏感
INSENSITIVE,
//严格
STRICT,
//宽松
LENIENT;
…
}
对应DateTimeFormatterBuilder 类中的方法:
// 大小写敏感
public DateTimeFormatterBuilder parseCaseSensitive()
// 大小写不敏感
public DateTimeFormatterBuilder parseCaseInsensitive()
// 严格
public DateTimeFormatterBuilder parseStrict()
// 宽松
public DateTimeFormatterBuilder parseLenient()
这四个方法对应的源码如下:
// 大小写敏感
public DateTimeFormatterBuilder parseCaseSensitive() {
appendInternal(SettingsParser.SENSITIVE);
return this;
}
// 大小写不敏感
public DateTimeFormatterBuilder parseCaseInsensitive() {
appendInternal(SettingsParser.INSENSITIVE);
return this;
}
// 严格
public DateTimeFormatterBuilder parseStrict() {
appendInternal(SettingsParser.STRICT);
return this;
}
// 宽松
public DateTimeFormatterBuilder parseLenient() {
appendInternal(SettingsParser.LENIENT);
return this;
}
可以看出,都是调用appendInternal 方法。
接着往下看 appendInternal 源码:
private int appendInternal(DateTimePrinterParser pp) {
Objects.requireNonNull(pp, “pp”);
if (active.padNextWidth > 0) {
if (pp != null) {
pp = new PadPrinterParserDecorator(pp, active.padNextWidth, active.padNextChar);
}
active.padNextWidth = 0;
active.padNextChar = 0;
}
active.printerParsers.add(pp);
active.valueParserIndex = -1;
return active.printerParsers.size() - 1;
}
其中active 是一个DateTimeFormatterBuilder 实例,且这个DateTimeFormatterBuilder 实例内部有一个列表 List< DateTimePrinterParser > ,看了源码可知,真正做解析工作的是DateTimePrinterParser 对应的实例来做的。
DateTimePrinterParser 的源码:
interface DateTimePrinterParser {
boolean format(DateTimePrintContext context, StringBuilder buf);
int parse(DateTimeParseContext context, CharSequence text, int position);
}
源码有一共有16个DateTimePrinterParser 的实例。
//1.Composite printer and parser.
static final class CompositePrinterParser implements DateTimePrinterParser {…}
//2.Pads the output to a fixed width.
static final class PadPrinterParserDecorator implements DateTimePrinterParser {…}
//3.Enumeration to apply simple parse settings.
static enum SettingsParser implements DateTimePrinterParser{…}
//4. Defaults a value into the parse if not currently present.
static class DefaultValueParser implements DateTimePrinterParser {…}
//5.Prints or parses a character literal.
static final class CharLiteralPrinterParser implements DateTimePrinterParser {…}
//6.Prints or parses a string literal.
static final class StringLiteralPrinterParser implements DateTimePrinterParser {…}
//7.Prints and parses a numeric date-time field with optional padding.
static class NumberPrinterParser implements DateTimePrinterParser {…}
//8.Prints and parses a numeric date-time field with optional padding.
static final class FractionPrinterParser implements DateTimePrinterParser {…}
//9.Prints or parses field text.
static final class TextPrinterParser implements DateTimePrinterParser {…}
//10.Prints or parses an ISO-8601 instant.
static final class InstantPrinterParser implements DateTimePrinterParser {…}
//11.Prints or parses an offset ID.
static final class OffsetIdPrinterParser implements DateTimePrinterParser {…}
//12.Prints or parses an offset ID.
static final class LocalizedOffsetIdPrinterParser implements DateTimePrinterParser {…}
//13.Prints or parses a zone ID.
static class ZoneIdPrinterParser implements DateTimePrinterParser {…}
//14. Prints or parses a chronology.
static final class ChronoPrinterParser implements DateTimePrinterParser {…}
//15.Prints or parses a localized pattern.
static final class LocalizedPrinterParser implements DateTimePrinterParser {…}
//16.Prints or parses a localized pattern from a localized field.
static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {…}
==========================================================================
2DateUtil(时间工具类)-常用的时间类型Date,DateTime,Calendar和TemporalAccessor(LocalDateTime)转换
9LocalDateTimeUtil(JDK8+中的{@link LocalDateTime} 工具类封装)
10TemporalAccessorUtil{@link TemporalAccessor} 工具类封装
最后
这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)
oralAccessorUtil{@link TemporalAccessor} 工具类封装]( )
最后
这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)
[外链图片转存中…(img-r3jEO0c2-1715721149134)]
[外链图片转存中…(img-cb771CXn-1715721149135)]