前言

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


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

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

欢迎关注公众号!
公众号回复:入群 ,扫码加入我们交流群!

史上最全jdk新特性总结,涵盖jdk8到jdk15!的更多相关文章

  1. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

  2. 史上最全的maven pom.xml文件教程详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  3. 史上最全阿里 Java 面试题总结

    以下为大家整理了阿里巴巴史上最全的 Java 面试题,涉及大量 Java 面试知识点和相关试题. JAVA基础 JAVA中的几种基本数据类型是什么,各自占用多少字节. String类能被继承吗,为什么 ...

  4. 史上最全的maven的pom.xml文件详解(转载)

    此文出处:史上最全的maven的pom.xml文件详解——阿豪聊干货 <project xmlns="http://maven.apache.org/POM/4.0.0" x ...

  5. 史上最全的spark面试题——持续更新中

    史上最全的spark面试题——持续更新中 2018年09月09日 16:34:10 为了九亿少女的期待 阅读数 13696更多 分类专栏: Spark 面试题   版权声明:本文为博主原创文章,遵循C ...

  6. Redis分布式锁 (图解-秒懂-史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  7. Java基础面试题(史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  8. sentinel (史上最全+入门教程)

    文章很长,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈 为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 < Java 高并发 三部曲 > 面试必备 + 大厂 ...

  9. spring + spring mvc + tomcat 面试题(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

随机推荐

  1. Flutter: The getter 'futureDynamicType' was called on null.

    > flutter packages pub upgrade

  2. SPC空投价值高达310万美金,生态建设者直呼真香!

    市场上面有句名言:"人赚不到自己认知以外的财富",这在数字加密上也是共通的.早在本月12日,也就是前天,NGK官方发行的第N波利好---SPC侧链代币空投已经陆续发放了,NGK以及 ...

  3. JPG学习笔记4(附完整代码)

    #topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...

  4. 从微信小程序到鸿蒙js开发【12】——storage缓存&自动登录

    鸿蒙入门指南,小白速来!从萌新到高手,怎样快速掌握鸿蒙开发?[课程入口] 正文: 在应用开发时,我们常需要将一些数据缓存到本地,以提升用户体验.比如在一个电商的app中,如果希望用户登录成功后,下次打 ...

  5. FreeRTOS操作系统最全面使用指南

    FreeRTOS操作系统最全面使用指南 1 FreeRTOS操作系统功能 作为一个轻量级的操作系统,FreeRTOS提供的功能包括:任务管理.时间管理.信号量.消息队列.内存管理.记录功能等,可基本满 ...

  6. 类关系与uml图示表示

    1. 关联(Association).聚合(Aggregation).组合(Composition)区别 association: 两者之间存在某种关联即可,很弱的关系,如student and co ...

  7. DOM及相关操作

    1.背景介绍        什么是DOM?简单地说,DOM是一套对文档的内容进行抽象和概念化的方法, 在现实世界里,人们对所谓的'世界对象模型'都不会陌生,例如,当用'汽车'.'房子'和'树'等名词来 ...

  8. 微信小程序中input标签高度设置

    如果没有设置高度所以显示的是控件自身的高度. 微信小程序input控件原始设置: 上图发现: 我只覆盖了官方input的height,而没有覆盖min-height; .query input{ bo ...

  9. Docker daemon socket权限不足

    一.概述 普通用户执行命令:docker ps报错,具体信息如下: docker: Got permission denied while trying to connect to the Docke ...

  10. MySQL深入研究--学习总结(2)

    前言 接上文,继续学习后续章节. 第四章&第五章<深入浅出索引> 这两章节主要介绍的索引结构及其如何合理建立索引,但是我觉得讲的比较简单. 总结回顾下吧,其实在我之前的文章< ...