【总结篇下】Java8新特性总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun8112133/article/details/88826302

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址: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) {

}

猜你喜欢

转载自blog.csdn.net/sun8112133/article/details/88826302