我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java——JDK1.8新特性

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java——JDK1.8新特性

目录

一、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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java——JDK1.8新特性

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java新特性:Optional类

Java新特性:Optional类 Optional 类是 Java 8 才引入的,Optional 是个容器,它可以保存类型 T 的值,或者仅仅保存 null。Optional 提供了很多方法,这样我们就不用显式进行空值检测。Opti
2023-08-17

Java 10 新特性解读

Java 10 是 JDK 的第十个版本,于 2018 年 3 月发布。Java 10 引入了一些新的特性和改进,下面是对其进行的解读:1. 局部变量类型推断:Java 10 引入了 var 关键字,可以在局部变量的声明中使用。var 关键
2023-09-13

Java新特性:Lambda表达式

Java新特性:Lambda表达式 Lambda 表达式(Lambda expression),也可称为闭包(Closure),是 Java(SE)8 中一个重要的新特性。Lambda 表达式允许我们通过表达式来代替功能接口。Lambd
2023-08-17

java 1.8新特性有哪些

这篇“java 1.8新特性有哪些”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“java 1.8新特性有哪些”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解,接下来就让我们进入
2023-06-06

详解Java中switch的新特性

这篇文章主要介绍了Java中switch的新特性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-20

怎么使用的新Java特性

这篇文章主要讲解了“怎么使用的新Java特性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用的新Java特性”吧!1 Try-with-resource 语句使用 try-catch
2023-06-15

Java 1.5新特性Enum的用法

Enum是enumeration(列举)的简写形式,包含在java.lang包中.public enum Season { winter, spring, summer, fall }一个enum是定义一组值的对象,它可以包括零个或多个值成
2023-06-03

JDK 新特性篇:JDK 9 新特性详解

JDK 9 是 Java 平台的一次重大更新,引入了许多新的特性和改进。以下是 JDK 9 的一些主要新特性的详细解释。模块化系统(Module System):JDK 9 引入了一个全新的模块化系统,它允许将代码和资源以模块的形式组织和封
2023-09-13

新特性解读 | mysql 8.0 memcached api 新特性

作者:杨涛涛资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、My
新特性解读 | mysql 8.0 memcached api 新特性
2017-07-06

JDK 新特性篇:JDK 10 新特性详解

JDK 10 是 Java 开发工具包的一个版本,其中包含了一些新的特性和改进。下面是 JDK 10 的一些新特性的详细解释:1. 局部变量类型推断:JDK 10 引入了局部变量类型推断的功能,使得在声明变量时可以使用 var 关键字代替具
2023-09-14

Angular5.0.0新特性

文章来自官网部分翻译https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935cedAngular5.0.0版本已经正式发布总结一下v5.0.0带来的新变
2023-05-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录