版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/88826302
文章目录
七、接口中的默认方法与静态方法
1、默认方法
1)语法格式
public default String getName() {
return "哈哈";
}
2)“类优先”原则
A. 一个类的父类和实现的接口中有相同方法时,优先选择父类中的方法
B. 一个类实现的多个接口中有相同方法时,会冲突,必须要求重写该相同方法。
2、静态方法
Java8 中,接口中允许添加静态方法。
public static void show() {
System.out.println("这是show()方法!");
}
八、新日期时间API
1、本地日期时间类(LocalDate、LocalTime、LocalDateTime类)
这些类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间,它们提供了简单的日期或时间。(ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法)
A. LocalDateTime类
如: 2019-03-16T10:02:11.987(T代表时间的开始)
B. LocalDate类
如: 2019-03-16
C. LocalTime类
如: 10:02:12.002
1)常用方法(LocalDateTime类/LocalDate类/LocalTime类)
A. 获取功能
LocalDateTime.now()
按默认格式获取当前日期时间
int year = ldt.getYear();
获取年份
int month = ldt.getMonthValue();
获取月份
int day = ldt.getDayOfMonth();
获取日期
int hour = ldt.getHour();
获取小时
int minute = ldt.getMinute();
获取分钟
int second = ldt.getSecond();
获取秒数
B.指定功能
LocalDateTime of(int year, int month, int day, int hour, int minute, int second)
指定当前日期时间
C.修改功能
LocalDateTime plusYears(long year)
在原来的年份上加2年
LocalDateTime minusYears(long year)
在原来的年份上减2年
2、时间戳类(Instant类)
时间戳是指世界标准时格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,Instant本身就指明时区了,0时区(UTC时区:世界统一时间)。
常用方法:
Instant.now()
获取时间戳日期时间
如: 2019-03-16T02:20:23.437Z(Z代表时区,默认是UTC时区)
long getEpochSecond()
获取时间戳(秒)
long toEpochMilli()
获取时间戳(毫秒)
3、日期/时间间隔(Period类/Duration类)
A. Period类
计算两个“日期”之间的间隔。
B. Duration类
计算两个“时间”之间的间隔。
1)常用方法
Period/Duration between(日期/时间1,日期/时间2)
获取两个“日期”/"时间"之间的间隔。(日期:P10Y2M14D 时间:PT1S)
period.getYears()
获取两个“日期”相差的年份。(如:10)
period.getMonths()
获取两个“日期”相差的月份。(如:2)
period.getDays()
获取两个“日期”相差的天数。(如:14)
duration.toMillis()
获取两个“时间”的毫秒数。(如:1072)
2)应用
// 两个“日期”的间隔
@Test
public void test1() {
LocalDate ld1 = LocalDate.of(2009, 1, 1);
LocalDate ld2 = LocalDate.now();
Period period = Period.between(ld1, ld2);
System.out.println(period); // P10Y2M14D
System.out.println(period.getYears()); // 10
System.out.println(period.getMonths()); // 2
System.out.println(period.getDays()); // 14
}
// 两个“时间”的间隔
@Test
public void test2() {
Instant ins1 = Instant.now();
Thread.sleep(1000);
Instant ins2 = Instant.now();
// 计算两个时间的间隔
Duration dur = Duration.between(ins1, ins2);
System.out.println(dur); // PT1S(代表1秒)
System.out.println(dur.toMillis()); // 1072
System.out.println("---------------------------");
LocalTime lt1 = LocalTime.now();
LocalTime lt2 = LocalTime.of(10, 20, 20);
// 计算两个时间的间隔
Duration dur2 = Duration.between(lt1, lt2);
System.out.println(dur2); // PT19M27.274S(代表19分钟27秒274毫秒)
System.out.println(dur2.toMillis()); // 1167274
}
4、时间校正器(TemporalAdjuster类)
有时我们可能需要获取例如:将日期调整到“下个周日”等操作。
TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。
1)常用方法(ldt代表是LocalDateTime类的实例)
ldt.withDayOfMonth(10)
将原来的日期改变成10。
ldt.with(TemporalAdjusters.firstDayOfMonth())
月的第一天(时间校正器来调整日期)。
ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY))
下一个周日(时间校正器来调整日期)。
ldt.with(Lambda表达式**)**
自定义时间校正器。
2)应用
@Test
public void test() {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt); // 2019-03-16T10:36:57.664
// 将原来的日期改变成10
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2); // 2019-03-10T10:36:57.664
// 使用时间校正器来调整日期
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.firstDayOfMonth()); // 月的第一天
System.out.println(ldt3); // 2019-03-01T10:36:57.664
LocalDateTime ldt4 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); // 下一个周日
System.out.println(ldt4); // 2019-03-17T10:36:57.664
// 自定义时间校正器
LocalDateTime ldt6 = ldt.with(t -> {
LocalDateTime ldt5 = (LocalDateTime) t;
DayOfWeek dow = ldt5.getDayOfWeek(); // 获取当前是周几
// 如果是周五,就在原天数上加3,如果是周六,就加2,否则就加1
if (dow.equals(DayOfWeek.FRIDAY)) {
return ldt5.plusDays(3);
} else if (dow.equals(DayOfWeek.SATURDAY)) {
return ldt5.plusDays(2);
} else {
return ldt5.plusDays(1);
}
});
System.out.println(ldt6); // 2019-03-18T10:36:57.664
}
5、解析格式化日期/时间(DateTimeFormatter类)
很好的替代了 SimpleDateFormat类。
1)常用方法:
DateTimeFormatter.ISO_DATE
ISO预定义日期格式。
ldt.format(dtf)
使用对应的格式来格式化。
LocalDateTime.parse(ldtStr, dtf)
使用对应的格式来解析字符串。
DateTimeFormatter.ofPattern(“yyyy年MM月dd日 HH:mm:ss”)
自定义格式。
2)应用:
@Test
public void test() {
// 使用 ISO的预定义标准来格式化日期(如:2019-03-16)
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
LocalDateTime ldt = LocalDateTime.now(); // 获取当前日期时间
// 格式化
String ldtStr = ldt.format(dtf);
System.out.println(ldtStr);
// 解析(按照dtf来解析ldtStr字符串)
LocalDateTime ldt2 = LocalDateTime.parse(ldtStr, dtf);
System.out.println(ldt2);
System.out.println("-----------------------------");
// 自定义格式化
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String ldtStr2 = ldt.format(dtf2);
System.out.println(ldtStr2);
}
6、时区的处理
Java8 中加入了对时区的支持,带时区的时间为分别为:
ZonedDate、ZonedTime、ZonedDateTime
其中每个时区都对应着ID,地区ID都为 “{区域}/{城市}”的格式,例如:Asia/Shanghai等。
**ZoneId:**该类中包含了所有的时区信息。
1)常用方法
ZoneId.getAvailableZoneIds()
可以获取所有的时区信息,返回Set集合。
ZoneId.of(“Pacific/Majuro”)
用指定的时区信息获取 ZoneId 对象。
2)应用
@Test
public void test() {
// 获取所有的时区
Set<String> set = ZoneId.getAvailableZoneIds();
set.forEach(System.out::println);
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Pacific/Majuro"));
System.out.println(ldt); // 2019-03-16T15:29:53.402
// 带时区的时间,但这个时间并不一定就是这个时区的时间
LocalDateTime ldt2 = LocalDateTime.now(); // 默认使用的是UTC的时区
ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Pacific/Majuro"));
System.out.println(zdt); // 2019-03-16T11:29:53.449+12:00[Pacific/Majuro]
}
九、重复注解和参数类型注解
1、重复注解
可以重复使用同一个注解。
1)例如
@MyAnno("hello")
@MyAnno("world")
public void show() {
}
2)使用方式
A. 自定义注解
B. 自定义注解容器
C. 在自定义注解上声明@Repeatable,并指明该注解的容器
自定义注解:
@Repeatable(MyAnnos.class)
@Target({METHOD})
public @interface MyAnno {
String value();
}
自定义注解容器:
@Target({METHOD})
public @interface MyAnnos {
MyAnno[] value();
}
3)应用
// 通过反射获取该方法上的所有注解
@Test
public void test1() throws Exception {
Class<TestAnnotation> clazz = TestAnnotation.class;
Method m1 = clazz.getMethod("show");
// 获取MyAnno类型的重复注解
MyAnno[] mas = m1.getAnnotationsByType(MyAnno.class);
// 遍历重复注解
for (MyAnno ma : mas) {
System.out.println(ma.value());
}
}
2、参数类型注解
ElementType.TYPE_PARAMETER:可以用于参数类型上。
1)例如
public void show(@MyAnno String str) {
}
2)应用
@Target({TYPE_PARAMETER})
public @interface MyAnno {
String value() default "sunkuan";
}
十、其他新特性
1、匿名内部类访问局部变量时,局部变量省略final
1.7前匿名内部类使用局部变量时必须加final,1.8可以省略,系统会自动加final。
局部内部类在访问它所在方法中的局部变量必须用final修饰,为什么?
因为当调用这个方法时,局部变量如果没有用final修饰,它的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。
2、类型推断
main {
eat(new HashMap<>());
// 在Java8中可以推断出来,
// 在Java7以前必须这样写:eat(new HashMap<String, Integer>());
}
void eat(Map<String, Integer> map) {
}