JDK8-JDK17中的新特性(var类型推断、模式匹配、Record、密封类)(二)

简介: JDK8-JDK17中的新特性(var类型推断、模式匹配、Record、密封类)(二)

JDK8-JDK17中的新特性(var类型推断、模式匹配、Record、密封类)(一):https://developer.aliyun.com/article/1416372

JDK13的新特性

使用"""作为文本块的开始符和结束符,在其中就可以放置多行的字符串,不需要进行任何转义。因此,文本块将提高Java程序的可读性和可写性。

基本使用:

"""
line1
line2
line3
"""

相当于:

"line1\nline2\nline3\n"

或者一个连接的字符串:

"line1\n" +
"line2\n" +
"line3\n"

如果字符串末尾不需要行终止符,则结束分隔符可以放在最后一行内容上。例如:

"""
line1
line2
line3"""

相当于

"line1\nline2\nline3"

文本块可以表示空字符串,但不建议这样做,因为它需要两行源代码:

String empty = """
""";

举例1:普通文本

原有写法:

String text1 = "The Sound of silence\n" +
                "Hello darkness, my old friend\n" +
                "I've come to talk with you again\n" +
                "Because a vision softly creeping\n" +
                "Left its seeds while I was sleeping\n" +
                "And the vision that was planted in my brain\n" +
                "Still remains\n" +
                "Within the sound of silence";
System.out.println(text1);

使用新特性:

String text2 = """
                The Sound of silence
                Hello darkness, my old friend
                I've come to talk with you again
                Because a vision softly creeping
                Left its seeds while I was sleeping
                And the vision that was planted in my brain
                Still remains
                Within the sound of silence
                """;
System.out.println(text2);

举例2:HTML语句

<html>
  <body>
      <p>Hello, JDK</p>
  </body>
</html>

将其复制到Java的字符串中,会展示成以下内容:

"<html>\n" +
"    <body>\n" +
"        <p>Hello, JDK</p>\n" +
"    </body>\n" +
"</html>\n";

即被自动进行了转义,这样的字符串看起来不是很直观,在JDK 13中:

"""
<html>
  <body>
      <p>Hello, world</p>
  </body>
</html>
""";

举例3:SQL语句

select employee_id,last_name,salary,department_id
from employees
where department_id in (40,50,60)
order by department_id asc

原有方式:

String sql = "SELECT id,NAME,email\n" +
                "FROM customers\n" +
                "WHERE id > 4\n" +
                "ORDER BY email DESC";

使用新特性:

String sql1 = """
                SELECT id,NAME,email
                FROM customers
                WHERE id > 4
                ORDER BY email DESC
                """;

举例4:JSON字符串

原有方式:

String myJson = "{\n" +
                "    \"name\":\"Song Hongkang\",\n" +
                "     \"address\":\"xy5462.blog.csdn.net\",\n" +
                "    \"email\":\"shkstart@126.com\"\n" +
                "}";
System.out.println(myJson);

使用新特性:

String myJson1 = """
                {
                    "name":"Song Hongkang",
                     "address":"xy5462.blog.csdn.net",
                    "email":"shkstart@126.com"
                }""";
System.out.println(myJson1);

JDK14中二次预览特性

JDK14的版本主要增加了两个escapesequences,分别是 \ <line-terminator>\s escape sequence

举例:

public class Feature05 {
    //jdk14新特性
    @Test
    public void test5(){
        String sql1 = """
                SELECT id,NAME,email
                FROM customers
                WHERE id > 4
                ORDER BY email DESC
                """;
        System.out.println(sql1);
        // \:取消换行操作
        // \s:表示一个空格
        String sql2 = """
                SELECT id,NAME,email \
                FROM customers\s\
                WHERE id > 4 \
                ORDER BY email DESC
                """;
        System.out.println(sql2);
    }
}

JDK15中功能转正

1.7 Record

背景

早在2019年2月份,Java 语言架构师 Brian Goetz,曾写文抱怨“Java太啰嗦”或有太多的“繁文缛节”。他提到:开发人员想要创建纯数据载体类(plain data carriers)通常都必须编写大量低价值、重复的、容易出错的代码。如:构造函数、getter/setterequals()hashCode()以及toString()等。

以至于很多人选择使用IDE的功能来自动生成这些代码。还有一些开发会选择使用一些第三方类库,如Lombok等来生成这些方法。

JDK14中预览特性:神说要用record,于是就有了。 实现一个简单的数据载体类,为了避免编写:构造函数,访问器,equals()hashCode ()toString ()等,Java 14推出 record。

record 是一种全新的类型,它本质上是一个 final 类,同时所有的属性都是 final 修饰,它会自动编译出 public gethashcodeequalstoString、构造器等结构,减少了代码编写量。

具体来说:当你用record 声明一个类时,该类将自动拥有以下功能:

  • 获取成员变量的简单方法,比如下面示例中的 name()partner() 。注意区别于我们平常getter()的写法。
  • 一个 equals 方法的实现,执行比较时会比较该类的所有成员属性。
  • 重写 hashCode() 方法。
  • 一个可以打印该类所有成员属性的 toString() 方法。
  • 只有一个构造方法。

此外:

  • 还可以在record声明的类中定义 静态字段、静态方法、构造器 或 实例方法。
  • 不能 在record声明的类中 定义实例字段;类不能声明为abstract;不能声明显式的父类等。

举例1(旧写法)

class Point {
    private final int x;
    private final int y;
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    int x() {
        return x;
    }
    int y() {
        return y;
    }
    public boolean equals(Object o) {
        if (!(o instanceof Point)) return false;
        Point other = (Point) o;
        return other.x == x && other.y == y;
    }
    public int hashCode() {
        return Objects.hash(x, y);
    }
    @Override
    public String toString() {
        return "Point{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

举例1(新写法)

record Point(int x, int y) { }

举例1

public record Dog(String name, Integer age) {
}
public class Java14Record {
    public static void main(String[] args) {
        Dog dog1 = new Dog("牧羊犬", 1);
        Dog dog2 = new Dog("田园犬", 2);
        Dog dog3 = new Dog("哈士奇", 3);
        System.out.println(dog1);
        System.out.println(dog2);
        System.out.println(dog3);
    }
}

举例2

public class Feature07 {
    @Test
    public void test1(){
        //测试构造器
        Person p1 = new Person("罗密欧",new Person("zhuliye",null));
        //测试toString()
        System.out.println(p1);
        //测试equals():
        Person p2 = new Person("罗密欧",new Person("zhuliye",null));
        System.out.println(p1.equals(p2));
        //测试hashCode()和equals()
        HashSet<Person> set = new HashSet<>();
        set.add(p1);
        set.add(p2);
        for (Person person : set) {
            System.out.println(person);
        }
        //测试name()和partner():类似于getName()和getPartner()
        System.out.println(p1.name());
        System.out.println(p1.partner());
    }
    @Test
    public void test2(){
        Person p1 = new Person("zhuyingtai");
        System.out.println(p1.getNameInUpperCase());
        Person.nation = "CHN";
        System.out.println(Person.showNation());
    }
}
public record Person(String name,Person partner) {
    //还可以声明静态的属性、静态的方法、构造器、实例方法
    public static String nation;
    public static String showNation(){
        return nation;
    }
    public Person(String name){
        this(name,null);
    }
    public String getNameInUpperCase(){
        return name.toUpperCase();
    }
    //不可以声明非静态的属性
//    private int id;//报错
}
//不可以将record定义的类声明为abstract的
//abstract record Order(){
//
//}
//不可以给record定义的类声明显式的父类(非Record类)
//record Order() extends Thread{
//
//}

JDK15中第二次预览特性

JDK16中转正特性

最终到JDK16中转正。

记录不适合哪些场景

record的设计目标是提供一种将数据建模为数据的好方法。它也不是 JavaBeans 的直接替代品,因为 record的方法不符合 JavaBeans 的 get 标准。另外 JavaBeans 通常是可变的,而记录是不可变的。尽管它们的用途有点像,但记录并不会以某种方式取代 JavaBean。

1.8 密封类

背景:

在 Java 中如果想让一个类不能被继承和修改,这时我们应该使用 final 关键字对类进行修饰。不过这种要么可以继承,要么不能继承的机制不够灵活,有些时候我们可能想让某个类可以被某些类型继承,但是又不能随意继承,是做不到的。Java 15 尝试解决这个问题,引入了 sealed 类,被 sealed 修饰的类可以指定子类。这样这个类就只能被指定的类继承。

JDK15的预览特性:

通过密封的类和接口来限制超类的使用,密封的类和接口限制其它可能继承或实现它们的其它类或接口。

具体使用:

  • 使用修饰符sealed,可以将一个类声明为密封类。密封的类使用保留关键字permits列出可以直接扩展(即extends)它的类。
  • sealed 修饰的类的机制具有传递性,它的子类必须使用指定的关键字进行修饰,且只能是 finalsealednon-sealed 三者之一。

举例:

public abstract sealed class Shape permits Circle, Rectangle, Square {...}
public final class Circle extends Shape {...} //final表示Circle不能再被继承了
public sealed class Rectangle extends Shape permits TransparentRectangle, FilledRectangle {...}
public final class TransparentRectangle extends Rectangle {...}
public final class FilledRectangle extends Rectangle {...}
public non-sealed class Square extends Shape {...} //non-sealed表示可以允许任何类继承

JDK16二次预览特性

JDK17中转正特性

2. API的变化

2.1 Optional类

JDK8的新特性

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google在著名的Guava项目引入了Optional类,通过检查空值的方式避免空指针异常。受到Google的启发,Optional类已经成为Java 8类库的一部分。

Optional<T> 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。如果值存在,则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

  • 创建Optional类对象的方法:
  • static <T> Optional<T> empty():用来创建一个空的Optional实例
  • static <T> Optional<T> of(T value) :用来创建一个Optional实例,value必须非空
  • static <T> Optional<T> ofNullable(T value) :用来创建一个Optional实例,value可能是空,也可能非空
  • 判断Optional容器中是否包含对象:
  • boolean isPresent() : 判断Optional容器中的值是否存在
  • void ifPresent(Consumer<? super T> consumer) :判断Optional容器中的值是否存在,如果存在,就对它进行Consumer指定的操作,如果不存在就不做
  • 获取Optional容器的对象:
  • T get(): 如果调用对象包含值,返回该值。否则抛异常。T get()of(T value)配合使用
  • T orElse(T other) orElse(T other)ofNullable(T value)配合使用,如果Optional容器中非空,就返回所包装值,如果为空,就用orElse(T other)other指定的默认值(备胎)代替
  • T orElseGet(Supplier<? extends T> other) :如果Optional容器中非空,就返回所包装值,如果为空,就用Supplier接口的Lambda表达式提供的值代替
  • T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException

举例:

import java.util.Optional;
import org.junit.Test;
public class TestOptional {
  @Test
    public void test1(){
        String str = "hello";
        Optional<String> opt = Optional.of(str);
        System.out.println(opt);
    }
    @Test
    public void test2(){
        Optional<String> opt = Optional.empty();
        System.out.println(opt);
    }
    @Test
    public void test3(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
        System.out.println(opt);
    }
    @Test
    public void test4(){
        String str = "hello";
        Optional<String> opt = Optional.of(str);
        String string = opt.get();
        System.out.println(string);
    }
    @Test
    public void test5(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
//    System.out.println(opt.get());//java.util.NoSuchElementException: No value present
    }
    @Test
    public void test6(){
        String str = "hello";
        Optional<String> opt = Optional.ofNullable(str);
        String string = opt.orElse("csdn");
        System.out.println(string);
    }
    @Test
    public void test7(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
        String string = opt.orElseGet(String::new);
        System.out.println(string);
    }
    @Test
    public void test8(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
        String string = opt.orElseThrow(()->new RuntimeException("值不存在"));
        System.out.println(string);
    }
    @Test
    public void test9(){
        String str = "Hello1";
        Optional<String> opt = Optional.ofNullable(str);
        //判断是否是纯字母单词,如果是,转为大写,否则保持不变
        String result = opt.filter(s->s.matches("[a-zA-Z]+"))
                .map(s -> s.toUpperCase()).orElse(str);
        System.out.println(result);
    }
}

这是JDK9-11的新特性

新增方法 描述 新增的版本
boolean isEmpty() 判断value是否为空 JDK 11
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) value非空,执行参数1功能;如果value为空,执行参数2功能 JDK 9
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) value非空,返回对应的Optional;value为空,返回形参封装的Optional JDK 9
Stream<T> stream() value非空,返回仅包含此value的Stream;否则,返回一个空的Stream JDK 9
T orElseThrow() value非空,返回value;否则抛异常NoSuchElementException JDK 10

2.2 String存储结构和API变更

这是JDK9的新特性。

产生背景:

Motivation

The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component of heap usage and, moreover, that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.

背景

String类的当前实现将字符存储在字符数组中,每个字符使用两个字节(16位)。从许多不同的应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且,大多数String对象只包含Latin-1字符。这些字符只需要一个字节的存储空间,因此这些String对象的内部字符数组中有一半的空间是未使用的。

使用说明:

Description

We propose to change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field. The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

描述:

我们建议将String类的内部表示形式从UTF-16字符数组更改为字节数组加上编码标志字段。新的String类将根据字符串的内容存储编码为ISO-8859-1/Latin-1(每个字符一个字节)或UTF-16(每个字符两个字节)的字符。编码标志将指示使用哪种编码

结论:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
  ...
}

拓展:StringBufferStringBuilder

那StringBuffer 和 StringBuilder 是否仍无动于衷呢?

String-related classes such as AbstractStringBuilder, StringBuilder, and StringBuffer will be updated to use the same representation, as will the HotSpot VM’s intrinsic string operations.

翻译

与字符串相关的类,如AbstractStringBuilder、StringBuilder和StringBuffer,将被更新为使用相同的表示,HotSpot VM的固有字符串操作也是如此。

JDK11新特性:新增了一系列字符串处理方法

描述 举例
判断字符串是否为空白 " ".isBlank(); // true
去除首尾空白 " Javastack ".strip(); // “Javastack”
去除尾部空格 " Javastack ".stripTrailing(); // " Javastack"
去除首部空格 " Javastack ".stripLeading(); // "Javastack "
复制字符串 "Java".repeat(3);// “JavaJavaJava”
行数统计 "A\nB\nC".lines().count(); // 3

JDK12新特性:String 实现了 Constable 接口

String源码:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence,Constable, ConstantDesc {

java.lang.constant.Constable接口定义了抽象方法:

public interface Constable {
  Optional<? extends ConstantDesc> describeConstable();
}

Java 12 String 的实现源码:

/**
 * Returns an {@link Optional} containing the nominal descriptor for this
 * instance, which is the instance itself.
 *
 * @return an {@link Optional} describing the {@linkplain String} instance
 * @since 12
 */
@Override
public Optional<String> describeConstable() {
  return Optional.of(this);
}

很简单,其实就是调用 Optional.of 方法返回一个 Optional 类型。

举例:

private static void testDescribeConstable() {
  String name = "Java高级工程师";
  Optional<String> optional = name.describeConstable();
  System.out.println(optional.get());
}

结果输出:

Java高级工程师

JDK12新特性:String新增方法

String的transform(Function)

var result = "foo".transform(input -> input + " bar");
System.out.println(result); //foo bar

或者

var result = "foo".transform(input -> input + " bar").transform(String::toUpperCase)
System.out.println(result); //FOO BAR

对应的源码:

/**
* This method allows the application of a function to {@code this}
* string. The function should expect a single String argument
* and produce an {@code R} result.
* @since 12
*/
public <R> R transform(Function<? super String, ? extends R> f) {
 return f.apply(this);
}

在某种情况下,该方法应该被称为map()

举例:

private static void testTransform() {
  System.out.println("======test java 12 transform======");
  List<String> list1 = List.of("Java", " Python", " C++ ");
  List<String> list2 = new ArrayList<>();
  list1.forEach(element -> list2.add(element.transform(String::strip)
                  .transform(String::toUpperCase)
                  .transform((e) -> "Hi," + e))
         );
  list2.forEach(System.out::println);
}

结果输出:

======test java 12 transform======
Hi,JAVA
Hi,PYTHON
Hi,C++

如果使用Java 8的Stream特性,可以如下实现:

private static void testTransform1() {
        System.out.println("======test before java 12 ======");
        List<String> list1 = List.of("Java  ", " Python", " C++ ");
        Stream<String> stringStream = list1.stream().map(element -> element.strip()).map(String::toUpperCase).map(element -> "Hello," + element);
        List<String> list2 = stringStream.collect(Collectors.toList());
        list2.forEach(System.out::println);
    }

2.3 JDK17:标记删除Applet API

Applet API 提供了一种将 Java AWT/Swing 控件嵌入到浏览器网页中的方法。不过,目前 Applet 已经被淘汰。大部分人可能压根就没有用过 Applet。

Applet API 实际上是无用的,因为所有 Web 浏览器供应商都已删除或透露计划放弃对 Java 浏览器插件的支持。Java 9 的时候,Applet API 已经被标记为过时,Java 17 的时候终于标记为删除了。

具体如下:

java.applet.Applet
java.applet.AppletStub
java.applet.AppletContext
java.applet.AudioClip
javax.swing.JApplet
java.beans.AppletInitializer

3. 其它结构变化

3.1 JDK9:UnderScore(下划线)使用的限制

在java 8 中,标识符可以独立使用“_”来命名:

String _ = "hello";
System.out.println(_);

但是,在java 9 中规定“_”不再可以单独命名标识符了,如果使用,会报错:

3.2 JDK11:更简化的编译运行程序

看下面的代码。

// 编译
javac JavaStack.java
// 运行
java JavaStack

我们的认知里,要运行一个 Java 源代码必须先编译,再运行。而在 Java 11 版本中,通过一个 java 命令就直接搞定了,如下所示:

java JavaStack.java

注意点:

  • 执行源文件中的第一个类,第一个类必须包含主方法。

3.3 GC方面新特性

GC是Java主要优势之一。 然而,当GC停顿太长,就会开始影响应用的响应时间。随着现代系统中内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存, 并且无需长时间的GC暂停时间。

3.3.1 G1 GC

JDK9以后默认的垃圾回收器是 G1GC。

JDK10 : 为G1提供并行的 Full GC

G1最大的亮点就是可以尽量的避免full gc。但毕竟是“尽量”,在有些情况下,G1就要进行full gc了,比如如果它无法足够快的回收内存的时候,它就会强制停止所有的应用线程然后清理。

在Java10之前,一个单线程版的标记-清除-压缩算法被用于full gc。为了尽量减少full gc带来的影响,在Java10中,就把之前的那个单线程版的标记-清除-压缩的full gc算法改成了 支持多个线程 同时full gc。这样也算是减少了full gc所带来的停顿,从而提高性能。

可以通过-XX:ParallelGCThreads参数来指定用于并行GC的线程数。

JDK12:可中断的 G1 Mixed GC

JDK12:增强G1,自动返回未用堆内存给操作系统

3.3.2 Shenandoah GC

JDK12:Shenandoah GC:低停顿时间的GC

Shenandoah 垃圾回收器是 Red Hat 在 2014 年宣布进行的一项垃圾收集器研究项目 Pauseless GC 的实现,旨在针对 JVM 上的内存收回实现低停顿的需求

据 Red Hat 研发 Shenandoah 团队对外宣称,Shenandoah 垃圾回收器的暂停时间与堆大小无关,这意味着无论将堆设置为 200 MB 还是 200 GB,都将拥有一致的系统暂停时间,不过实际使用性能将取决于实际工作堆的大小和工作负载。

Shenandoah GC 主要目标是 99.9% 的暂停小于 10ms,暂停与堆大小无关 等。

这是一个实验性功能,不包含在默认(Oracle)的OpenJDK版本中。

Shenandoah开发团队在实际应用中的测试数据:

JDK15:Shenandoah垃圾回收算法转正

Shenandoah垃圾回收算法终于从实验特性转变为产品特性,这是一个从 JDK 12 引入的回收算法,该算法通过与正在运行的 Java 线程同时进行疏散工作来减少 GC 暂停时间。Shenandoah 的暂停时间与堆大小无关,无论堆栈是 200 MB 还是 200 GB,都具有相同的一致暂停时间。

Shenandoah在JDK12被作为experimental引入,在JDK15变为Production;之前需要通过-XX:+UnlockExperimentalVMOptions-XX:+UseShenandoahGC来启用,现在只需要-XX:+UseShenandoahGC即可启用

3.3.3 革命性的 ZGC

JDK11:引入革命性的 ZGC

ZGC,这应该是JDK11最为瞩目的特性,没有之一。

ZGC是一个并发、基于region、压缩型的垃圾收集器。

ZGC的设计目标是:支持TB级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于15%。 将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存),或压缩堆。

JDK13:ZGC:将未使用的堆内存归还给操作系统

JDK14:ZGC on macOS和windows

  • JDK14之前,ZGC仅Linux才支持。现在mac或Windows上也能使用ZGC了,示例如下:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
  • ZGC与Shenandoah目标高度相似,在尽可能对吞吐量影响不大的前提下,实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在十毫秒以内的低延迟。

JDK15:ZGC 功能转正

ZGC是Java 11引入的新的垃圾收集器,经过了多个实验阶段,自此终于成为正式特性。

但是这并不是替换默认的GC,默认的GC仍然还是G1;之前需要通过-XX:+UnlockExperimentalVMOptions -XX:+UseZGC来启用ZGC,现在只需要-XX:+UseZGC就可以。相信不久的将来它必将成为默认的垃圾回收器。

ZGC的性能已经相当亮眼,用“令人震惊、革命性”来形容,不为过。未来将成为服务端、大内存、低延迟应用的首选垃圾收集器。

怎么形容Shenandoah和ZGC的关系呢?异同点大概如下:

  • 相同点:性能几乎可认为是相同的
  • 不同点:ZGC是Oracle JDK的,根正苗红。而Shenandoah只存在于OpenJDK中,因此使用时需注意你的JDK版本

JDK16:ZGC 并发线程处理

在线程的堆栈处理过程中,总有一个制约因素就是safepoints。在safepoints这个点,Java的线程是要暂停执行的,从而限制了GC的效率。

回顾:

我们都知道,在之前,需要 GC 的时候,为了进行垃圾回收,需要所有的线程都暂停下来,这个暂停的时间我们称为 Stop The World

而为了实现 STW 这个操作, JVM 需要为每个线程选择一个点停止运行,这个点就叫做安全点(Safepoints)

而 ZGC的并发线程堆栈处理可以保证Java线程可以在GC safepoints的同时可以并发执行。它有助于提高所开发的Java软件应用程序的性能和效率。

4. 小结与展望

随着云计算和 AI 等技术浪潮,当前的计算模式和场景正在发生翻天覆地的变化,不仅对 Java 的发展速度提出了更高要求,也深刻影响着 Java 技术的发展方向。传统的大型企业或互联网应用,正在被云端、容器化应用、模块化的微服务甚至是函数(FaaS, Function-as-a-Service)所替代。

Java 需要在新的计算场景下,改进开发效率。 比如,Java 代码虽然进行了一些类型推断等改进,更易用的集合 API 等,但仍然给开发者留下了过于刻板、形式主义的印象,这是一个长期的改进方向。

Java虽然标榜面向对象编程,却毫不顾忌的加入面向接口编程思想,又扯出匿名对象的概念,每增加一个新的东西,对Java的根本(面向对象思想)的一次冲击。

相关文章
|
1月前
|
Java Go Scala
jdk10的var局部变量类型推理
本文介绍了JDK 10中引入的局部变量类型推断功能,即`var`关键字,它允许开发者在声明具有初始值的局部变量时省略显式类型,以简化代码并提高可读性。
13 1
jdk10的var局部变量类型推理
|
2月前
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
44 3
|
1月前
|
存储 安全 Java
JDK1.8 新的特性
JDK1.8 新的特性
19 0
|
2月前
|
编解码 安全 Java
jdk8新特性-接口和日期处理
jdk8新特性-接口和日期处理
|
2月前
|
Java
安装JDK18没有JRE环境的解决办法
安装JDK18没有JRE环境的解决办法
293 3
|
3月前
|
Java 关系型数据库 MySQL
"解锁Java Web传奇之旅:从JDK1.8到Tomcat,再到MariaDB,一场跨越数据库的冒险安装盛宴,挑战你的技术极限!"
【8月更文挑战第19天】在Linux上搭建Java Web应用环境,需安装JDK 1.8、Tomcat及MariaDB。本指南详述了使用apt-get安装OpenJDK 1.8的方法,并验证其版本。接着下载与解压Tomcat至`/usr/local/`目录,并启动服务。最后,通过apt-get安装MariaDB,设置基本安全配置。完成这些步骤后,即可验证各组件的状态,为部署Java Web应用打下基础。
57 1
|
3月前
|
Oracle Java 关系型数据库
Mac安装JDK1.8
Mac安装JDK1.8
685 4
|
4月前
|
Java Linux
Linux复制安装 jdk 环境
Linux复制安装 jdk 环境
107 3
|
1天前
|
Ubuntu Java
Ubuntu之jdk安装
以下是Ubuntu之jdk安装的详细内容
|
1月前
|
Oracle Java 关系型数据库
jdk17安装全方位手把手安装教程 / 已有jdk8了,安装JDK17后如何配置环境变量 / 多个不同版本的JDK,如何配置环境变量?
本文提供了详细的JDK 17安装教程,包括下载、安装、配置环境变量的步骤,并解释了在已有其他版本JDK的情况下如何管理多个JDK环境。
586 0