1. 史上最全jdk版本新特性大全

        共 16053字,需瀏覽 33分鐘

         ·

        2021-06-08 02:53

        前言

        在本文中,我將描述自第8版以來Java最重要且對開發(fā)人員友好的功能。為什么會有這樣的主意?在Web上,您可以找到許多文章,其中包含每種Java版本的新功能列表。但是,由于缺少文章,因此無法簡要概述自第8版以來最重要的更改。好的,但是為什么是第8版?令人驚訝的是,它仍然是最常用的Java版本。即使我們已經(jīng)到了Java 16發(fā)行版的前夕。如您所見,超過46%的響應(yīng)者仍在生產(chǎn)中使用Java 8。相比之下,只有不到10%的響應(yīng)者使用Java 12或更高版本。

        java版本使用占比


        那接下來咋們從JDK8到JDK15,給大家介紹新的JDK提供給咋們的新特性!

         

        JDK8

        1. Lambda表達式

        最直接作用就是減少代碼,代碼直接減少50%+,顯得非常簡潔

         //使用java匿名內(nèi)部類
          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中  篩選產(chǎn)品為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. 函數(shù)式接口

        位于java.util.function包下,下面介紹最常用的幾個

        • Predicate

        接收一個值返回boolean

          Predicate p = t->true;
        • Supplier

        無接受參數(shù)返回一個值

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

        接受一個參數(shù)無返回值

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

        接受參數(shù)T 返回參數(shù)R

        Function<Long,String> f = c -> String.valueof(c);
        • 其他還有一個 BiFunction,BiConsumer,DoubleSupplier等大家有興趣自己去閱讀下源碼

        1. 方法引用

        • 靜態(tài)引用:格式:Class::static_method

        List<String> list = Arrays.asList("a","b","c");
        list.forEach(str -> System.out.print(str));
        list.forEach(System.out::print);
        • 構(gòu)造器調(diào)用 構(gòu)造器方法引用格式:Class::new,調(diào)用默認構(gòu)造器

        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;
            }
        }
        • 方法調(diào)用 格式: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(){

            // 循環(huán)過濾元素                                       
            proList.stream()
                   .fliter((p) -> "紅色".equals(p.getColor()))
                   .forEach(System.out::println);

            // map處理元素然后再循環(huán)遍歷
            proList.stream()
                   .map(Product::getName)
                   .forEach(System.out::println);
          
           // map處理元素轉(zhuǎn)換成一個List
           proList.stream()
                   .map(Product::getName)
                   .collect(Collectors.toList());
        }
        1. 接口中的默認方法和靜態(tài)方法

        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的一項新功能,即集合工廠方法,您可以輕松地使用預(yù)定義的數(shù)據(jù)創(chuàng)建不可變的集合。您只需要在特定集合類型上使用of方法。

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

        在Java 9之前,您可以使用Collections,但這絕對是一種更復(fù)雜的方法。

        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對象表創(chuàng)建即可使用Arrays.asList(...)method。

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

        從Java 8開始,您可以在接口內(nèi)部使用公共默認方法。但是僅從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();
        }

        因此,您可以避免將帶參數(shù)的if語句與isPresentmethod一起使用。

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

        第二種有趣的方法是ifPresentOrElse。如果存在一個值,它將使用該值執(zhí)行給定的操作。否則,它將執(zhí)行給定的基于空的操作。

        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關(guān)鍵字而不是類型。從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,相同的示例要復(fù)雜得多。

        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

        文本塊是多行字符串文字,它避免使用轉(zhuǎn)義序列,并以可預(yù)測的方式自動設(shè)置字符串格式。它還使開發(fā)人員可以控制字符串的格式。從Java 13開始,文本塊可用作預(yù)覽功能。它們以三個雙引號(""")開頭。讓我們看看我們?nèi)绾屋p松地創(chuàng)建和格式化JSON消息。

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

        創(chuàng)建Java 13之前的相同JSON字符串要復(fù)雜得多。

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

         

         

        JDK14

        使用Records,您可以定義不可變的純數(shù)據(jù)類(僅限getter)。它會自動創(chuàng)建toString,equals和hashCode方法。實際上,您只需要定義如下所示的字段即可。

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

        具有類似功能的類如record包含字段,構(gòu)造函數(shù),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關(guān)鍵字,sealed您可以定義哪些其他類或接口可以擴展或?qū)崿F(xiàn)當前類。

        public abstract sealed class Pet permits Cat, Dog {}

        允許的子類必須定義一個修飾符。如果您不想允許任何其他擴展名,則需要使用final關(guān)鍵字。

        public final class Cat extends Pet {}

        另一方面,您可以打開擴展類。在這種情況下,應(yīng)使用non-sealed修飾符。

        public non-sealed class Dog extends Pet {}

        當然,下面的可見聲明是不允許的。

        public final class Tiger extends Pet {}



        有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

        歡迎大家關(guān)注Java之道公眾號


        好文章,我在看??

        瀏覽 40
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 夜夜春夜夜弄 | 黄色短视频网址在线播放 | 欧美风狂大伦交XXXX | 亚洲精品自拍偷拍 | 日本免费一二三区 |