<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 16053字,需瀏覽 33分鐘

           ·

          2021-06-08 02:53

          前言

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

          java版本使用占比


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

           

          JDK8

          1. Lambda表達(dá)式

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

           //使用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表達(dá)式
            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包下,下面介紹最常用的幾個(gè)

          • Predicate

          接收一個(gè)值返回boolean

            Predicate p = t->true;
          • Supplier

          無(wú)接受參數(shù)返回一個(gè)值

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

          接受一個(gè)參數(shù)無(wú)返回值

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

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

          Function<Long,String> f = c -> String.valueof(c);
          • 其他還有一個(gè) 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)用默認(rèn)構(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進(jìn)行集合的操作
          @Test
          public void test(){

              // 循環(huán)過(guò)濾元素                                       
              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)換成一個(gè)List
             proList.stream()
                     .map(Product::getName)
                     .collect(Collectors.toList());
          }
          1. 接口中的默認(rèn)方法和靜態(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

          用于處理對(duì)象空指針異常:

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

           

           

          JDK9

          • 收集工廠方法

          借助Java 9的一項(xiàng)新功能,即集合工廠方法,您可以輕松地使用預(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,但這絕對(duì)是一種更復(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對(duì)象表創(chuàng)建即可使用Arrays.asList(...)method。

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

          從Java 8開(kāi)始,您可以在接口內(nèi)部使用公共默認(rèn)方法。但是僅從Java 9開(kāi)始,由于接口中的私有方法,您將能夠充分利用此功能。

          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開(kāi)始,有幾種用于Optional的有用方法。其中最有趣的兩個(gè)是orElseThrow和ifPresentOrElse。如果沒(méi)有值,則使用該orElseThrow方法拋出NoSuchElementException。否則,它返回一個(gè)值。

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

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

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

          第二種有趣的方法是ifPresentOrElse。如果存在一個(gè)值,它將使用該值執(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開(kāi)始,您可以聲明沒(méi)有其類型的局部變量。您只需要定義var關(guān)鍵字而不是類型。從Java 11開(kāi)始,您還可以將其與lambda表達(dá)式一起使用,如下所示。

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

           

           

          JDK 12

          使用Switch表達(dá)式,您可以定義多個(gè)case標(biāo)簽并使用箭頭返回值。此功能自JDK 12起可用。它使Switch表達(dá)式真正更易于訪問(wèn)。

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

          對(duì)于低于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ù)測(cè)的方式自動(dòng)設(shè)置字符串格式。它還使開(kāi)發(fā)人員可以控制字符串的格式。從Java 13開(kāi)始,文本塊可用作預(yù)覽功能。它們以三個(gè)雙引號(hào)(""")開(kāi)頭。讓我們看看我們?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)。它會(huì)自動(dòng)創(chuàng)建toString,equals和hashCode方法。實(shí)際上,您只需要定義如下所示的字段即可。

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

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

          public abstract sealed class Pet permits Cat, Dog {}

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

          public final class Cat extends Pet {}

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

          public non-sealed class Dog extends Pet {}

          當(dāng)然,下面的可見(jiàn)聲明是不允許的。

          public final class Tiger extends Pet {}



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

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


          好文章,我在看??

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉亚洲在线 | 日韩精品黄 | 青娱乐精品视频 | 看片地址 | 中文字幕av久久爽一区 |