返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java——JDK1.8新特性
  • 905
分享到

Java——JDK1.8新特性

java开发语言servlet后端java-consul 2023-09-22 16:09:39 905人浏览 八月长安
摘要

目录 一、Lambda 表达式 (一)Lambda 表达式语法 (二)类型推断 二、函数式接口 (一)自定义函数式接口 (二)作为参数传递Lambda 表达式 (三)Java 内置四大核心函数式接口 三、方法引用 四、Stream API

目录

一、Lambda 表达式

(一)Lambda 表达式语法

(二)类型推断

二、函数式接口

(一)自定义函数式接口

(二)作为参数传递Lambda 表达式

(三)Java 内置四大核心函数式接口

三、方法引用

四、Stream API

(一)什么是Stream?

(二)Stream 的操作三个步骤

(三)创建流的四种方式

(四)Stream的中间操作

(五)Stream的终止操作

五、综合案例

六、新时间日期API

(一)使用LocalDate、LocalTime、LocalDateTime

(二)使用Instant时间戳

(三)Duration 和 Period

(四)日期的操纵

(五)解析与格式化

(六)时区的处理

(七)与传统日期处理的转换

七、接口中的默认方法与静态方法

八、其他新特性

(一)Optional 类

(二)重复注解与类型注解


一、Lambda 表达式

Lambda 是一个 匿名函数 ,我们可以把 Lambda表达式理解为是 一段可以传递的代码 (将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。 案例:从匿名内部类---》Lambda表达式
    // 原来的匿名内部类    @Test    public void test1() {        Comparator com = new Comparator() {            @Override            public int compare(Integer o1, Integer o2) {                return Integer.compare(o1, o2);            }        };        TreeSet ts = new TreeSet<>(com);    }    // Lambda表达式    @Test    public void test2() {        Comparator com = (o1, o2) -> Integer.compare(o1, o2);        TreeSet ts = new TreeSet<>(com);    }

(一)Lambda 表达式语法

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ -> ” , 该操作符被称为 Lambda 操作符或剪头操作符。它将 Lambda 分为两个部分:
  • 左侧:指定了 Lambda 表达式需要的所有参数
  • 右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能。

语法格式一:无参,无返回值,Lambda体只需一条语句

 语法格式二:Lambda需要一个参数

语法格式三:Lambda只需要一个参数时,参数的小括号可以省略 

语法格式四:Lambda需要两个参数,并且有返回值

语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略

 (二)类型推断

上述 Lambda 表达式中的参数类型都是由编译器推断得出的。Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的 “类型推断“

二、函数式接口

只包含一个抽象方法的接口,称为 函数式接口
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
  • 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

(一)自定义函数式接口

(二)作为参数传递Lambda 表达式

作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递,接 收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口 的类型。

(三)Java 内置四大核心函数式接口

 

其他子接口(参数个数) 

public class TestLambda02 {        @Test    public void test04() {        List stringList = Arrays.asList("hello", "world","you");        List list = getStringList(stringList, (s) -> s.length() > 3);        list.forEach(System.out::println);    }    public List getStringList(List stringList, Predicate pre) {        List strings = new ArrayList<>();        for (String s : stringList) {            if(pre.test(s)) {                strings.add(s);            }        }        return strings;    }        @Test    public void test03() {        String string = getString("\t\t\t 帅哥好帅", (str) -> str.trim());        System.out.println(string);    }    public String getString(String str, Function func) {        return func.apply(str);    }        @Test    public void test02() {        int num = 10;        generator(num, () -> (int)(Math.random() * 100) + 1);    }    public void generator(int x, Supplier sup) {        List integerList = new ArrayList<>();        for(int i = 0; i < x; i ++) {            Integer integer = sup.get();            integerList.add(integer);        }        integerList.forEach(System.out::println);    }        @Test    public void test01() {        int num = 100;        consumer(num, x -> System.out.println("消费了" + num + "元"));    }    public void consumer(int num, Consumer com) {        com.accept(num);    }}

三、方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用! 实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致! 方法引用:使用操作符 “ :: ” 将方法名和对象或类的名字分隔开来。 如下三种主要使用情况
  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法
public class TestMethodRef {    // 数组引用    @Test    public void test05() {        Function func = (x) -> new String[x];        String[] strings = func.apply(10);        System.out.println(strings.length);        Function func2 = String[]::new;        String[] strs = func2.apply(20);        System.out.println(strs.length);    }    // 构造器引用    @Test    public void test04() {        Supplier sup = () -> new Employee();        // 构造器引用的方式        Supplier sup2 = Employee::new;        Employee employee = sup2.get();        System.out.println(employee);                Function func = Employee::new;        Employee employee1 = func.apply(20);        System.out.println(employee1);    }    // 类::实例方法名    @Test    public void tes03() {        // 规则:若Lambda参数列表中的第一参数是实例方法的调用者,第二参数是实例方法的参数时,此时        //      可以通过 class::method        BiPredicate bp = (x, y) -> x.equals(y);        BiPredicate bp1 = String::equals;    }    // 对象::静态方法    @Test    public void  test02() {        Comparator com = (x, y) -> Integer.compare(x, y);        Comparator com1 = Integer::compare;    }    // 对象::实例方法    @Test    public void test01() {        PrintStream ps = System.out;        Consumer con = (x) -> System.out.println(x);        Consumer con2 = ps::println;    }}

 四、Stream API

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API(java.util.stream.*) 。 Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream api 对集合数据进行操作,就类似于使用 sql 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

(一)什么是Stream?

流(Stream) 到底是什么呢? 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 “集合讲的是数据,流讲的是计算!” 注意: ①Stream 自己不会存储元素。 ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。 ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

 (二)Stream 的操作三个步骤

  • 创建 Stream
        一个数据源(如:集合、数组),获取一个流
  • 中间操作
        一个中间操作链,对数据源的数据进行处理
  • 终止操作(终端操作)
        一个终止操作,执行中间操作链,并产生结果

(三)创建流的四种方式

方式一:Collection接口

Java8 中的 Collection 接口被扩展,提供了 两个获取流的方法 default Stream stream() : 返回一个顺序流 default Stream parallelStream() : 返回一个并行流

方式二:数组创建流

Java8 中的 Arrays 的静态方法 stream() 可 以获取数组流: static Stream stream(T[] array): 返回一个流 重载形式,能够处理对应基本类型的数组: public static IntStream stream(int[] array) public static LongStream stream(long[] array) public static DoubleStream stream(double[] array) 方式三:由值创建流 可以使用静态方法 Stream.of(), 通过显示值 创建一个流。它可以接收任意数量的参数。 public static Stream of(T... values) : 返回一个流 方式四:由函数创建流 可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。 迭代 public static Stream iterate(final T seed, final UnaryOperator f) 生成 public static Stream generate(Supplier s) :
public class testStream {    // 创建stream    @Test    public void test1() {        //1.可以通过Collection 系列集合提供的stream() or parallelStream()        List list = new ArrayList<>();        Stream stream1 = list.stream();        //2. 通过Arrays的静态方法stream()获取数组流        Employee[] emps = new Employee[2];        Stream stream2 = Arrays.stream(emps);        //3. 通过stream的静态方法of()        Stream stream3 = Stream.of(1, 2, 3);        //4. 创建无限流        // 迭代        Stream stream4 = Stream.iterate(0, (x) -> x + 2);        stream4.limit(10).forEach(System.out::println);        // 生成        Stream stream5 = Stream.generate(Math::random);        stream5.limit(10).forEach(System.out::println);    }}

 (四)Stream的中间操作

多个 中间操作 可以连接起来形成一个 流水线 ,除非流水线上触发终止操作,否则 中间操作不会执行任何的处理 !而在 终止操作时一次性全部处理,称为“惰性求值” 筛选与切片

 映射

排序

public class testStreamApi {    List empList = Arrays.asList(            new Employee("张三", 50, 7777.77),            new Employee("李四", 35, 8888.6),            new Employee("王五", 20, 999.55),            new Employee("赵六", 40, 1000.5),            new Employee("赵六", 40, 1000.5),            new Employee("赵六", 40, 1000.5));    // 中间操作        @Test    public void test06() {        List strs = Arrays.asList("aaa", "bbb", "ccc");        strs.stream()                .sorted()  // 按已经实现的comparator接口的排序规则进行排序称为自然排序                .forEach(System.out::println);        // 先按年龄排序,然后按姓名排序        empList.stream()                .sorted((x, y) -> {                    if(x.getAge().equals(y.getAge())) {                        return x.getName().compareTo(y.getName());                    }                    return x.getAge().compareTo(y.getAge());                })                .forEach(System.out::println);    }        @Test    public void test05() {        List stringList = Arrays.asList("aaa", "bbb", "ccc");        stringList.stream()                .map((str) -> str.toUpperCase())                .forEach(System.out::println);        System.out.println("---------------------------------");        // 获取员工的名字        empList.stream()                .distinct()                .map(Employee::getName)                .forEach(System.out::println);        System.out.println("---------------------------------");        // map实现将每个字符串转化为字符  复杂        Stream> streamStream = stringList.stream()                .map(testStreamApi::filterCharacter);        streamStream.forEach((sm) -> {            sm.forEach(System.out::println);        });        System.out.println("---------------------------------");        // flatMap实现将每个字符串转化为字符 简单        Stream stream = stringList.stream()                .flatMap(testStreamApi::filterCharacter);        stream.forEach(System.out::println);    }    public static Stream filterCharacter(String str) {        List list = new ArrayList<>();        for(Character ch : str.toCharArray()) {            list.add(ch);        }        return list.stream();    }        @Test    public void test04() {        empList.stream()                .filter((e) -> e.getAge() > 30)                .skip(2)                .distinct() // 这里是根据hashCode和equals,所以employee需要重写hashCode和equals                .forEach(System.out::println);    }    @Test    public void test03() {        empList.stream()                .filter((e) -> e.getAge() > 30)                .limit(2)                .forEach(System.out::println);    }    // 内部迭代:即stream内部帮我们迭代    @Test    public void test01() {        // 中间操作        Stream stream = empList.stream()                .filter((e) -> e.getAge() > 30);        // 终止操作:一次性执行全部内容,即“惰性求值”        stream.forEach(System.out::println);    }    // 外部迭代    @Test    public void test02() {        Iterator iterator = empList.iterator();        while(iterator.hasNext()) {            Employee employee = iterator.next();            if(employee.getAge() > 30) {                System.out.println(employee);            }        }    }}

 (五)Stream的终止操作

Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:

public class testStreamApi2 {    List empList = Arrays.asList(            new Employee("张三", 50, 7777.77, Employee.Status.FREE),            new Employee("李四", 35, 8888.6, Employee.Status.BUSY),            new Employee("王五", 20, 999.55, Employee.Status.VOCATION),            new Employee("赵六", 40, 1000.5, Employee.Status.BUSY),            new Employee("赵六", 40, 1000.5, Employee.Status.FREE),            new Employee("赵六", 40, 1000.5, Employee.Status.VOCATION));        // 其他    @Test    public void test09() {        DoubleSummaryStatistics ssd = empList.stream()                .collect(Collectors.summarizingDouble(Employee::getSalary));        System.out.println(ssd.getAverage());        System.out.println(ssd.getMax());        System.out.println(ssd.getMin());        String str = empList.stream()                .map(Employee::getName)                .collect(Collectors.joining(",", "===", "==="));        System.out.println(str);    }    // 分区    @Test    public void test08() {        // 分成true和false两个区        Map> map = empList.stream()                .collect(Collectors.partitioningBy((e) -> e.getSalary() > 5000));        System.out.println(map);    }    // 多级分组    @Test    public void test07() {        Map>> map = empList.stream()                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {                    if (e.getAge() < 30) {                        return "青年";                    } else if (e.getAge() < 50) {                        return "中年";                    } else {                        return "老年";                    }                })));        System.out.println(map);    }    // 分组    @Test    public void test06() {        Map> map = empList.stream()                .collect(Collectors.groupingBy(Employee::getStatus));        System.out.println(map);    }    @Test    public void test05() {        Long size = empList.stream()                .collect(Collectors.counting());        System.out.println(size);        Double avg = empList.stream()                .collect(Collectors.averagingDouble(Employee::getSalary));        System.out.println(avg);        Double sum = empList.stream().collect(Collectors.summingDouble(Employee::getSalary));        System.out.println(sum);        Optional max = empList.stream()                .map(Employee::getSalary)                .collect(Collectors.maxBy(Double::compareTo));        System.out.println(max.get());        Optional min = empList.stream()                .collect(Collectors.minBy((x, y) -> Double.compare(x.getSalary(), y.getSalary())));        System.out.println(min.get());    }    @Test    public void test04() {        List list1 = empList.stream()                .map(Employee::getName)                .collect(Collectors.toList());        list1.forEach(System.out::println);        System.out.println("------------------------");        Set set = empList.stream()                .map(Employee::getName)                .collect(Collectors.toSet());        set.forEach(System.out::println);        System.out.println("------------------------");        LinkedHashSet hashSet = empList.stream()                .map(Employee::getName)                .collect(Collectors.toCollection(LinkedHashSet::new));        hashSet.forEach(System.out::println);    }        @Test    public void test03() {        List list = Arrays.asList(1, 2, 3);        Integer sum1 = list.stream()                .reduce(1, (x, y) -> x + y);        System.out.println(sum1);        Optional sum2 = empList.stream()                .map(Employee::getSalary)                .reduce(Double::sum);        System.out.println(sum2.get());    }        @Test    public void test02() {        // 数量        long count = empList.stream()                .count();        System.out.println(count);        // 最大值        Optional max = empList.stream()                .max((x, y) -> Double.compare(x.getSalary(), y.getSalary()));        System.out.println(max.get().getSalary());        // 最小值        Optional min = empList.stream()                .map(Employee::getSalary)                .min(Double::compareTo);        System.out.println(min.get());    }    @Test    public void test01() {        boolean b1 = empList.stream()                .allMatch((e) -> e.getStatus().equals(Employee.Status.FREE));        System.out.println(b1);        boolean b2 = empList.stream()                .anyMatch((e) -> e.getStatus().equals(Employee.Status.FREE));        System.out.println(b2);        boolean b3 = empList.stream()                .noneMatch((e) -> e.getStatus().equals(Employee.Status.FREE));        System.out.println(b3);        // 返回的值有可能为空所以封装到了Optional        Optional op1 = empList.stream()                .sorted((x, y) -> Double.compare(x.getSalary(), y.getSalary()))                .findFirst();        System.out.println(op1.get());        Optional op2 = empList.stream()                .sorted((x, y) -> Double.compare(x.getSalary(), y.getSalary()))                .findAny();        System.out.println(op2.get());    }}

 案例:

public class testStreamApi3 {        @Test    public void test() {        Integer[] num = new Integer[]{1, 2, 3, 4, 5};        Stream stream = Arrays.stream(num);        stream.map(x -> x*x).forEach(System.out::println);    }    List empList = Arrays.asList(            new Employee("张三", 50, 7777.77),            new Employee("李四", 35, 8888.6),            new Employee("王五", 20, 999.55),            new Employee("赵六", 40, 1000.5),            new Employee("赵六", 40, 1000.5),            new Employee("赵六", 40, 1000.5));        @Test    public void test2() {        Optional sum = empList.stream()                .map(e -> 1)                .reduce(Integer::sum);        System.out.println(sum.get());    }}

 五、综合案例

public interface MyPredicate {    public boolean test(Employee employee);}====================================================================    List empList = Arrays.asList(        new Employee("张三", 50, 7777.77),        new Employee("李四", 35, 8888.6),        new Employee("王五", 20, 999.55),        new Employee("赵六", 40, 1000.5)    );    // 需求:获取当前公司中员工年龄大于35的员工    @Test    public void test3() {        List employees = filterList(empList);        for (Employee employee : employees) {            System.out.println(employee);        }        System.out.println("---------------------------------");        employees = filterListBySalary(empList);        for (Employee employee : employees) {            System.out.println(employee);        }    }    public List filterList(List empList) {        List emps = new ArrayList<>();        for (Employee emp : empList) {            if(emp.getAge() > 35) {                emps.add(emp);            }        }        return emps;    }    // 需求:获取当前公司中员工工资大于4000的员工    public List filterListBySalary(List empList) {        List emps = new ArrayList<>();        for (Employee emp : empList) {            if(emp.getSalary() > 4000) {                emps.add(emp);            }        }        return emps;    }    // 优化方式一:策略设计模式    @Test    public void test4() {        List employees                = filterList(empList, new filterEmployeeByAge());        for (Employee employee : employees) {            System.out.println(employee);        }        System.out.println("--------------------------------");        employees                = filterList(empList, new filterEmployeeBySalary());        for (Employee employee : employees) {            System.out.println(employee);        }    }    public List filterList(List empList, MyPredicate pre) {        List emps = new ArrayList<>();        for (Employee emp : empList) {            if(pre.test(emp)) {                emps.add(emp);            }        }        return emps;    }    // 优化方式二:匿名内部类    @Test    public void test5() {        List emps = filterList(empList, new MyPredicate() {            @Override            public boolean test(Employee employee) {                return employee.getSalary() > 4000;            }        });        emps.forEach(System.out::println);    }    // 优化方式三:Lambda表达式    @Test    public void test6() {        List employees = filterList(empList, e -> e.getSalary() > 4000);        employees.forEach(System.out::println);    }    // 优化方式四:streamApi    @Test    public void test7() {        empList.stream()                .filter(e -> e.getSalary() > 4000)                .limit(1)                .forEach(System.out::println);        System.out.println("-----------------------");        empList.stream()                .map(Employee::getName)                .forEach(System.out::println);    }

六、新时间日期API

原本的时间相关的类存在线程安全问题

public class testSimpleDateFORMat {    public static void main(String[] args) throws ExecutionException, InterruptedException {        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");        Callable task = new Callable() {            @Override            public Date call() throws Exception {                return sdf.parse("20230518");            }        };        ExecutorService pool = Executors.newFixedThreadPool(10);        List> results = new ArrayList<>();        for(int i = 0; i < 10; i ++) {            results.add(pool.submit(task));        }        for(Future future:results) {            System.out.println(future.get());        }        pool.shutdown();    }}

以前的方式,加,这里使用ThreadLocal

public class DateFormatThreadLocal {    private static final ThreadLocal df = new ThreadLocal(){            protected DateFormat initialValue() {                return new SimpleDateFormat("yyyyMMdd");            }    };    public static Date convert(String source) throws ParseException {        return df.get().parse(source);    }}=========================================================================public class testSimpleDateFormat {    public static void main(String[] args) throws ExecutionException, InterruptedException {//        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");        Callable task = new Callable() {            @Override            public Date call() throws Exception {//                return sdf.parse("20230518");                return DateFormatThreadLocal.convert("20230518");            }        };        ExecutorService pool = Executors.newFixedThreadPool(10);        List> results = new ArrayList<>();        for(int i = 0; i < 10; i ++) {            results.add(pool.submit(task));        }        for(Future future:results) {            System.out.println(future.get());        }        pool.shutdown();    }}

 jdk1.8的时间类

public class testSimpleDateFormat {    public static void main(String[] args) throws ExecutionException, InterruptedException {        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");        Callable task = new Callable() {            @Override            public LocalDate call() throws Exception {                return LocalDate.parse("20230518", dtf);            }        };        ExecutorService pool = Executors.newFixedThreadPool(10);        List> results = new ArrayList<>();        for(int i = 0; i < 10; i ++) {            results.add(pool.submit(task));        }        for(Future future:results) {            System.out.println(future.get());        }        pool.shutdown();    }}

(一)使用LocalDateLocalTimeLocalDateTime

LocalDate LocalTime LocalDateTime 类的实例是 不可变的对象 ,分别表示使用 ISO-8601 历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。

 

(二)使用Instant时间戳

用于“时间戳”的运算。它是以 Unix 元年 ( 传统的设定为UTC 时区 1970 1 1 日午夜时分 ) 开始所经历的描述进行运算

(三)Duration Period

Duration: 用于计算两个“时间”间隔 Period: 用于计算两个“日期”间隔

(四)日期的操纵

TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作。 TemporalAdjuster s : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。

(五)解析与格式化

java.time.format.DateTimeFormatter 类:该类提供了三种 格式化方法: 预定义的标准格式 语言环境相关的格式 自定义的格式

(六)时区的处理

Java8 中加入了对时区的支持,带时区的时间为分别为: ZonedDate ZonedTime ZonedDateTime 其中每个时区都对应着 ID ,地区 ID 都为 “{区域 }/{ 城市 } ”的格式 例如 : Asia/Shanghai ZoneId :该类中包含了所有的时区信息         getAvailableZoneIds() : 可以获取所有时区时区信息         of(id) : 用指定的时区信息获取 ZoneId 对象

(七)与传统日期处理的转换

public class testLocalDateTime {    // ZonedDate/ZonedTime/ZonedDateTime 时区相关的    @Test    public void test8() {        // 获得的是指定时区的当前时间        LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));        System.out.println(ldt);        LocalDateTime ldt2 = LocalDateTime.now();        ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Asia/Shanghai"));        // 输出2023-05-18T22:01:45.684+08:00[Asia/Shanghai]        // +08:00 是距离UTC的时间差        System.out.println(zdt);    }    @Test    public void test7() {        // 获取支持的时区        Set set = ZoneId.getAvailableZoneIds();        set.forEach(System.out::println);    }    // DateTimeFormatter : 格式化时间/日期    @Test    public void test6() {        DateTimeFormatter dtf1 = DateTimeFormatter.ISO_DATE;        LocalDateTime ldt1 = LocalDateTime.now();        System.out.println(ldt1.format(dtf1));        System.out.println("-------------------------------");        // 格式化        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");        String time = ldt1.format(dtf2);        System.out.println(time);        // 再格式化回去        LocalDateTime ldt2 = ldt1.parse(time, dtf2);        System.out.println(ldt2);    }    // TemporalAdjuster: 时间矫正器    @Test    public void test5() {        LocalDateTime ldt1 = LocalDateTime.now();        System.out.println(ldt1);        // 直接设置日期为哪一天,不太方便求下一个周几等的操作        LocalDateTime ldt2 = ldt1.withDayOfMonth(10);        System.out.println(ldt2);        // 求下一个星期日        LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));        System.out.println(ldt3);        //自定义:下一个工作日        LocalDateTime ldt5 = ldt1.with((l) -> {            LocalDateTime ldt4 = (LocalDateTime)l;            DayOfWeek dayOfWeek = ldt4.getDayOfWeek();            if(dayOfWeek.equals(DayOfWeek.FRIDAY)) {                return ldt4.plusDays(3);            } else if(dayOfWeek.equals(DayOfWeek.SATURDAY)) {                return ldt4.plusDays(2);            } else {                return ldt4.plusDays(1);            }        });        System.out.println(ldt5);    }    // 3、 Duration: 计算两个“时间”之间的间隔    //     Period: 计算两个“日期”之间的间隔    @Test    public void test4() {        LocalDate l1 = LocalDate.of(2022, 5, 17);        LocalDate l2 = LocalDate.now();        Period period = Period.between(l1, l2);        System.out.println(period);        System.out.println(period.getYears());        System.out.println(period.getMonths());        System.out.println(period.getDays());    }    @Test    public void test3() throws InterruptedException {        Instant i1 = Instant.now();        Thread.sleep(1000);        Instant i2 = Instant.now();        System.out.println(Duration.between(i1, i2));        System.out.println("----------------------------");        LocalTime l1 = LocalTime.now();        Thread.sleep(1000);        LocalTime l2 = LocalTime.now();        System.out.println(Duration.between(l1, l2));    }    // 2、Instant :时间戳(以Unix元年:1970年1月1日00:00:00到某个时间之间的毫秒数)    @Test    public void test2() {        Instant i1 = Instant.now(); // 默认获取UTC时区        System.out.println(i1);        // 与中国相差八个时区,可设置偏移        OffsetDateTime time = i1.atOffset(ZoneOffset.ofHours(8));        System.out.println(time);        // 从 1970-现在 的秒数        long second = i1.getEpochSecond();        System.out.println(second);        // 从元年开始计算,这里是+60s        Instant i2 = Instant.ofEpochSecond(60);        System.out.println(i2);    }    // 1、LocalDate LocalTime LocalDateTime(前两个的结合体)    // 一个会用另外两个也差不多了    @Test    public void test1() {        // 返回当前年月日时分秒毫秒        LocalDateTime ldt1 = LocalDateTime.now();        System.out.println(ldt1);        // 构造日期        LocalDateTime ldt2 = LocalDateTime.of(2023, 5, 18, 20, 2, 20);        System.out.println(ldt2);        // 加年数        LocalDateTime ldt3 = ldt1.plusYears(2);        System.out.println(ldt3);        // 减年数        LocalDateTime ldt4 = ldt1.minusYears(2);        System.out.println(ldt4);        // 取详细信息        System.out.println(ldt1.getYear());        System.out.println(ldt1.getMonthValue());        System.out.println(ldt1.getDayOfMonth());        System.out.println(ldt1.getHour());        System.out.println(ldt1.getMinute());        System.out.println(ldt1.getNano());    }}

 七、接口中的默认方法与静态方法

Java 8中允许接口中包含具有具体实现的方法,该方法称为“默认方法” ,默认方法使用 default 关键字修饰。 接口默认方法的”类优先”原则 若一个接口中定义了一个默认方法,而另外一个父类或接口中 又定义了一个同名的方法时 选择父类中的方法。如果一个父类提供了具体的实现,那么 接口中具有相同名称和参数的默认方法会被忽略。 接口冲突。如果一个父接口提供一个默认方法,而另一个接 口也提供了一个具有相同名称和参数列表的方法(不管方法 是否是默认方法),那么必须覆盖该方法来解决冲突 Java8 中,接口中允许添加静态方法。
public class MyClass {    public String getName() {        return "father";    }}===========================================================================public interface MyFun {    default String getName() {        return "hahaha";    }}===========================================================================public interface MyInterface {    default String getName() {        return "heiheihei";    }}===========================================================================public class SubClass extends MyClass implements MyFun, MyInterface {    // 两个接口中都有同名函数时,需要实现方法指定执行哪一个接口中的函数// 当父类中也有同名函数而子类中没有时,默认调用父类函数,忽略接口中的默认函数}===========================================================================public class testDefault {    public static void main(String[] args) {        SubClass subClass = new SubClass();        System.out.println(subClass.getName());    }}

public class SubClass extends MyClass implements MyFun, MyInterface {    // 两个接口中都有同名函数时,需要实现方法指定执行哪一个接口中的函数// 当父类中也有同名函数而子类中没有时,默认调用父类函数,忽略接口中的默认函数    @Override    public String getName() {        return MyInterface.super.getName();    }}

public interface MyInterface {    default String getName() {        return "heiheihei";    }    public static void show() {        System.out.println("展示");    }}==================================================public class testDefault {    public static void main(String[] args) {        SubClass subClass = new SubClass();        System.out.println(subClass.getName());        // 调用接口中的静态方法        MyInterface.show();    }}

八、其他新特性

(一)Optional

Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。 常用方法:
  • Optional.of(T t) : 创建一个 Optional 实例
  • Optional.empty() : 创建一个空的 Optional 实例
  • Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
  • isPresent() : 判断是否包含值
  • orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
  • orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
  • map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
  • flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
public class testOptional {        // 为什么说它方便了空指针异常的调试,因为这里出现空值会报错NoSuchElementException    @Test    public void test6() {        Optional optional = Optional.ofNullable(new Employee("张三", 18, 50000.0, Employee.Status.BUSY));//        Optional name = optional.map((e) -> optional.get().getName());//        System.out.println(name.get());        Optional name = optional.flatMap(e -> Optional.of(e.getName()));        System.out.println(name.get());    }    @Test    public void test5() {        Optional optional = Optional.ofNullable(null);        // 如果optional为空,那么返回传进去的默认参数,否则返回optional的参数        Employee employee1 = optional.orElse(new Employee());        System.out.println(employee1);        // 使用供给型函数式接口,如果optional为空,那么返回传进去的默认参数,否则返回optional的参数        Employee employee2 = optional.orElseGet(Employee::new);        System.out.println(employee2);    }    @Test    public void test4() {        Optional optional = Optional.ofNullable(null);//        System.out.println(optional.get()); // 报错NoSuchElementException        // 安全的做法,判断是否包含值        if(optional.isPresent()) {            System.out.println(optional.get());        }    }    @Test    public void test3() {        Optional optional = Optional.empty();        System.out.println(optional.get()); // 报错NoSuchElementException    }    @Test    public void test2() {        Optional optional = Optional.of(null); // 报错NullPointerException    }    @Test    public void test1() {        Optional optional = Optional.of(new Employee());        System.out.println(optional.get());    }}

(二)重复注解与类型注解

Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。
@Repeatable(MyAnnotaions.class) // 指明容器类@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotaion {    String value() default "atguigu";}===============================================================================@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotaions {    MyAnnotaion[] value();}===============================================================================public class TestAnnotaion {    @Test    public void test1() throws Exception {        Class aClass = TestAnnotaion.class;        Method method =                aClass.getMethod("show");        MyAnnotaion[] annotations = method.getAnnotationsByType(MyAnnotaion.class);        for(MyAnnotaion mya: annotations) {            System.out.println(mya);        }    }    @MyAnnotaion("world")    @MyAnnotaion("hello")    public void show(@MyAnnotaion("abc") String abs) {    }}

来源地址:https://blog.csdn.net/m0_62946761/article/details/130753016

--结束END--

本文标题: Java——JDK1.8新特性

本文链接: https://lsjlt.com/news/415499.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java——JDK1.8新特性
    目录 一、Lambda 表达式 (一)Lambda 表达式语法 (二)类型推断 二、函数式接口 (一)自定义函数式接口 (二)作为参数传递Lambda 表达式 (三)Java 内置四大核心函数式接口 三、方法引用 四、Stream API ...
    99+
    2023-09-22
    java 开发语言 servlet 后端 java-consul
  • Java8(JDK1.8)新特性
    一、Java8(JDK1.8)新特性 Lamdba表达式 函数式接口 方法引用和构造引用 Stream API 接口中的默认方法和静态方法 新时间日期API OPtional 其他特性 二、java8(JDK1.8)新特性简介 速度快; 代...
    99+
    2023-09-12
    java
  • Java关于JDK1.8新特性的Stream流
    目录Java的Stream流一、定义二、操作的特征三、代码示例1、生成流2、forEach迭代3、limit方法用于获取指定数量的流4、map5、sorted6、并行(paralle...
    99+
    2024-04-02
  • JDK1.8新特性之方法引用 ::和Optional详解
    一:简介 方法引用分为三种,方法引用通过一对双冒号:: 来表示,方法引用是一种函数式接口的另一种书写方式 静态方法引用,通过类名::静态方法名, 如 Integer::pa...
    99+
    2024-04-02
  • JAVA 8 的新特性
    简介: 前段时间面了完美世界,被问到Java8的新特性,在此特地记录一下,虽然现在Java的版本可能已经很高了,但是Java8的新特性依然值得学习一下! 1. Lambda 表达式 lambda表达...
    99+
    2023-09-08
    java 开发语言
  • Java新特性:Optional类
    Java新特性:Optional类 Optional 类是 Java 8 才引入的,Optional 是个容器,它可以保存类型 T 的值,或者仅仅保存 null。Optional 提供了很多方法,这样我们就不用显式进行空值检测。Opti...
    99+
    2023-08-17
    java 开发语言 Optional
  • Java 10 新特性解读
    Java 10 是 JDK 的第十个版本,于 2018 年 3 月发布。Java 10 引入了一些新的特性和改进,下面是对其进行的解...
    99+
    2023-09-13
    Java
  • JAVA 8新特性有哪些
    这篇文章主要介绍“JAVA 8新特性有哪些”,在日常操作中,相信很多人在JAVA 8新特性有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JAVA 8新特性有哪些”的疑惑...
    99+
    2024-04-02
  • java 1.8新特性有哪些
    这篇“java 1.8新特性有哪些”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“java 1.8新特性有哪些”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解,接下来就让我们进入...
    99+
    2023-06-06
  • Java 17 版本的新特性
    Java 17 版本的新特性 💗Sealed类💗Pattern Matching for instanceof💗 垃圾回收器改进💗...
    99+
    2023-09-16
    java jvm 开发语言
  • Java 21 新特性和改进
    Java 21 是 Java 17 之后的下一个 LTS 版本。虚拟线程在 Java 21 中将成为正式功能。可以预期的是,Java 21 会成为一个很流行的 Java 版本。 Java 21 将在 2023 年 9 月 19 日发布。目...
    99+
    2023-09-21
    java jvm 开发语言
  • Java新特性:Lambda表达式
    Java新特性:Lambda表达式 Lambda 表达式(Lambda expression),也可称为闭包(Closure),是 Java(SE)8 中一个重要的新特性。Lambda 表达式允许我们通过表达式来代替功能接口。Lambd...
    99+
    2023-08-17
    java python 开发语言
  • 怎么使用的新Java特性
    这篇文章主要讲解了“怎么使用的新Java特性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用的新Java特性”吧!1 Try-with-resource 语句使用 try-catch ...
    99+
    2023-06-15
  • 详解Java中switch的新特性
    目录一. switch分支结构1. 简介2. 基本语法3. 语法规则(重点)4. 执行逻辑二. switch案例1. 基本案例2. case穿透三. switch新特性(了解)1. ...
    99+
    2023-05-20
    Java switch新特性 Java switch switch新特性
  • Java 1.5新特性Enum的用法
    Enum是enumeration(列举)的简写形式,包含在java.lang包中.public enum Season { winter, spring, summer, fall }一个enum是定义一组值的对象,它可以包括零个或多个值成...
    99+
    2023-06-03
  • 新特性解读 | mysql 8.0 memcached api 新特性
    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MyS...
    99+
    2017-07-06
    新特性解读 | mysql 8.0 memcached api 新特性
  • JDK 新特性篇:JDK 8 新特性详解
    Java8新特性简介 Java 8 (又称为 JDK 1.8) 是 Java 语言开发的一个主要版本。Java 8 是 Oracle 公司于 2014 年 3 月发布,可以看成是自 Java 5 以来最具革命性的版本。Java 8 为 J...
    99+
    2023-09-12
    java jvm 开发语言
  • JDK 新特性篇:JDK 9 新特性详解
    JDK 9 是 Java 平台的一次重大更新,引入了许多新的特性和改进。以下是 JDK 9 的一些主要新特性的详细解释。模块化系统(...
    99+
    2023-09-13
    JDK
  • JDK 新特性篇:JDK 10 新特性详解
    JDK 10 是 Java 开发工具包的一个版本,其中包含了一些新的特性和改进。下面是 JDK 10 的一些新特性的详细解释:1. ...
    99+
    2023-09-14
    JDK
  • 一篇文章带你了解jdk1.8新特性--为什么使用lambda表达式
    目录一、为什么使用Lambda表达式二、匿名内部类的方式与Lambda表达式方式的比较(示例)三、需求演示示例一、创建一个员工实体类二、普通方式实现1、代码如下2、运行main函数,...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作