JDK8-JDK17版本升级

JDK8

一、接口内允许添加默认实现的方法

interface Formula{
	
	double calculate(int a);

	//求平方根(defalult关键字,接口默认的方法实现)
	default double sqrt(int a){
		return Math.sqrt(a);
	}
}
Formula formula = new Formula(){
	@Override
	public double calculate(int a){
		return sqrt(a * 100);
	}
};

formula.calculate(100);
formula.sqrt(16); //无需重新实现,直接调用接口已经实现好的默认方法

二、Lambda表达式

//Collecitons工具类提供了静态方法sort,两个参数中的Comparator比较器,为给定的list排序
Collections.sort(names,(String a,String b) -> {
	return b.compareTo(a);
});

//只有一行代码可以省略大括号,甚至return关键字
Collections.sort(names,(a,b) -> b.compareTo(a));

不是每个接口都可以缩写成 Lambda 表达式。只有那些函数式接口(Functional Interface)才能缩写成 Lambda 表示式

Lambda 访问外部变量及接口默认方法(包括:局部变量,成员变量,静态变量,接口的默认方法)

①、局部变量

//转化器
@FunctionalInterface
interface Converter<F,T>{
	
	T convert(F from);
}

//匿名内部类不同的是,我们不必显式声明 num 变量为 final 类型
final int num = 1; //final可以省略(实际属于隐式声明,num值不可以被改变)
Converter<Integer,String> stringConverter = (from) -> String.valueOf(from+num);

②、访问成员变量和静态变量

@FunctionalInterface
interface Converter<F,T>{
	T convert(F from);
}

//对成员变量和静态变量拥有读写权限
class Lambda4{
	
	static int outerStaticNum;
	int outerNum;

	void testScopes(){
		Converter<Integer,String> stringConverter1 = (from) -> {
			//对成员变量赋值
			outerNum = 23;
			return String.valueOf(from);
		};

		Converter<Integer,String> stringConvert2 = (from) -> {
			//对静态变量赋值
			outerStaticNum = 72;
			retrn String.valueOf(from);
		};
	}
}

③、访问接口的默认方法

//访问上面接口实现类,带有默认实现的接口方法,是不能在 lambda 表达式中访问的,下面这段代码将无法被编译通过
Formula formula = a -> sqrt(a *100);

三、函数式接口

就是只包含一个抽象方法的声明,添加@FunctionalInterface,一旦你添加了第二个抽象方法,编译器会立刻抛出错误提示。

@FunctionalInterface
interface Converter<F,T>{
	T convert(F from);
}
Converter<String,Integer> converter = from -> Integer.valueOf(from);//简化一
Converter<String,Integer> converter = Integer::valueOf;//简化二:通过双冒号引用类的方法或构造器

Integer converted = converter.convert("124");

除了以上静态方法,还可以通过普通方法

class Something{
	String startsWith(String s){
		return String.valueOf(s.charAt(0));
	}
}

Something something = new Something();
Converter<String,String> converter = something::startsWith;//调用

String converted = sonverter.convert("Java");
System.out.println(converted);

如何通过::关键字来引用类的构造器?

①、类中构造器

class Person{
	
	String firstName;
	String lastName;

	Person(){}
	Person(String firstName,String lastName){
		this.firstName = firstName;
		this.lastName = lastName;
	}
}

②、工厂接口生成Person

interface PersonFactory<P extends Person> {
	
	P create(String firstName,String lastName);
}

③、通过::引用

// Java 编译器能够根据上下文选中正确的构造器去实现create方法
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter","Parker");

四、内置函数式接口

①、Predicate断言

一个可以指定入参类型,并返回 boolean 值的函数式接口。内部提供了一些带有默认实现的方法,可以被用来组合一个复杂的逻辑判断( and, or, negate):

Predicate<String> predicate = s -> s.length() > 0;

predicate.test("foo");//true
predicate.negate().test("foo");//false


Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;

Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();

②、Function

函数式接口的作用是,我们可以为其提供一个原料,他给生产一个最终的产品。通过它提供的默认方法,组合,链行处理( compose, andThen):

Function<String,Integer> toInteger = Integer::valueOf;
Function<String,String> backToString = toInteger.andThen(String::valueOf);

backToString.apply("123");

③、Supplier生产者

不接受入参,直接为我们生产一个指定的结果

class Person{
	
	String firstName;
	String lastName;

	Person(){}

	Person(String firstName,String lastName){
		this.firstName = firstName;
		this.lastName = lastName;
	}
}

Supplier<Person> psersonSupplier = Person::new;
personSupplier.get();

④、Consumer消费者

需要提供入参,用来被消费

Cunsumer<Person> greeter = (p) -> System.out.println("Hello," + p.firstName);
greeter.accept(new Person("Luke","Skywalker"));

⑤、Comparator

拓展了一些默认方法

Comparator<Person> comparator = (p1,p2) -> p1.firstName.compareTo(p2.firstName);
Person p1 = new Person("John","Doe");
Person p2 = new Person("Alice","Wonderland");

comparator.compare(p1,p2);
comparator.reversed().compare(p1,p2);

五、Optional

为了防止空指针异常( NullPointerException)

Optional<String> optional = Optional.of("bam");

optional.isPresent(); //true
optional.get();
optional.orElse("fallback");

optional.isPresent(s -> System.out.println(s.charAt(0)));

六、Stream流

对一个包含一个或多个元素的集合做各种操作,只能对实现了 java.util.Collection 接口的类做流的操作
【Map不支持Stream流】
Stream支持同步执行,也支持并发执行

①、Filter过滤

Filter 的入参是一个 Predicate, 上面已经说到, Predicate 是一个断言的中间操作,它能够帮我们筛选出我们需要的集合元素。
返参同样是一个 Stream 流,我们可以通过 foreach 终端操作,来打印被筛选的元素

list.stream().filter(s -> s.startsWith("a")).forEach(System.out::println);

②、Sorter排序

Sorted 同样是一个中间操作,它的返参是一个 Stream 流。另外,我们可以传入一个 Comparator 用来自定义排序,如果不传,则使用默认的排序规则。不会对list集合做出任何改变,还是原有的元素,顺序不变。

list.stream().sorted().filter(s -> s.startsWith("a")).forEach(System.out::println);

③、Map转换

List 中的每一个元素做功能处理。例如下面的示例,通过 map 我们将每一个 string 转成大写
业务中常见的:对象之间的转换,业务中比较常用的是将 DO(数据库对象) 转换成 BO(业务对象)

list.stream().map(String::boUpperCase)
	.sorted((a,b) -> b.compareTo(a))
	.forEach(System.out::println);

④、Match匹配

返回值是一个 boolean 类型,验证一个list中是否存在某个类型的元素

//验证list中String是否以a开头,匹配到第一个,返回true
boolean anyStartsWithA = list.stream().anyMatch(s -> s.startsWith("a"));
System.out.println(anyStartsWithA);//true

//验证list中是否都以a开头
boolean allStartsWithA = list.stream().allMatch(s -> startsWith("a"));
System.out.println(allStartsWithA);//false

//验证list中是否都不是z开头
boolean noneStartsWithZ = list.stream().noneMatch(s -> s.startsWith("z"));
System.out.println(noneStartsWithZ)

⑤、Count计数

终端操作,它能够统计 stream 流中的元素总数,返回值是 long 类型

//先对list中的字符串开头为b进行过滤,然后统计数量
long startsWithB = list.stream().filter(s -> s.startsWith("b")).count();
System.out.println(startsWithB);

⑥、Reduce

中文翻译为:减少、缩小。通过入参的 Function,将 list 归约成一个值。它的返回类型是 Optional 类型。

Optional<String> reduced = list.stream().sorted().reduce((s1,s2) -> s1 + "#" + s2);
reduced.isPresent(System.out::println);

七、Parallel-Streams 并行流

同样的逻辑处理,通过并行流,我们的性能提升了近 50%。完成这一切,我们需要做的仅仅是将 stream 改成了 parallelStream

//创建按一个包含 1000000 UUID list 集合
int max = 1000000;
List<String> values = new ArrayList<>(max);
for(int i = 0;i < max;i++){
	UUID uuid = UUID.randomUUID();
	values.add(uuid.toString());
}

//顺序流进行排序(单线程操作)
long t0 = System.nanoTime();
long count = values.stream().sorted().count();
System.out.println(count);

long t1 = System.nanoTime();

long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);//纳秒转微秒
System.out.println(String.format("顺序流排序耗时:%d ms",millis));

//并行流多线程来处理的,能够充分利用物理机
long t0 = System.nanoTime();
long count = values.parallelStream().sorted().count();
System.out.println(count);

long t1 = System.nanoTime();

long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);//纳秒转微秒
System.out.println(String.format("顺序流排序耗时:%d ms",millis));

八、Map集合

Map 是不支持 Stream 流的,因为 Map 接口并没有像 Collection 接口
可以对其 key, values, entry 使用流操作,如 map.keySet().stream(), map.values().stream() 和 map.entrySet().stream().

Map<Integer,String> map = new HashMap<>();

for(int i = 0;i < 10;i++){
	map.putIfAbsent(i,"val" + i);//在put之前会判断key是否存在,如果存在直接返回value,否则put之后再返回value
}
//forEach遍历
map.forEach((key,value) -> System.out.println(value));

//对某个 key 的值做相关操作:
//对key为3的值,判断是否存在,如果存在则作value+key拼接操作
map.computeIfPresent(3,(num,val) -> val + num);
map.get(3);//val33

//判断key为9的元素是否存在,如果存在则作删除操作
map.computeIfPresent(9,(num,val) -> null);
map.containsKey(9);//false

//先判断key为23是否存在,如果不存在则添加
map.computeIfAbsent(23,num -> "val" + num);
map.cotainsKey(23);//true

//先判断key为3的元素是否存在,如果存在,则不做任何处理
map.computeIfAbsent(3,num -> "bam");
map.get(3);

关于删除操作,jdk8提供了新的remove
只有当给定的 key 和 value 完全匹配时,才会执行删除操作

map.remove(3,"val3");
map.get(3);//val33

map.remove(3,"val33");
map.get(3);
//若key42不存在,则返回not found
map.getOrDefault(42,"not found");

//先判断进行合并的key是否存在,不存在则添加元素
map.merge(9,"val9",(value,newValue) -> value.concat(newValue));
map.get(9);//val9

//若key的元素存在,则对value执行拼接操作
map.merge(9,"concat",(value,newValue) -> value.concat(newValue));
map.get(9);//val9concat

九、新的日期API

①、Clock

提供对当前日期和时间的访问,替代 System.currentTimeMillis() 方法
通过 clock.instant() 能够获取一个 instant 实例,此实例能够方便地转换成老版本中的 java.util.Date 对象

Clock clock = Clock.systemDefalultZone();
long millis = clock.millis();

Instant instant = clock.instant();
Date legacyDate = Date.from(instant);

②、Timezones时区

ZoneId 代表时区类。通过静态工厂方法方便地获取它,入参我们可以传入某个时区编码。另外,时区类还定义了一个偏移量,用来在当前时刻或某时间与目标时区时间之间进行转换。

System.out.println(ZoneId.getAvailableZoneIds());

ZoneId zone1 = ZoneId.of("Eirope/Berlin");
ZoneId zone2 = ZoneId.of("Brazil/East");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());

③、LocalTime

表示一个没有指定时区的时间类,例如, 10p.m.或者 17:30:15,
下面示例代码中,将会使用上面创建的时区对象创建两个 LocalTime。然后我们会比较两个时间,并计算它们之间的小时和分钟的不同。

LocalTime now1 = LocalTime.now(zone1);
LocalTime now2 = LocalTime.now(zone2);

System.out.println(now1.isBefore(now2));//false

long hoursBetween = ChronoUnit.HOURS.between(now1,now2);
long minutesBetween = ChronoUnit.MINUTES.between(now1,now2);

System.out.println(hoursBetween);//-3
System.out.println(minutesBetween);//-239

LocalTime 提供多个静态工厂方法,目的是为了简化对时间对象实例的创建和操作,包括对时间字符串进行解析的操作等。

LocalTime late = LocalTime.of(23,59,59);
System.out.println(late);//23:59:59

DateTimeFormatter germanFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
	.withLocale(Locale.GERMAN);
LocalTime lettTime = LocalTime.parse("13:37",germanFormatter);
System.out.println(lettTime);//13:37

④、LocalDate

一个日期对象,例如: 2014-03-11。它和 LocalTime 一样是个 final 类型对象。
LocalDate, LocalTime, 因为是 final 类型的对象,每一次操作都会返回一个新的时间对象。

LocalDate today = LocalDate.now();
//今天加一天
LocalDate tomorrow = today.plus(1,ChronoUnit.DAYS);
//明天减两天
LocalDate yesterday = tomorow.minusDays(2);

//2014年七月的第四天
LocalDate independenceDay = LocalDate.of(2014,Month.JULY,4);
DayOfWeek dayOfWeek = independenceDay.getDayOfWeek();
System.out.println(dayOfWeek);//星期五

也可以直接解析日期字符串,生成 LocalDate 实例。(和 LocalTime 操作一样简单)

DateTimeFormatter germanFormatter = DateTimeFormatter.of(FormatStyle.MEDIUM).withLocale(Locale.GERMAN);
LocalDate xmas = LocalDate.parse("24.12.2014",germanFormatter);
System.out.println(xmas);

⑤、LocalDateTime

是一个日期-时间对象。将其看成是 LocalDate 和 LocalTime 的结合体。
LocalDateTime 同样是一个 final 类型对象,实现原理是基于 Java 的时间 API,其内部实现主要依赖于 Java 中的 long 类型和标准 Unix 时间戳来表示日期时间。
LocalDateTime 内部包含了一个 long 类型的字段,用于表示自 UTC(协调世界时)1970 年 1 月 1 日 00:00:00 开始经过的毫秒数(即 Unix 时间戳),通过对这个时间戳的操作来实现 LocalDateTime 类的各种功能。
同时,在实现时区相关的操作时,LocalDateTime 类还依赖于 Java 中的时区类(例如 ZoneId 和 ZoneOffset),通过将 LocalDateTime 转换为 ZonedDateTime 或 OffsetDateTime 对象来实现时区相关的计算。

  • 更加丰富的日期时间类型支持: LocalDateTime 类封装了 LocalDate 和 LocalTime 两个类,支持更加细化的日期时间操作,例如获取某一天的开始和结束时间、获取某个时间段内的所有日期等。
  • 线程安全性: LocalDateTime 类是不可变对象,线程安全性较高,可以在多线程环境下安全使用。
  • 时区支持: LocalDateTime 类在处理时区相关的操作时有着很好的支持,例如可以将一个 LocalDateTime 对象转换成 ZonedDateTime 对象,以支持更加复杂的时区计算。
//通过静态方法of根据指定的年、月、日、时、分、秒和纳秒值创建一个 LocalDateTime 对象
LocalDateTime sylvester = LocalDateTime.of(2014,Month.DECEMBER,31,23,59,59);
DayOfWeek dayOfWeek = sylvester.getDayOfWeek();
System.out.println(dayOfWeek);//星期三

Month month = sylvester.getMonth();
System.out.println(month);//十二月

long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY);
System.out.println(minuteOfDay);//1439

如果再加上的时区信息, LocalDateTime 还能够被转换成 Instance 实例。 Instance 能够被转换成老版本中 java.util.Date 对象。

Instant instant = sylvester.atZone(ZoneId.systemDefault()).toInstant();
Date legacyDate = Date.from(instant);//from() 方法用于将一个 TemporalAccessor 对象转换成 LocalDateTime 对象
System.out.println(legacyDate);

格式化 LocalDateTime 对象就和格式化 LocalDate 或者 LocalTime 一样。除了使用预定义的格式以外,也可以自定义格式化输出。

DateTimeFormatter formatter = DateTimeFormatter.of("MMM dd,yyyy-HH:mm");

//用于将一个字符串解析成 LocalDateTime 对象
//ext 表示要解析的字符串,formatter 表示日期时间格式化对象。如果不指定 formatter,则默认使用 ISO_LOCAL_DATE_TIME 格式
LocalDateTime parsed = LocalDateTime.parse("Nov 03,2014-07:13",formatter);

//将一个 TemporalAccessor 对象转换成 LocalDateTime 对象
String string = formatter.format(parsed);
System.out.println(string);

和 java.text.NumberFormat 不同,新的 DateTimeFormatter 类是 final 类型的,同时也是线程安全的。

//当前系统时间
LocalDateTime dateTime = LocalDateTime.now();

①、LocalDateTime转换

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalDate date = dateTime.toLocalDate();

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalTime time = dateTime.toLocalTime();

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
ZoneOffset offset = ZoneOffset.of("+08:00");
OffsetDateTime offsetDateTime = dateTime.atOffset(offset);//将一个 LocalDateTime 对象转换成带偏移量的 OffsetDateTime 对象

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
ZoneOffset offset = ZoneOffset.of("+08:00");
long epochSecond = dateTime.toEpochSecond(offset);//以下代码把一个 LocalDateTime 对象转换成 Unix 时间戳

②、LocalDateTime 的格式化与解析

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String strDate = dateTime.format(formatter);//将一个 LocalDateTime 对象格式化成 "yyyy-MM-dd HH:mm:ss" 格式的字符串

LocalDateTime dateTime = LocalDateTime.parse("2019-10-30T14:30:00");//parse() 方法用于将一个字符串解析成 LocalDateTime 对象

③、多种内置的格式化方式,同时也可以自定义日期时间格式

//使用指定的模式字符串创建一个 DateTimeFormatter 对象
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

//创建了一个 "yyyy-MM-ddTHH:mm:ss" 格式的 DateTimeFormatter 对象
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

//创建了一个 "yyyy-MM-dd" 格式的 DateTimeFormatter 对象
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;

④、LocalDateTime 的计算与比较

plusXxx() 和 minusXxx() 方法分别用于在当前 LocalDateTime 对象上加上或减去指定的日期时间量,其中 Xxx 表示日期时间单位,如:Years、Months、Days、Hours、Minutes、Seconds 和 Nanos。

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.plusYears(1).minusMonths(1);

withXxx() 方法用于以指定的日期时间量来修改 LocalDateTime 对象的对应字段,其他字段不变,其中 Xxx 表示日期时间单位,如:Year、Month、DayOfMonth、Hour、Minute、Second 和 Nano

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.withYear(2020);//将 LocalDateTime 对象的年份修改为 2020 年

isBefore() 和 isAfter() 方法分别用于判断两个 LocalDateTime 对象的先后顺序。其中,isBefore() 方法用于判断当前 LocalDateTime 对象是否在参数对象之前,isAfter() 方法用于判断当前 LocalDateTime 对象是否在参数对象之后。

LocalDateTime dateTime1 = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2020, 10, 30, 14, 30, 0, 0);
boolean before = dateTime1.isBefore(dateTime2); // true
boolean after = dateTime1.isAfter(dateTime2);   // false

⑤、其他操作

with() 方法用于以指定的 TemporalAdjuster 对象或者方法来修改 LocalDateTime 对象,例如,以下代码将 LocalDateTime 对象的日期调整为当前月份的第一天:
其中,TemporalAdjusters 是 Java 8 中提供的一个类,它提供了许多方便的日期时间调整器,如:firstDayOfMonth()、lastDayOfMonth()、next()、previous() 等。通过调用这些方法可以生成对应的 TemporalAdjuster 对象。

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.with(TemporalAdjusters.firstDayOfMonth());

getXXX() 方法用于获取 LocalDateTime 对象的指定字段值,其中 Xxx 表示日期时间单位,如:Year、Month、DayOfMonth、Hour、Minute、Second 和 Nano。

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
int month = dateTime.getMonthValue();  // 10
int minute = dateTime.getMinute();     // 30

getDayOfWeek() 和 getDayOfMonth() 方法分别用于获取 LocalDateTime 对象所表示日期的星期几和哪一天。例如,以下代码获取 LocalDateTime 对象的星期几和哪一天:

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
DayOfWeek dayOfWeek = dateTime.getDayOfWeek();   // WEDNESDAY
int dayOfMonth = dateTime.getDayOfMonth();       // 30

toInstant() 方法用于获取 LocalDateTime 对象的 Instant 对象,其中 Instant 对象表示了从 1970 年 1 月 1 日 00:00:00 GMT 开始的毫秒数例如,以下代码获取 LocalDateTime 对象的 Instant 对象:

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
Instant instant = dateTime.toInstant();

compareTo() 方法用于比较两个 LocalDateTime 对象的顺序大小,如果当前对象在参数对象之前,则返回负数,如果当前对象在参数对象之后,则返回正数,如果两个对象相等,则返回 0。

例如,以下代码比较两个 LocalDateTime 对象的顺序:

LocalDateTime dateTime1 = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2020, 10, 30, 14, 30, 0, 0);
int result = dateTime1.compareTo(dateTime2);  // -1

十、Annotatios注解

①、定义一个包装注解,里面包含一个有着实际注解的数组

@interface Hints{
	Hint[] value();
}

@Repeatable(Hints.class)
@interface Hint{
	String value();
}

Java 8 中,通过 @Repeatable,允许我们对同一个类使用多重注解:

第一种形态:使用注解容器

@Hints({@Hint("hint1"),@Hint("hint2")})
class Person{

}

第二种形态:使用可重复注解

@Hint("hint1")
@Hint("hint2")
class Person{

}

使用第二种形态,Java 编译器能够在内部自动对 @Hint 进行设置。这对于需要通过反射来读取注解信息时,是非常重要的。

Hint hint = Person.class.getAnnotation(Hint.class);
System.out.println(hint);

Hints hints1 = Person.class.getAnnotation(Hints.class);
System.out.println(hints1.value().length);

Hint[] hints2 = Person.class.getAnnotationsByType(Hint.class);
System.out.println(hints2.length);

尽管我们绝对不会在 Person 类上声明 @Hints 注解,但是它的信息仍然是可以通过 getAnnotation(Hints.class) 来读取的。
并且, getAnnotationsByType 方法会更方便,因为它赋予了所有 @Hints 注解标注的方法直接的访问权限。

@Target({ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})
@interface MyAnnotation{

}

局部变量类型推断

在这里插入图片描述

switch表达式

在这里插入图片描述

文本块

在这里插入图片描述

Records

记录Records是添加到 Java 14 的一项新功能。它允许你创建用于存储数据的类。它类似于 POJO 类,但代码少得多;大多数开发人员使用 Lombok 生成 POJO 类,但是有了记录,你就不需要使用任何第三方库。
在这里插入图片描述

模式匹配

在这里插入图片描述

密封类

sealed关键字将类的继承限制为一组有限的子类
密封类的子类可以声明为final或non-sealed。final 子类不能进一步扩展,而非密封子类可以进一步扩展。
在这里插入图片描述

有用的NullPoiterException

在这里插入图片描述

参考:

JDK 10 功能 — https://openjdk.org/projects/jdk/10/
JDK 11 功能 — https://openjdk.org/projects/jdk/11
JDK 12 功能 — https://openjdk.org/projects/jdk/12
JDK 13 功能 — https://openjdk.org/projects/jdk/13
JDK 14 功能 — https://openjdk.org/projects/jdk/14
JDK 15 功能 — https://openjdk.org/projects/jdk/15
JDK 16 功能 — https://openjdk.org/projects/jdk/16
JDK 17 功能 — https://openjdk.org/projects/jdk/17

Java8之后的LocalDateTime

LocalDateTime类提供的静态方法

①、of()方法用于根据指定的年、月、日、时、分、秒和纳秒值创建一个 LocalDateTime 对象

//2019 年 10 月 30 日 14 点 30 分 0 秒
LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);

②、now() 方法用于获取当前系统时间的 LocalDateTime 对象

LocalDateTime dateTime = LocalDateTime.now();

③、parse() 方法用于将一个字符串解析成 LocalDateTime 对象

//如果不指定 formatter参数,则默认使用 ISO_LOCAL_DATE_TIME 格式
LocalDateTime dateTime = LocalDateTime.parse("2019-10-30T14:30:00");

④、from() 方法用于将一个 TemporalAccessor 对象转换成 LocalDateTime 对象

//将一个 ZonedDateTime 对象转换成 LocalDateTime 对象
ZonedDateTime zonedDate = ZonedDateTime.of(2019, 10, 30, 14, 30, 0, 0, ZoneId.systemDefault());
LocalDateTime localDateTime = LocalDateTime.from(zonedDate);

LocalDateTime 的转换

①、toLocalDate() 方法用于把 LocalDateTime 对象转换成 LocalDate 对象

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalDate date = dateTime.toLocalDate();

②、toLocalTime() 方法用于把 LocalDateTime 对象转换成 LocalTime 对象

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalTime time = dateTime.toLocalTime();

③、atOffset() 方法用于把 LocalDateTime 对象转换成带偏移量的 OffsetDateTime 对象

其中,offset 表示要添加的时区偏移量。

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
ZoneOffset offset = ZoneOffset.of("+08:00");
OffsetDateTime offsetDateTime = dateTime.atOffset(offset);

④、toEpochSecond() 方法用于把 LocalDateTime 对象转换成 Unix 时间戳

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
ZoneOffset offset = ZoneOffset.of("+08:00");
long epochSecond = dateTime.toEpochSecond(offset);

⑤、from() 方法用于将一个 TemporalAccessor 对象转换成 LocalDateTime 对象

LocalDateTime 的格式化与解析

①、format() 方法用于将 LocalDateTime 对象格式化成字符串

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String strDate = dateTime.format(formatter);

②、parse() 方法用于将一个字符串解析成 LocalDateTime 对象

LocalDateTime dateTime = LocalDateTime.parse("2019-10-30T14:30:00");

③、DateTimeFormatter 类是 Java 8 中提供的日期时间格式化类,它提供了多种内置的格式化方式,同时也可以自定义日期时间格式。常用的几种内置格式化方式包括:

ofPattern() 方法:使用指定的模式字符串创建一个 DateTimeFormatter 对象

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

ISO_LOCAL_DATE_TIME:表示格式为 “yyyy-MM-ddTHH:mm:ss” 的日期时间

DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

ISO_LOCAL_DATE:表示格式为 “yyyy-MM-dd” 的日期

DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;

LocalDateTime 的计算与比较

①、plusXxx() 和 minusXxx() 方法分别用于在当前 LocalDateTime 对象上加上或减去指定的日期时间量

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.plusYears(1).minusMonths(1);

②、LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.plusYears(1).minusMonths(1);

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.withYear(2020);

③、isBefore() 和 isAfter() 方法分别用于判断两个 LocalDateTime 对象的先后顺序

isBefore() 方法用于判断当前 LocalDateTime 对象是否在参数对象之前,isAfter() 方法用于判断当前 LocalDateTime 对象是否在参数对象之后

LocalDateTime dateTime1 = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2020, 10, 30, 14, 30, 0, 0);
boolean before = dateTime1.isBefore(dateTime2); // true
boolean after = dateTime1.isAfter(dateTime2);   // false

LocalDateTime 的其他操作

①、with() 方法用于以指定的 TemporalAdjuster 对象或者方法来修改 LocalDateTime 对象

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
dateTime = dateTime.with(TemporalAdjusters.firstDayOfMonth());

如:firstDayOfMonth()、lastDayOfMonth()、next()、previous() 等。通过调用这些方法可以生成对应的 TemporalAdjuster 对象。

②、如:firstDayOfMonth()、lastDayOfMonth()、next()、previous() 等。通过调用这些方法可以生成对应的 TemporalAdjuster 对象。

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
int month = dateTime.getMonthValue();  // 10
int minute = dateTime.getMinute();     // 30

③、getDayOfWeek() 和 getDayOfMonth() 方法分别用于获取 LocalDateTime 对象所表示日期的星期几和哪一天

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
DayOfWeek dayOfWeek = dateTime.getDayOfWeek();   // WEDNESDAY
int dayOfMonth = dateTime.getDayOfMonth();       // 30

④、toInstant() 方法用于获取 LocalDateTime 对象的 Instant 对象,其中 Instant 对象表示了从 1970 年 1 月 1 日 00:00:00 GMT 开始的毫秒数

LocalDateTime dateTime = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
Instant instant = dateTime.toInstant();

⑤、compareTo() 方法用于比较两个 LocalDateTime 对象的顺序大小,如果当前对象在参数对象之前,则返回负数,如果当前对象在参数对象之后,则返回正数,如果两个对象相等,则返回 0

LocalDateTime dateTime1 = LocalDateTime.of(2019, 10, 30, 14, 30, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2020, 10, 30, 14, 30, 0, 0);
int result = dateTime1.compareTo(dateTime2);  // -1
  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值