zoukankan      html  css  js  c++  java
  • 史上最全jdk新特性总结,涵盖jdk8到jdk15!

    前言

    在本文中,我将描述自第8版以来Java最重要且对开发人员友好的功能。为什么会有这样的主意?在Web上,您可以找到许多文章,其中包含每种Java版本的新功能列表。但是,由于缺少文章,因此无法简要概述自第8版以来最重要的更改。好的,但是为什么是第8版?令人惊讶的是,它仍然是最常用的Java版本。即使我们已经到了Java 16发行版的前夕果。如您所见,超过46%的响应者仍在生产中使用Java 8。相比之下,只有不到10%的响应者使用Java 12或更高版本。

    java版本使用占比
    java版本使用占比

    那接下来咋们从JDK8到JDK15,给大家介绍新的JDK提供给咋们的新特性!

    JDK8

    1. Lambda表达式

    最直接作用就是减少代码,代码直接减少50%+,显得非常简洁

     //使用java匿名内部类
      Comparator<Integer> cpt = new Comparator<Integer>() {
          @Override
          public int compare(Integer o1, Integer o2) {
              return Integer.compare(o1,o2);
          }
      };

      TreeSet<Integer> set = new TreeSet<>(cpt);

      System.out.println("=========================");

      //使用JDK8 lambda表达式
      Comparator<Integer> cpt2 = (x,y) -> Integer.compare(x,y);
      TreeSet<Integer> set2 = new TreeSet<>(cpt2);
    // java7中  筛选产品为nike的
    public  List<Product> filterProductByColor(List<Product> list){
        List<Product> prods = new ArrayList<>();
        for (Product product : list){
            if ("nike".equals(product.getName())){
                prods.add(product);
            }
        }
        return prods;
     }

    // 使用 lambda
    public  List<Product> filterProductByPrice(List<Product> list){
      return list.stream().filter(p->"nike".equals(p.getName())).collect(Collectors.toList());  
     }

    1. 函数式接口

    位于java.util.function包下,下面介绍最常用的几个

    • Predicate

    接收一个值返回boolean

      Predicate p = t->true;
    • Supplier

    无接受参数返回一个值

    Supplier<T> s = () -> new T();
    • Consumer

    接受一个参数无返回值

    Consumer<String> c = c -> System.out.println(s);
    • Function<T,R>

    接受参数T 返回参数R

    Function<Long,String> f = c -> String.valueof(c);
    • 其他还有一些 BiFunction,BiConsumer,DoubleSupplier等大家有兴趣自己去阅读下源码
    1. 方法引用

    • 静态引用: 格式:Class::static_method
    List<String> list = Arrays.asList("a","b","c");
    list.forEach(str -> System.out.print(str));
    list.forEach(System.out::print);
    • 构造器调用 构造器方法引用格式:Class::new,调用默认构造器
    List<String> list = Arrays.asList("a","b","c");
    List<Test> list.stream().map(Test::new).collect(Collectors.toList());

    public class Test{
        private final String desc;
      
        public Test(String desc){
          this.desc=desc;
        }
    }
    • 方法调用 格式:instance::method
    List<String> list = Arrays.asList("a","b","c");
    Test test = new Test();
    List<String> list.stream().map(test::toAdd).collect(Collectors.toList());

    public class Test{
        private final String desc;
      
        public Test(String desc){
          this.desc=desc;
        }

        public String toAdd(String desc){
            return desc+"add";
        }
    }
    1. Stream API

    // 使用jdk1.8中的Stream API进行集合的操作
    @Test
    public void test(){

        // 循环过滤元素                                       
        proList.stream()
               .fliter((p) -> "红色".equals(p.getColor()))
               .forEach(System.out::println);

        // map处理元素然后再循环遍历
        proList.stream()
               .map(Product::getName)
               .forEach(System.out::println);
      
       // map处理元素转换成一个List
       proList.stream()
               .map(Product::getName)
               .collect(Collectors.toList());
    }
    1. 接口中的默认方法和静态方法

    public interface ProtocolAdaptor {

        ProtocolAdaptor INSTANCE = DynamicLoader.findFirst(ProtocolAdaptor.class).orElse(null);

       
        default ProtocolAdaptor proxy() {
            return (ProtocolAdaptor) Proxy.newProxyInstance(ProtocolAdaptor.class.getClassLoader(),
                    new Class[]{ProtocolAdaptor.class},
                    (proxy, method, args) -> intercept(method, args));
        }
    }  
    1. Optional

    用于处理对象空指针异常:

      public String getDesc(Test test){
              return Optional.ofNullable(test)
                      .map(Test::getDesc).else("");
          }

    JDK9

    • 收集工厂方法

    借助Java 9的一项新功能,即集合工厂方法,您可以轻松地使用预定义的数据创建不可变的集合。您只需要在特定集合类型上使用of方法。

    List<String> fruits = List.of("apple""banana""orange");
    Map<Integer, String> numbers = Map.of(1, "one", 2,"two", 3, "three");

    在Java 9之前,您可以使用Collections,但这绝对是一种更复杂的方法。

    public List<String> fruits() {
     List<String> fruitsTmp = new ArrayList<>();
     fruitsTmp.add("apple");
     fruitsTmp.add("banana");
     fruitsTmp.add("orange");
     return Collections.unmodifiableList(fruitsTmp);
    }

    public Map<Integer, String> numbers() {
     Map<Integer, String> numbersTmp = new HashMap<>();
     numbersTmp.put(1, "one");
     numbersTmp.put(2, "two");
     numbersTmp.put(3, "three");
     return Collections.unmodifiableMap(numbersTmp);
    }

    同样,仅从ArrayList对象表创建即可使用Arrays.asList(...)method。

    public List<String> fruitsFromArray() {
     String[] fruitsArray = {"apple""banana""orange"};
     return Arrays.asList(fruitsArray);
    }
    • 接口中的私有方法

    从Java 8开始,您可以在接口内部使用公共默认方法。但是仅从Java 9开始,由于接口中的私有方法,您将能够充分利用此功能。

    ublic interface ExampleInterface {

        private void printMsg(String methodName) {
            System.out.println("Calling interface");
            System.out.println("Interface method: " + methodName);
        }

        default void method1() {
            printMsg("method1");
        }

        default void method2() {
            printMsg("method2");
        }
    }

    JDK10

    从Java 9和Java 10开始,有几种用于Optional的有用方法。其中最有趣的两个是orElseThrow和ifPresentOrElse。如果没有值,则使用该orElseThrow方法抛出NoSuchElementException。否则,它返回一个值。

    public Person getPersonById(Long id) {
     Optional<Person> personOpt = repository.findById(id);
     return personOpt.orElseThrow();
    }

    因此,您可以避免将带参数的if语句与isPresentmethod一起使用。

    public Person getPersonByIdOldWay(Long id) {
     Optional<Person> personOpt = repository.findById(id);
     if (personOpt.isPresent())
      return personOpt.get();
     else
      throw new NoSuchElementException();
    }

    第二种有趣的方法是ifPresentOrElse。如果存在一个值,它将使用该值执行给定的操作。否则,它将执行给定的基于空的操作。

    public void printPersonById(Long id) {
     Optional<Person> personOpt = repository.findById(id);
     personOpt.ifPresentOrElse(
       System.out::println,
       () -> System.out.println("Person not found")
     );
    }

    在Java 8中,我们可以if-else直接与isPresent方法一起使用。

    public void printPersonByIdOldWay(Long id) {
     Optional<Person> personOpt = repository.findById(id);
     if (personOpt.isPresent())
      System.out.println(personOpt.get());
     else
      System.out.println("Person not found");
    }

    JDK 10 && JDK 11

    从Java 10开始,您可以声明没有其类型的局部变量。您只需要定义var关键字而不是类型。从Java 11开始,您还可以将其与lambda表达式一起使用,如下所示。

    public String sumOfString() {
     BiFunction<String, String, String> func = (var x, var y) -> x + y;
     return func.apply("abc""efg");
    }

    JDK 12

    使用Switch表达式,您可以定义多个case标签并使用箭头返回值。此功能自JDK 12起可用。它使Switch表达式真正更易于访问。

      public String newMultiSwitch(int day) {
            return switch (day) {
                case 1, 2, 3, 4, 5 -> "workday";
                case 6, 7 -> "weekend";
                default -> "invalid";
            };
        }

    对于低于12的Java,相同的示例要复杂得多。

    public String oldMultiSwitch(int day) {
            switch (day) {
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                    return "workday";
                case 6:
                case 7:
                    return "weekend";
                default:
                    return "invalid";
            }
        }

    JDK 13

    文本块是多行字符串文字,它避免使用转义序列,并以可预测的方式自动设置字符串格式。它还使开发人员可以控制字符串的格式。从Java 13开始,文本块可用作预览功能。它们以三个双引号(""")开头。让我们看看我们如何轻松地创建和格式化JSON消息。

        public String getNewPrettyPrintJson() {
            return """
                   {
                        "
    firstName": "Piotr",
                        "
    lastName": "Mińkowski"
                   }
                   "
    "";
        }

    创建Java 13之前的相同JSON字符串要复杂得多。

       public String getOldPrettyPrintJson() {
            return "{\n" +
                   "     \"firstName\": \"Piotr\",\n" +
                   "     \"lastName\": \"Mińkowski\"\n" +
                   "}";
        }

    JDK14

    使用Records,您可以定义不可变的纯数据类(仅限getter)。它会自动创建toString,equals和hashCode方法。实际上,您只需要定义如下所示的字段即可。

    public record Person(String name, int age) {}

    具有类似功能的类如record包含字段,构造函数,getter和实施toString,equals以及hashCode方法。

    public class PersonOld {

        private final String name;
        private final int age;

        public PersonOld(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            PersonOld personOld = (PersonOld) o;
            return age == personOld.age && name.equals(personOld.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }

        @Override
        public String toString() {
            return "PersonOld{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '
    }';
        }

    }

    JDK15

    使用密封类功能,您可以限制超类的使用。使用new关键字,sealed您可以定义哪些其他类或接口可以扩展或实现当前类。

    public abstract sealed class Pet permits Cat, Dog {}

    允许的子类必须定义一个修饰符。如果您不想允许任何其他扩展名,则需要使用final关键字。

    public final class Cat extends Pet {}

    另一方面,您可以打开扩展类。在这种情况下,应使用non-sealed修饰符。

    public non-sealed class Dog extends Pet {}

    当然,下面的可见声明是不允许的。

    public final class Tiger extends Pet {}

    END

    原创整理不容易,欢迎大家关注公众号!阅读更多好文!

    欢迎关注公众号! 公众号回复:入群 ,扫码加入我们交流群! 扫码关注公众号获取更多学习资料

  • 相关阅读:
    strftime和strptime函数对时间的转换操作
    第四章文件和目录学习笔记
    getenv和putenv在获取和设置环境变量中的使用
    SQL 常用语句以及函数(个人收藏)
    详测 Generics Collections TQueue (2): Create、Count、Clear、TrimExcess
    详测 Generics Collections TQueue (1): Enqueue、Dequeue、Peek
    详测 Generics Collections TList (9): BinarySearch
    详测 Generics Collections TList (8): Sort
    详测 Generics Collections TList (4): AddRange、InsertRange、DeleteRange
    详测 Generics Collections TList (7): Items、Contains
  • 原文地址:https://www.cnblogs.com/1ssqq1lxr/p/14657613.html
Copyright © 2011-2022 走看看