Java 9&10&11 新特性

视频链接:Java零基础教程

JDK 9 的发布

经历4次跳票,历经曲折的Java 9终于在2017年9月21日发布
从Java 9这个版本开始,Java的计划发布周期是6个月,下一个Java的主版本将于2018年3月发布,命名为 Java 18.3,紧接着再过六个月将发布 Java 18.9
这意味着Java的更新从传统的以特性驱动的发布周期,转变为以时间驱动的(6个月为周期)发布模式,并逐步的将Oracle JDK原商业特性进行开源
针对企业客户的需求,Oracle将以三年为周期发布长期支持版本(long term support)
Java 9 提供了超过150项新功能特性,包括备受期待的模块化系统、可交互的REPL工具:jshell,JDK编译工具,Java公共API和私有代码,以及安全增强、拓展提升、性能管理改善等。可以说Java 9是一个庞大的系统工程,完全做了一个整体改变

下载安装

Java SE Downloads

Java 9 新特性
  • 模块化系统
  • jShell命令
  • 多版本兼容jar包
  • 接口的私有方法
  • 钻石操作符的使用升级
  • 语法改进:try语句
  • String存储结构变更
  • 便利的集合特性:of()
  • 增强的Stream API
  • 全新的HTTP客户端API
  • Deprecated的相关API
  • javadoc的HTML 5支持
  • Javascript引擎升级:Nashorn
  • java的动态编译器

官方提供的新特性列表:
https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-C23AFD78-C777-460B-8ACE-58BE5EA681F6

或参考 Open JDK
http://openjdk.java.net/projects/jdk9/

在线Oracle JDK 9 Documentation
https://docs.oracle.com/javase/9/

一、目录结构变化
二、模块化系统:Jigsaw -> Modularity

本质上讲也就是说,用模块来管理各个package,通过声明某个package暴露,模块(module)的概念,其实就是package外再裹一层,不声明默认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏

实现目标

  • 模块化的主要目的在于减少内存的开销
  • 只须必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
  • 改进Java SE平台,使其可以适应不同大小的计算设备
  • 改进其安全性,可维护性,提高性能
三、jShell命令

产生背景

Python和Scala之类的语言早就有交互式编程环境 REPL(read-evaluate-print-loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本想要执行代码,必须创建文件、声明类、提供测试方法方可实现

设计理念

即写即得、快速运行

实现目标

  • Java 9中终于拥有了REPL工具:jShell。让Java可以像脚本语言一样运行,从控制台启动jShell,利用jShell在没有创建类的情况下直接声明变量,计算表达式,执行语句。即开发时可以在命令行里直接运行Java的代码,而无需创建Java文件,无需跟人解释“public static void main(String[] args)"这句废话
  • jShell也可以从文件中加载语句或者将语句保存到文件中
  • jShell也可以是tab键进行自动补全和自动添加分号

调出jShell:jshell
获取帮助:/help
只需按下Tab键,就能自动补全代码
列出当前session里所有有效的代码:/list
执行文件:/open
没有受检异常(编译时异常)
退出jShell: /exit

四、接口的私有方法

Java 8中规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认方法。一定程度上,拓展了接口的功能,此时的接口更像是一个抽象类

在Java 9中,接口更加的灵活和强大,连方法的访问修饰符都可以声明为private的了,此时方法将不会成为你对外暴露的API的一部分

public interface MyInterface {
    // 如下的三个方法的权限修饰符都是public
    void methodAbstract();
    
    // 接口中的静态方法只能通过接口调用,不能通过实现类调用
    static void methodStatic() {
        System.out.println("我是接口中的静态方法");
    }
    
    default void methodDefault() {
        System.out.println("我是接口中的默认方法");
    }
    
    // jdk 9中允许接口中定义私有的方法,不能在接口外部调用
    private void methodPrivate() {
        System.out.println("我是接口中的私有方法");
    }
}
五、钻石操作符使用升级

我们将能够与匿名实现类共同使用钻石操作符(diamond operator)在Java 8中如下的操作都会报错的:

// jdk8 编译报错信息:Cannot use "<>" with anonymous inner classes.
// 钻石操作符与匿名内部类在java 8中不能共存。在java 9可以
Comparator<Object> com = new Comparator<>() {

    @Override
    public int compare(Object o1, Object o2) {
        return 0;
    }
};
// jdk7中的新特性:类型推断
ArrayList<String> list = new ArrayList<>();
六、语法改进:try语句

Java 8中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。如下例所示:

// java 8 中资源关闭操作:Java 8中,可以实现资源的自动关闭
// 要求自动关闭的资源的初始化必须放在try的一对小括号中
try(InputStreamReader reader = new InputStreamReader(System.in)) {
	// 读取数据细节省略
} catch (IOException e) {
    e.printStackTrace();
}

Java 9 中,用资源语句编写try将更容易,我们可以在try子句中使用已经初始化过的资源,此时的资源时final的

// java9中资源关闭操作:需要自动关闭的资源的实例化可以放在try的一对小括号外
// 此时的资源属性是常量,声明为final的,不可修改
InputStreamReader reader = new InputStreamReader(System.in);
OutputStreamWriter writer = new OutputStreamWriter(System.out);
try(reader; writer) {
    // reader是final的,不可再被赋值
    // reader = null;
    // 具体读写操作省略
} catch (IOException e) {
    e.printStackTrace();
}
七、String存储结构变更

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

八、集合工厂方法:快速创建只读集合

要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合

// java 8
List<String> namesList = new ArrayList<>();
namesList.add("Joe");
namesList.add("Bob");
namesList.add("Bill");
// 返回的namesList是一个只读的集合
namesList = Collections.unmodifiableList(namesList);
namesList.add("Tom"); // 运行报错
System.out.println(namesList);

List<Integer> list = Arrays.asList(1,2,3,4,5);
// java 9
List<Integer> list2 = List.of(1,2,3,4,5);
九、InputStream加强

InputStream终于有了一个非常有用的方法:transferTo,可以用来将数据直接传输到OutputStream,这是在处理原始数据流时非常常用的一种方法,如下实例:

ClassLoader c1 = this.getClass().getClassLoader();
try(InputStream is = c1.getResourceAsStream("hello.txt")) {
    OutputStream os = new FileOutputStream("src\\hello1.txt");
    is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
} catch (IOException e) {
    e.printStackTrace();
}
十、增强的Stream API

Java的Stream API是java标准库最好的改进之一,让开发者能够快速运算,从而能够有效的利用数据并行计算。Java8提供的Stream能够利用多核架构实现声明式的数据处理

在Java 9中,Stream API变得更好,Stream接口中添加了4个新的方法:
takeWhile,dropWhile,ofNullable,还有个iterate方法的重载方法,可以让你提供一个Predicate(判断条件)来指定什么时候结束迭代

除了对Stream本身的拓展,Optional和Stream之间的结合也得到了改进。现在可以通过Optional的新方法stream()将一个Optional对象转换为一个(可能为空的)Stream对象

List<Integer> list = Arrays.asList(12, 34, 12, 31, 62, 67, 73, 12);
// takeWhile 返回从开头开始的按照指定规则尽量多的元素
list.stream().takeWhile(x -> x < 60).forEach(System.out::println);
// dropWhile 与takeWhile相反,返回剩余元素
list.stream().dropWhile(x -> x < 60).forEach(System.out::println);

// of()参数中的多个元素,可以包含null值
Stream<Integer> stream = Stream.of(1, 2, 3, null);
stream.forEach(System.out::println);
// of()参数不能存储单个null值。否则,报异常
// Stream<Integer> stream2 = Stream.of(null); // 报异常
// stream2.forEach(System.out::println);
Integer i = 10;
i = null;
// ofNullable():形参变量是可以为null值的单个元素
Stream<Integer> stream3 = Stream.ofNullable(i);
stream3.forEach(System.out::println);

Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out::println);
// java 9中新增的重载的方法
Stream.iterate(0, x -> x < 100, x -> x + 1).forEach(System.out::println);
十一、Optional获取Stream的方法
List<String> list = new ArrayList<>();
list.add("Tom");
list.add("Jerry");
list.add("Tim");

Optional<List<String>> optional = Optional.ofNullable(list);
Stream<List<String>> stream = optional.stream();
stream.flatMap(x -> x.stream()).forEach(System.out::println);
十二、Javascript引擎升级:Nashorn

Nashorn项目在JDK 9中得到改进,它为Java提供轻量级的Javascript运行时。Nashorn项目跟随Netscape的Rhino项目,目的是为了在Java中实现一个高性能但轻量级的Javascript运行时。Nashorn项目使得Java应用能够嵌入JavaScript。它在JDK 8中为Java提供了Javascript引擎

JDK 9包含一个用来解析Nashorn的ECMAScript语法树的API。这个API使得IDE和服务端框架不需要依赖Nashorn项目的内部实现类,就能够分析ECMAScript代码Nashorn

Java 10 新特性

2018年3月21日,Oracle官方宣布Java 10正式发布
需要注意的是Java 9和Java 10都不是LTS(Long-Term-Support)版本。和过去的Java大版本升级不同,这两个只有半年左右的开发和维护期。而未来的Java 11,也就是18.9 LTS,才是 Java 8之后第一个LTS版本

JDK 10一共定义了109个新特性,其中包含12个JEP(对于程序员来讲,真正的新特性其实就一个),还有一些新API和JVM规范以及JAVA语言规范上的改动

JDK 10的12个JEP(JDK Enhancement Proposal 特性加强提议)参阅官方文档:http://openjdk.java.net/projects/jdk/10/

286: Local-Variable Type Inference 局部变量类型推断
296: Consolidate the JDK Forest into a Single Repository JDK库的合并
304: Garbage-Collector Interface 统一的垃圾回收接口
307: Parallel Full GC for G1 为G1提供并行的Full GC
310: Application Class-Data Sharing 应用程序类数据(AppCDS)共享
312: Thread-Local Handshakes 握手交互
313: Remove the Native-Header Generation Tool (javah) 移除JDK中附带的javah工具
314: Additional Unicode Language-Tag Extensions 使用附加的Unicode语言标记拓展
316: Heap Allocation on Alternative Memory Devices 能将堆内存占用分配给用户指定的备用内存设备
317: Experimental Java-Baed JIT Compiler 使用基于Java的JIT编译器
319: Root Certificates 根证书
322: Time-Based Release Versioning 基于时间的发布版本

一、局部变量类型推断

产生背景

开发者经常抱怨Java中引用代码的程度。局部变量的显示类型声明,常常被认为是不必须的,给一个好听的名字经常很清楚的表达出下面应该怎样继续

好处

减少了啰嗦和形式的代码,避免了信息冗余,而且对齐了变量名,更容易阅读!

举例如下

场景一:类实例化时

作为Java开发者,在声明一个变量时,我们总是习惯了敲打两次变量类型,第一次用于声明变量类型,第二次用于构造器

LinkedHashSet<Integer> set = LinkedHashSet<>();

场景二:返回值类型含复杂泛型结构

变量的声明类型书写复杂且较长,尤其是加上泛型的使用

Interator<Map.Entry<Integer, Student>> iterator = set.iterator();

场景三

我们也经常声明一种变量,它只会被使用一次,而且是用在下一行代码中,比如:

URL url = new URL("www.antherd.com");
URLConnection connection = url.openConnection();
Reader reader = new BufferedReader(new InputStreamReader(connnection.getInputStream()));

尽管IDE可以帮我们自动完成这些代码,但当变量总是跳来跳去的时候,可读性还是会受到影响,因变量类型的名称由各种不同长度的字符组成。而且,有时候开发人员会尽力避免声明中间变量,因为太多的类型声明只会分散注意力,不会带来额外的好处

// 1. 声明变量时,根据所赋的值,推断变量的类型
var num = 10;

var list = new ArrayList<Integer>();
list.add(123);

// 2. 遍历操作
for(var i : list) {
    System.out.println(i);
    System.out.println(i.getClass());
}

// 3. 普通的遍历操作
for(var i = 0; i < 100; i ++) {
    System.out.println(i);
}

在局部变量中使用时,如下情况不适用:

  • 初始值为null
  • 方法引用
  • Lambda表达式
  • 为数组静态初始化
  • 没有初始化的局部变量声明
  • 方法的返回类型
  • 方法的参数类型
  • 构造器的参数类型
  • 属性
  • catch块
// 1. 局部变量不赋值,就不能类型推断
 // var num;
 // 2. Lambda表达式,左边的函数式接口不能声明为var
 // Supplier<Double> sup = () -> Math.random();
 // var sup = () -> Math.random();
 // 3. 方法引用中
 // Consumer<String> con = System.out::println;
 // var con = System.out::println;
 // 4. 数组的静态初始化中,注意如下的情况也不可以
 // int[] arr = new int[] {1,2.3.4};
 // var arr = {1,2,3,4}

 // 5. 没有初始化的局部变量声明
 // var s = null;
 // 6. 方法的返回类型
 // public var method1() {
 //    return 0;
 // }
 // 7. 方法的参数类型、构造器的参数类型、属性
 // public void method2(var num) {

 // }
 // 8. catch快
 // try {
     
 // } catch (var e) {
 //     e.printStackTrace();
 // }

正常情况:

try {
    var url = new URL("http://www.antherd.com");
    var connection = url.openConnection();
    var reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} catch (IOException e) {
    e.printStackTrace();
}

工作原理

在处理var时,编译器先是查看表达式右边部分,并根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字节码当中

注意

var不是一个关键字

你不需要担心变量名或方法名会与var发生冲突,因为var实际上并不是一个关键字,而是一个类型名,只有在编译器需要知道类型的地方才需要用到它。除此之外,它就是一个普通合法的标识符。也就是说,除了不能用它作为类名,其他的都可以,但极少人会用它作为类名

这不是Javascript

首先我要说明的是,var并不会改变java是一门静态类型语言的事实。编译器负责推断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。下面是使用Intellij(实际上是Fernflower的反编译器)反编译出的代码:

二、集合新增创建不可变集合的方法

自Java 9开始,Jdk里面为集合(List/Set/Map)都添加了 of(jdk 9新增)copyOf(jdk 10新增)方法,它们两个都用来创建不可变的集合,来看下他们的使用和区别

// 示例1:
var list1 = List.of("Java", "Python", "C");
var copy1 = List.copyOf(list1);
System.out.println(list1 == copy1); // true

// 示例2:
var list2 = new ArrayList<String>();
var copy2 = List.copyOf(list2);
System.out.println(list2 == copy2); // false

// 示例1和示例2基本一致,为什么一个为true,一个为false?
// 结论:copyOf(Xxx coll):如果参数coll本身就是一个只读集合,则copyOf()返回值即为当前coll
// 如果参数coll不是一个只读集合,则copyOf()返回一个新的集合,这个集合是只读的

从源码分析,可以看出copyOf方法会先判断来源集合是不是AbstractImmutableList类型的,如果是,就直接返回,如果不是,则调用of创建一个新的集合

示例2因为用的new创建的集合,不属于不可变AbstractImmutableList类的子类,所以copyOf方法又创建了一个新的实例,所以为false

注意:使用of和copyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报java.lang.UnsupportedOpeartionException异常

上面演示了List的of和copyOf方法,Set和Map接口都有

Java 11 新特性

北京时间2018年9月26日,Oracle官方宣布Java 11正式发布。这是Java大版本周期变化后的第一个长期支持版本,非常值得关注。从官网即可下载,最新发布的Java 11将带来ZGC Http Client等重要特性,一共包含17个JEP(JDK Enhancement Proposals,JDK增强提案)。其实,总共更新不止17个,只是我们更关注如下17个JEP更新

181: Nest-Based Access Control
309: Dynamic Class-File Constants
315: Improve Aarch64 Intrinsics
318: Epsilon: A No-Op Garbage Collector
320: Remove the Java EE and CORBA Modules
321: HTTP Client (Standard)
323: Local-Variable Syntax for Lambda Parameters
324: Key Agreement with Curve25519 and Curve448
327: Unicode 10
328: Flight Recorder
329: ChaCha20 and Poly1305 Cryptographic Algorithms
330: Launch Single-File Source-Code Programs
331: Low-Overhead Heap Profiling
332: Transport Layer Security (TLS) 1.3
333: ZGC: A Scalable Low-Latency Garbage Collector
   (Experimental)
335: Deprecate the Nashorn JavaScript Engine
336: Deprecate the Pack200 Tools and API

JDK 11是一个长期支持版本(LTS,Long-Term-Support)

  • 对于企业来说,选择11将意味着长期的、可靠的、可预期的技术路线图。其中免费的OpenJDK 11确定将得到OpenJDK社区的长期支持,LTS版本将是可以放心选择的版本
  • 从JVM GC的角度,JDK 11引入了两种新的GC,其中包括也许是划时代意义的ZGC,虽然其目前还是实验特性,但是从能力上来看,这是JDK的一个巨大突破,为特定生产环境的苛刻需求提供了一个可能的选择。例如,对部分企业核心存储等产品,如果能够保证不超过10ms的GC暂停,可靠性会上一个大的台阶,这是过去我们进行GC调优几乎做不到的,是能与不能的问题

新的长期支持版本每三年发布一次,根据后续的发布计划,下一个长期支持版Java 17将于2021年发布

一、新增了一系列字符串处理方法
描述举例
判断字符串是否为空白“ ”.isBlank(); // true
去除首尾空白“ Javastack ”.strip(); // “Javastack”
去除尾部空格“ Javastack ”.stripTrailing(); // " Javastack"
去除首部空格“ Javastack ”.stripLeading(); // "Javastack "
复制字符串“Java”.repeat(3); // “JavaJavaJava”
行数统计”A\nB\nC“.lines().count(); // 3
二、Optional 加强

Optional也增加了几个非常酷的方法,现在可以很方便的将一个Optional转换成一个Stream,或者当一个空Optional时给它一个替代的

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

在var上添加注解的语法格式,在jdk 10中是不能实现的。在JDK 11 中加入了这样的语法

// 错误的形式:必须要有类型,可以加上var
// Consumer<String> con1 = (@Deprecated t) -> System.out.println(t.toUpperCase());
// 正确的形式:
// 使用var的好处是在使用lambda表达式时给参数加上注解
Consumer<String> con2 = (@Deprecated var t) -> System.out.println(t.toUpperCase());
四、全新的HTP客户端API

HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年,HTTP2才成为标准

HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。HTTP/2允许服务器”push“数据:它可以发送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网页至关重要的数据

这是Java 9 开始引入的一个处理HTTP请求的HTTP Client API,该API支持同步和异步,而在Java 11中已经为正式可用状态,你可以在java.net包中找到这个API

它将替代仅适用于blocking模式的HttpURLConnection(HttpURLConnection是在HTTP 1.0的时代创建的,并使用了协议无关的方法),并提供对WebSocket和HTTP/2的支持

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
BodyHandler<String> responseBodyHandler = BodyHandlers.ofString();
HttpResponse<String> response = client.send(request, responseBodyHandler);
String body = response.body();
System.out.println(body);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
BodyHandler<String> responseBodyHandler = BodyHandlers.ofString();
CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, responseBodyHandler);
sendAsync.thenApply(t -> t.body()).thenAccept(System.out::println);
HttpResponse<String> response = sendAsync.get();
String body = response.body();
System.out.println(body);
五、更简化的编译运行程序

看下面的代码

// 编译
javac Jacastack.java
// 运行
java Javastack

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

java Javastack.java

一个命令编译运行源代码的注意点

  • 执行源文件中的第一个类,第一个类必须包含主方法
  • 并且不可以使用其他源文件中的自定义类,本文件中的自定义类是可以使用的
六、废弃Nashorn引擎

废除Nashorn javascript引擎,在后续版本准备移除掉,有需要的可以考虑使用GraalVM

七、ZGC

GC是java主要优势之一。然而,当GC停顿太长,就会开始影响应用的响应时间。消除或者减少GC停顿时长,java将对更广泛的应用场景是一个更有吸引力的平台。此外,现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存,而且无需长时间的GC暂停时间

ZGC, A Scalable Low-Latency Garbage Collector(Experimental). ZGC,这应该是JDK 11最为瞩目的特性,没有之一。但是后面带了Experimental,说明这还不建议用到生产环境

ZGC是一个并发,基于region,压缩型的垃圾收集器,只有root扫描阶段会STW(stop the world),因此GC停顿时间不会随着堆的增长和存活对象的增长而变长

优势:

  • GC暂停时间不会超过10ms
  • 既能处理几百兆的小堆,也能处理几个T的大堆(OMG)
  • 和G1相比,应用吞吐能力不会下降超过15%
  • 为未来的GC功能和利用colord指针及Load barriers优化奠定基础
  • 初始只支持64位系统

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

八、其他新特性
  • Unicode 10
  • Deprecate the Pack200 Tools and API
  • 新的Epsilon垃圾回收器
  • 完全支持Linux容器(包括Docker)
  • 支持G1上的并行完全垃圾收集
  • 最新的HTTPS安全协议TLS 1.3
  • Java Flight Recorder
jdk后续更新的展望
一个标准和轻量级的JSON API

一个标准和轻量级的JSON API被许多Java开发人员所青睐。但是由于资金问题无法在java当前版本中见到,但并不会削减掉。Java平台首席架构师Mark Reinhold在JDK 9邮件列中说:”这个JEP将是平台上的一个有用的补充,但是在计划中,它并不像Oracle资助的其他功能那么重要,可能会重新考虑JDK 10或更高版本中实现。

新的货币API

对许多应用而言货币价值都是一个关键的特性,但JDK对此却几乎没有任何支持。严格来讲,现有的java.util.Currency类只是代表了当前ISO 4217货币的一个数据结构,但并没有关联的值或者自定义货币。JDK对货币的运算及转换也没有内建的支持,更别说一个能够代表货币值的标准类型了

此前,Orale公布的JSR 354定义了一套新的Java货币API:JavaMoney,计划会在Java 9中正式引入。但是目前没有出现在JDK新特性中

不过,如果你用的是Maven的话,可以做如下的添加,即可使用相关API处理货币:

<dependency>
	<groupId>org.javamoney</groupId>
	<artifactId>moneta</artifactId>
	<version>0.9</version>
</dependency>
展望

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

Java虽然标榜面向对象编程,却毫不顾忌的加入面向接口编程思想,又扯出匿名对象之概念,每增加一个新的东西,对Java的根本所在的面向对象思想的一次冲击。反观Python,抓住面向对象的本质,又能在函数编程思想方面游刃有余。Java对标C/C++,以抛掉内存管理为卖点,却又陷入了JVM优化的噩梦。选择比努力更重要,选择Java的人更需要对它有更清晰的认识。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值