编程语言界的扛把子 Java,不仅搭载上了如火箭版的更新速度,现在还有意让上车的用户付费买票了,那么身为 Java 开发者,下一步究竟是该弃用 23 年的老牌工具 JDK 还是乖乖付费继续搭载这列车?

上个月,Java 开发工具包(JDK)11刚刚到来,JDK 12 就在紧密敲锣筹备中,随着消息接连不断地爆出,不少使用 Java 的开发者开始有种一年一万个更新版本的错觉,而当面对厚厚的一堆堆 Java 8/9/10/11 的入门书籍和教程时,就问你怕不怕?不仅如此,就在 Java 早已在移动 App、服务器应用、Web 开发、J2EE 企业级应用和嵌入式等领域根深蒂固时,Oracle 于近日最新发布的一纸 Java 用户使用协议轰动了整个业界,因为 Java 将收费了!

1.JDK 11 不容错过的那些新特性

JDK 11 作为 Oracle 以六个月为更新周期之后公开发布的第一个长期支持版本,其中还是有许多实用的功能特性。

局部变量推断

Java 10 引入了新的关键字 var,可以在定义局部变量时代替类型信息(局部指的是在方法体内部的变量定义)。

在 Java 10 之前,局部变量必须这样定义:

String text = "Hello Java 9";

而现在可以用 var 代替 String。编译器会根据变量的赋值推断出正确的类型。因此,text 的类型是 String:

var text = "Hello Java 10";

使用 var 定义的变量依然是静态类型。这种变量不能重新用不兼容的类型赋值。比如,下面的代码无法通过编译:

var text = "Hello Java 11";
text = 23; // Incompatible types
还可以通过同时使用 var 和 final 来禁止变量的重新赋值:

final var text = "Banana";
text = "Joe"; // Cannot assign a value to final variable 'text'
而且,当编译器无法推断出正确类型时也不允许使用 var:

// Cannot infer type:
var a;
var nothing = null;
var lambda = () -> System.out.println("Pity!");
var method = this::someMethod;
局部变量类型的推断在泛型中非常有用。下面的例子中,current 有个非常复杂的类型 Map<String, List<Integer>>,而这个类型可以简化成一个 var 关键字,节省了很多敲代码的时间:

var myList = new ArrayList<Map<String, List<Integer>>>();
for (var current : myList) {
// current is infered to type: Map<String, List<Integer>>
System.out.println(current);
}
由于 Java 11 的 var 关键字也可以在 lambda 的参数上使用,因此可以给参数加注解:

Predicate<String> predicate = (@Nullable var a) -> true;

小提示:Intellij IDEA 中可以按住 CMD/CTRL 键并将鼠标悬停在变量上来查看推断出的类型(键盘快捷键为Ctrl+J)。

HTTP 客户端

Java 9 引入了新的 HttpClient API 来处理 HTTP 请求。在 Java 11 中,这个 API 已稳定,可以通过 java.net 包使用。我们来看看这个 API 能干什么。

新的 HttpClient 支持同步和异步方式。同步请求会阻塞当前线程直到响应返回。BodyHandlers 定义了期待的响应体的类型(如字符串、字节数组或文件):

var request = HttpRequest.newBuilder()
.uri(URI.create("https://winterbe.com"))
.GET()
.build();
var client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
同样的请求也可以异步进行。调用 sendAsync 不会阻塞当前线程,它会返回一个 CompletableFuture 用来构建异步操作管线。

var request = HttpRequest.newBuilder()
.uri(URI.create("https://winterbe.com"))
.build();
var client = HttpClient.newHttpClient();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
小提示:可以省略 .GET() 调用,因为它是默认的。

下面这个例子用 POST 方式将数据发送到给定的 URL。与 BodyHandlers 类似,这里使用 BodyPublishers 来定义请求体中要发送的数据类型,如字符串、字节数组、文件或输入流:

var request = HttpRequest.newBuilder()
.uri(URI.create("https://postman-echo.com/post"))
.header("Content-Type", "text/plain")
.POST(HttpRequest.BodyPublishers.ofString("Hi there!"))
.build();
var client = HttpClient.newHttpClient();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200
下面的例子演示了通过 BASIC-AUTH 方式进行认证的方法:

var request = HttpRequest.newBuilder()
.uri(URI.create("https://postman-echo.com/basic-auth"))
.build();
var client = HttpClient.newBuilder()
.authenticator(new Authenticator() {br/>@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("postman", "password".toCharArray());
}
})
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200
集合

像 List、Set 和 Map 等集合类都加入了新的方法。List.of 会根据给定的参数创建一个新的不可变的 list。List.copyOf 能创建 list 的不可变副本。

var list = List.of("A", "B", "C");
var copy = List.copyOf(list);
System.out.println(list == copy); // true
因为 list 已经是不可变的了,因此不需要实际创建 list 实例的副本,因此 list 和 copy 会指向同一个副本。但如果赋值一个可变的列表,copy 就会生成一个新的实例,以保证修改原始列表时不会产生副作用:

var list = new ArrayList<String>();
var copy = List.copyOf(list);
System.out.println(list == copy); // false
在创建不可变的 map 时,不需要自行创建 map 的内容,只需要传递键和值即可:

var map = Map.of("A", 1, "B", 2);
System.out.println(map); // {B=2, A=1}
Java 11 中的不可变集合依然使用与原来的集合 API 同样的接口。但如果试图通过添加或删除元素的方式改变不可变集合,则会发生 java.lang.UnsupportedOperationException 异常。好在 Intellij IDEA 会在你试图改变不可变集合时发出警告。

Java 8 引入了 流的概念,现在它有三个新的方法。Stream.ofNullable 能从单个元素构建一个流:

Stream.ofNullable(null)
.count() // 0
dropWhile 和 takeWhile 两个方法都能接受 predicate 对象,从而可以抛弃流中的一些元素:

Stream.of(1, 2, 3, 2, 1)
.dropWhile(n -> n < 3)
.collect(Collectors.toList()); // [3, 2, 1]
Stream.of(1, 2, 3, 2, 1)
.takeWhile(n -> n < 3)
.collect(Collectors.toList()); // [1, 2]
Optional

Optional 也增加了几个新方法,比如现在可以很容易将 optional 转换成流,或者给空的 optional 提供另一个 optional 作为出错时的备选方案:

Optional.of("foo").orElseThrow(); // foo
Optional.of("foo").stream().count(); // 1
Optional.ofNullable(null)
.or(() -> Optional.of("fallback"))
.get(); // fallback
字符串

最基础的类之一 String 也加了几个辅助方法用来去除空白、检查空白,以及以流的方式输出字符串:

" ".isBlank(); // true
" Foo Bar ".strip(); // "Foo Bar"
" Foo Bar ".stripTrailing(); // " Foo Bar"
" Foo Bar ".stripLeading(); // "Foo Bar "
"Java".repeat(3); // "JavaJavaJava"
"A\nB\nC".lines().count(); // 3
其他 JVM 特性

在我看来,上述这些是 Java 11 与 8 相比时最有意思的语言 API 特性,不过新的特性还有许多,比如下面这些:

用于响应式编程的流式 API
Java 模块系统
应用程序类数据共享
动态类-文件常量
Java REPL(JShell)
飞行记录器
Unicode 10
G1:完全并行的垃圾回收器
ZGC:可扩展的低延迟垃圾回收器
Epsilon:No-Op垃圾回收器
不推荐使用的Nashorn JavaScript引擎
……
2.学不动的 Java,还要收费了?

对于 Java 新版本,不少开发者望尘莫及,纷纷表示不要再更新了,我的项目还停留在 Java 8 呢。话虽如此,事实上 Oracle 曾在今年四月就宣布,自 2019 年 1 月起,Java SE 8 公开更新将不向没有商用许可证的业务、商用或生产用途提供。即未来开发者还想使用 JDK 8,Oracle 将不会提供免费的技术支持,需要另外收费。所以总体而言还是建议开发者应该转换到最新版的 Java 11。

但就在这时,据国外网友@Stephen Colebourne 发布的一篇名为《Oracle's Java 11 trap - Use OpenJDK instead!》博文,我们才注意到,在 Java 11 中,Oracle 悄然更新了用户使用协议(https://www.oracle.com/technetwork/java/javase/terms/license/javase-license.html):

简而言之:

新版 Oracle JDK 不可以用在数据处理、商业、产品、或者内部商业用途(需要购买 License),仅可免费用于开发、测试、原型、演示。

正是这一修改意味着免费使用 23 年的 Java 即将走上收费的路子。倘若开发者还是如往常那般下载 Oracle JDK,并将其投入商业项目中使用,后续可能会带来不小的商业纠纷。

3.Oracle JDK 收费了,企业和开发者怎么办?

提及 Java 的商业纠纷,我们不禁想起此前轰动一时且长达八年的 Oracle 与 Google 关于 Java 的侵权案:

1995 年,Sun 公司发布了 Java;这其中需要介绍到 2006 年,Sun 公司开源了其 Java 项目——OpenJDK,但是并未开源此前的 Java 项目 SunJDK(现在是 OracleJDK);2009 年,Oracle 以 74 亿美元收购 Sun 从而获得了 Java 的版权,而其中也包含了 Sun 研发的 Java 商业项目版权;2010 年 8 月,Oracle 认为 Google Android 系统抄袭了 37 个 Java API 代码段,而这些代码属于 Oracle 商业私有 JDK(OracleJDK)的一部分,于是将 Google 诉讼至法庭,要求赔偿 26 亿美元;经过 8 年的调解及上诉,这一案最终于今年 3 月,美国联邦巡回法院判 Google 向 Oracle 赔偿 88 亿美元而告一段落。之所以没说案件告终,是因为 Google 不服判决,还在向最高法院上诉中。
而就在 Google 边应对诉讼时,或许就在周密思量针对自己的 Android 系统甚至是整个公司研发的下一步:如何摆脱 Oracle?

于是,在 2015 年年底,我们就亲眼见证了 Google 宣布将 Java 应用程序接口(APIs)从 Oracle JavaAPI 替换成开源的 OpenJDK。甚至在两年后的 Google I/O 大会上,震撼宣布 Kotlin 成为 Android 开发的一级编程语言,让其与 Java 齐驾并驱,反观,也是与之相抗衡。

再针对这一次的 Oracle 修改了 JDK 11 的用户协议来看,从 Oracle 的角度其实不难理解他的这一行为,毕竟作为纯软件先驱的 Oracle 也是个商业公司,他需要提供一个软件的商业版本来提高增值服务。但是对于使用 Oracle JDK 的开发者或企业而言,情况就变得有所不同了,为了避免上述 Google 的同等遭遇,我们除了付费是否还有其他选择?

对此,不少开发者纷纷热议:

Java 程序员是时候向 C# 转移了;
换 .NET 也行;
这个仅针对 JDK 11,不升级不使用 Java 11 不就行了。
在访问了几位知名的 Java 开发者之后,他们给出的答案几乎都是,「使用 Kotlin」。甚至就连微博研发副总经理@TimYang 也表示,这一行为直接导致 Kotlin 才是最大赢家,IDEA 环境将 Java 代码粘贴到 Kotlin 文件,自动转换。

不过相较于 23 岁的 Java,不少开发者还是对年仅 7 岁的 Kotlin 的未来感到迷茫,所以在面对 JDK 8 即将停止免费更新支持、JDK 11 无法商用的情况下,请记得 Oracle 还有一个名为 OpenJDK 的开源项目。

注:Java 9、10 并不是长期支持(LTS)版本,所以上述文章中并未提及。

要说 Oracle JDK 和 Open JDK 之前的差距很明显,那么在 JDK 11 中,Oracle 很人性化地将两者的不同尽可能地缩小了,甚至可以忽略微乎其微的差距。

或者除了 Open JDK 外,我们此前也发文为大家推荐了一些实用的

JDK

,譬如 AdoptOpenJDK builds、Red Hat OpenJDK builds、Azul Zulu 等等。最后,对于 Oracle 修改 JDK 11 的使用协议,你有着什么样的看法?欢迎下方留言,分享你的想法。

最关键的一步
对Java技术,架构技术感兴趣的同学, Java架构交流群 668041364, 一起学习,相互讨论。

群内已经有小伙伴将知识体系整理好(源码,笔记,PPT,学习视频),欢迎加群领取。

转载于:https://blog.51cto.com/14233733/2404937

23 岁的 Java 成为编程界的扛把子,网友回复:这就是实力相关推荐

  1. AI 女性界的“扛把子”,凭一己之力迫使 NIPS 改名

    作者 | 琥珀 出品 | AI科技大本营 "计算机领域其实没有歧视,只是存在性别比例的差异罢了--"如果这种事件不放在台面上说,可能大家就这么想当然的认为了. 或许当你津津有味阅读 ...

  2. AI女性界的“扛把子”,凭一己之力迫使NIPS改名

    作者 | 琥珀 出品 | AI科技大本营 "计算机领域其实没有歧视,只是存在性别比例的差异罢了--"如果这种事件不放在台面上说,可能大家就这么想当然的认为了. 或许当你津津有味阅读 ...

  3. 明星玩VR,会让娱乐成为VR内容界的扛把子吗?

    当明星遇上虚拟现实,原来VR和娱乐还能这么玩. 最近微博上最火的除了霍建华和林心如的婚礼,可能就是陈冠希为女友出头在微博上大骂林志玲了,陈冠希近些年在娱乐圈越来越活跃了,几个月前被爆在上海某机场和插队 ...

  4. 游戏界的扛把子、3D 游戏之父约翰•卡马克的传奇人生

    作者 | 年素清  责编 | 张文 出品 | 程序人生 (ID:coder _life) 约翰•卡马克(John D. Carmack II)是电脑游戏界的传奇人物,你可能没听过这个名字,但你肯定玩过 ...

  5. 游戏界的“扛把子”,“3D 游戏之父”, 约翰•卡马克的传奇人生

    作者 | 年素清 责编 | 王晓曼 出品 | 程序人生 (ID:coder _life) 约翰•卡马克(John D. Carmack II)是电脑游戏界的传奇人物,你可能没听过这个名字,但你肯定玩过 ...

  6. APM,监控界的扛把子,牛逼!

    你知道的越多,不知道的就越多,业余的像一棵小草! 成功路上并不拥挤,因为坚持的人不多. 编辑:业余草 javadoop.com/post/apm 推荐:https://www.xttblog.com/ ...

  7. 链表界的“扛把子”—双向带头循环链表

    目录 一:链表的分类 二:链表的实现 2-1:创建链表 2-2:创建新的结点 2-3:初始化链表 2-4:打印链表 2-5:销毁链表 三:链表的核心功能 3-1:尾插 3-2:尾删 3-3:链表查找 ...

  8. 诺基亚没放弃 它买下这家公司,要成为电信界的扛把子

    诺基亚抛售了智能手机业务,又转让了数字地图业务,今天的诺基亚最重要的主营业务是电信网络设备.在电信业务方面,诺基亚一直在忙着收购外部公司.日前,诺基亚又收购了美国一家专门进行有线电视网络铺网的公司. ...

  9. 年终奖买啥最合适?马上安排降噪耳机界的扛把子,索尼WF-1000XM4

    每到岁末年初,"年终奖"总是令人期待.无论金额多少,相信你早已计划着用这笔钱好好犒劳下辛苦了一年的自己,给望眼欲穿的春节团圆再添一丝温暖,才更有动力在接下来的一年继续奋战.面对数码 ...

最新文章

  1. 马斯克受罚离任董事长,默多克之子或将成接替者!
  2. F-子序列(组合数,打表,扩展欧拉,容斥)
  3. mybatis example处理and、or关系的方法
  4. LISP 冻结excel窗格_粗暴讲解,2分钟 | 即懂excel 冻结首行、首列和单元格怎么弄?...
  5. 扫掠曲面二条引导线_说说国策下的三四线城市与会展
  6. 将勾选数据从dataset中筛选出来
  7. java 重载、重写、重构的区别
  8. 关于android的tabhost中进行参数传递的问题
  9. FileUtils的简单读写文件操作
  10. 用计算机怎样弄出告白密码,数字表白密码 表白密码大全
  11. 代码审查工具 phabricator 使用学习
  12. 计算机网络专业综合实践报告,计算机网络专业实习报告.doc
  13. 【FPGA】RGMII接口
  14. 【运维】linux shell 编程之函数使用
  15. vs code 让界面占满全屏的快捷键
  16. 微信红包和转账有哪些区别?原来还有这些不同!涨知识了
  17. 订酒店接口 携程酒店在线预订
  18. 双开助手多开分身版 v5.1.8
  19. GUID分区与MBR分区有什么区别? 操作系统知识
  20. 教育期刊《中学语文教学参考》杂志简介及投稿须知

热门文章

  1. PS摩棒工具如何选中自己想要的区域
  2. Socket 同步/异步 与阻塞/非阻塞区别
  3. ISIS和OSPF的比较
  4. DATAGRID学习
  5. (MS SQL)如何实现相关文章功能(多关键字匹配)
  6. Hadoop- MapReduce分布式计算框架原理
  7. 五步让你玩转CocoaPods
  8. VS 2008 mfc 智能应用程序 调用 C# webservice.(二)(gsoap+wince)
  9. HTML5标签的语义认知和理解
  10. 推荐一款超级好用的开源画图工具:用例图、架构图、时序图、类图、E-R图、甘特图