diff --git a/README.md b/README.md index eca328cc..4b4e7557 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle ### 新特性 1. **Java 8** :[Java 8 新特性总结](docs/java/new-features/Java8新特性总结.md)、[Java8常用新特性总结](docs/java/new-features/java8-common-new-features.md) 、[Java 8 学习资源推荐](docs/java/new-features/Java8教程推荐.md)、[Java8 forEach 指南](docs/java/new-features/Java8foreach指南.md) -2. **Java9~Java14** : [一文带你看遍 JDK9~14 的重要新特性!](./docs/java/new-features/一文带你看遍JDK9到14的重要新特性.md) +2. **Java9~Java15** : [一文带你看遍 JDK9~15 的重要新特性!](./docs/java/new-features/java新特性总结.md) ## 计算机基础 diff --git a/docs/java/new-features/一文带你看遍JDK9到14的重要新特性.md b/docs/java/new-features/java新特性总结.md similarity index 90% rename from docs/java/new-features/一文带你看遍JDK9到14的重要新特性.md rename to docs/java/new-features/java新特性总结.md index cb0669f3..c815fa1a 100644 --- a/docs/java/new-features/一文带你看遍JDK9到14的重要新特性.md +++ b/docs/java/new-features/java新特性总结.md @@ -336,7 +336,7 @@ var op = Optional.empty(); System.out.println(op.isEmpty());//判断指定的 Optional 对象是否为空 ``` -### ZGC:可伸缩低延迟垃圾收集器 +### ZGC(可伸缩低延迟垃圾收集器) **ZGC 即 Z Garbage Collector**,是一个可伸缩的、低延迟的垃圾收集器。 @@ -549,6 +549,46 @@ if(obj instanceof String str){ ## Java13 +### 增强 ZGC(释放未使用内存) + +在 Java 11 中是实验性的引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题。 + +ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用(LRU)的顺序,并按照大小进行组织。 + +在 Java 13 中,ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用。 + +### SocketAPI 重构 + +Java Socket API 终于迎来了重大更新! + +Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 + +并且,在 Java 13 中是默认使用新的 Socket 实现。 + +```java +public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl { +} +``` + +### FileSystems + +`FileSystems` 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序: + +- `newFileSystem(Path)` +- `newFileSystem(Path, Map)` +- `newFileSystem(Path, Map, ClassLoader)` + +### 动态 CDS 存档 + +Java 13 中对 Java 10 中引入的应用程序类数据共享(AppCDS)进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。 + +这提高了应用程序类数据共享([AppCDS](https://openjdk.java.net/jeps/310))的可用性。无需用户进行试运行来为每个应用程序创建类列表。 + +```bash +$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar +$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar +``` + ### 预览新特性 #### 文本块 @@ -569,7 +609,6 @@ String json ="{\n" + 支持文本块之后的 HTML 写法: ```java - String json = """ { "name":"mkyong", @@ -633,46 +672,6 @@ public String translateEscapes() { } ``` -### 增强 ZGC(释放未使用内存) - -在 Java 11 中是实验性的引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题。 - -ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用(LRU)的顺序,并按照大小进行组织。 - -在 Java 13 中,ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用。 - -### SocketAPI 重构 - -Java Socket API 终于迎来了重大更新! - -Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 - -并且,在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性 - -```java -public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl { -} -``` - -### FileSystems - -`FileSystems` 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序: - -- `newFileSystem(Path)` -- `newFileSystem(Path, Map)` -- `newFileSystem(Path, Map, ClassLoader)` - -### 动态 CDS 存档 - -Java 13 中对 Java 10 中引入的应用程序类数据共享(AppCDS)进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。 - -这提高了应用程序类数据共享([AppCDS](https://openjdk.java.net/jeps/310))的可用性。无需用户进行试运行来为每个应用程序创建类列表。 - -```bash -$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar -$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar -``` - ## Java14 ### 空指针异常精准提示 @@ -789,6 +788,127 @@ c++ php - 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退) - 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb`和`rpm`,window 平台下的`msi`和`exe` +## Java15 + +### CharSequence + +`CharSequence` 接口添加了一个默认方法 `isEmpty()` 来判断字符序列为空,如果是则返回 true。 + +```java +public interface CharSequence { + default boolean isEmpty() { + return this.length() == 0; + } +} +``` + +### TreeMap + +`TreeMap` 新引入了下面这些方法: + +- `putIfAbsent()` +- `computeIfAbsent()` +- `computeIfPresent()` +- `compute()` +- `merge()` + +### ZGC(转正) + +Java11 的时候 ,ZGC 还在试验阶段。 + +当时,ZGC 的出现让众多 Java 开发者看到了垃圾回收器的另外一种可能,因此备受关注。 + +经过多个版本的迭代,不断的完善和修复问题,ZGC 在 Java 15 已经可以正式使用了! + +不过,默认的垃圾回收器依然是 G1。你可以通过下面的参数启动 ZGC: + +```bash +$ java -XX:+UseZGC className +``` + +### EdDSA(数字签名算法) + +新加入了一个安全性和性能都更强的基于 Edwards-Curve Digital Signature Algorithm (EdDSA)实现的数字签名算法。 + +虽然其性能优于现有的 ECDSA 实现,不过,它并不会完全取代 JDK 中现有的椭圆曲线数字签名算法( ECDSA)。 + +```java +KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519"); +KeyPair kp = kpg.generateKeyPair(); + +byte[] msg = "test_string".getBytes(StandardCharsets.UTF_8); + +Signature sig = Signature.getInstance("Ed25519"); +sig.initSign(kp.getPrivate()); +sig.update(msg); +byte[] s = sig.sign(); + +String encodedString = Base64.getEncoder().encodeToString(s); +System.out.println(encodedString); +``` + +输出: + +``` +0Hc0lxxASZNvS52WsvnncJOH/mlFhnA8Tc6D/k5DtAX5BSsNVjtPF4R4+yMWXVjrvB2mxVXmChIbki6goFBgAg== +``` + +### 文本块(转正) + +在 Java 15 ,文本块是正式的功能特性了。 + +### 隐藏类(Hidden Classes) + +隐藏类是为框架(frameworks)所设计的,隐藏类不能直接被其他类的字节码使用,只能在运行时生成类并通过反射间接使用它们。 + +### 预览新特性 + +#### record 关键字 + +Java 15 对 Java 14 中引入的预览新特性进行了增强,主要是引入了一个新的概念 **密封类(Sealed Classes)。** + +密封类可以对继承或者实现它们的类进行限制。 + +比如抽象类 `Person` 只允许 `Employee` 和 `Manager` 继承。 + +```java +public abstract sealed class Person + permits Employee, Manager { + + //... +} +``` + +另外,任何扩展密封类的类本身都必须声明为 `sealed`、`non-sealed` 或 `final`。 + +```java +public final class Employee extends Person { +} + +public non-sealed class Manager extends Person { +} +``` + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/image-20210820153955587.png) + +在 `java.lang.Class` 增加了两个公共方法用于获取 `Record` 类信息: + +1. `RecordComponent[] getRecordComponents()` +2. `boolean isRecord()` + +#### instanceof 模式匹配 + +Java 15 并没有对此特性进行调整,继续预览特性,主要用于接受更多的使用反馈。 + +在未来的 Java 版本中,Java 的目标是继续完善 `instanceof` 模式匹配新特性。 + +### Java15 其他新特性 + +- **Nashorn JavaScript 引擎彻底移除** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性。在 Java 11 中就已经被弃用,到了 Java 15 就彻底被删除了。 +- **DatagramSocket API 重构** +- **禁用和废弃偏向锁(Biased Locking)** : 偏向锁的引入增加了 JVM 的复杂性大于其带来的性能提升。不过,你仍然可以使用 `-XX:+UseBiasedLocking` 启用偏向锁定,但它会提示 这是一个已弃用的 API。 +- ...... + ## 总结 ### 关于预览特性 @@ -824,4 +944,5 @@ c++ php - Java13 新特性概述 - Oracle Java14 record - java14-features -- Java 14 Features : \ No newline at end of file +- Java 14 Features : +- What is new in Java 15: https://mkyong.com/java/what-is-new-in-java-15/ \ No newline at end of file diff --git a/docs/system-design/naming.md b/docs/system-design/naming.md index 33d0db49..33579c91 100644 --- a/docs/system-design/naming.md +++ b/docs/system-design/naming.md @@ -1,14 +1,42 @@ -编程过程中,有太多太多让我们头疼的事情了,比如命名、维护其他人的代码、写测试、与其他人沟通交流等等。就连世界级软件大师 **Martin Fowler** 大神都说过 CS 领域有两大最难的事情,一是**缓存失效**,一是**程序命名**(@ [https://martinfowler.com/bliki/TwoHardThings.html](https://martinfowler.com/bliki/TwoHardThings.html))。 +> 可选标题:工作半年,变量命名不规范,被diss了! +> +> 项目组新来的实习生因为变量命名被 “diss” 了! -![](pictures/marting-naming.png) +大家好,这里是热爱分享的 Guide ! -今天 Guide 就单独拎出 “**命名**” 来聊聊,据说之前在 Quora 网站,由接近 5000 名程序员票选出来的最难的事情就是“命名”。 +我还记得我刚工作那一段时间, 项目 Code Review 的时候,我经常因为变量命名不规范而被 “diss”! + +究其原因还是自己那会经验不足,而且,大学那会写项目的时候不太注意这些问题,想着只要把功能实现出来就行了。 + +但是,工作中就不一样,为了代码的可读性、可维护性,项目组对于代码质量的要求还是很高的! + +前段时间,项目组新来的一个实习生也经常在 Code Review 因为变量命名不规范而被 “diss”,这让我想到自己刚到公司写代码那会的日子。 + +于是,我就简单写了这篇关于变量命名规范的文章,希望能对同样有此困扰的小伙伴提供一些帮助。 + +确实,编程过程中,有太多太多让我们头疼的事情了,比如命名、维护其他人的代码、写测试、与其他人沟通交流等等。 + +据说之前在 Quora 网站,由接近 5000 名程序员票选出来的最难的事情就是“命名”。 + +大名鼎鼎的《重构》的作者老马(Martin Fowler)曾经在[TwoHardThings](https://martinfowler.com/bliki/TwoHardThings.html)这篇文章中提到过CS 领域有两大最难的事情:一是 **缓存失效** ,一是 **程序命名** 。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/marting-naming.png) + +这个句话实际上也是老马引用别人的,类似的表达还有很多。比如分布式系统领域有两大最难的事情:一是 **保证消息顺序** ,一是 **严格一次传递** 。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/20210629104844645.png) + +今天咱们就单独拎出 “**命名**” 来聊聊! 这篇文章配合我之前发的 [《编码 5 分钟,命名 2 小时?史上最全的 Java 命名规范参考!》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486449&idx=1&sn=c3b502529ff991c7180281bcc22877af&chksm=cea2443af9d5cd2c1c87049ed15ccf6f88275419c7dbe542406166a703b27d0f3ecf2af901f8&token=999884676&lang=zh_CN#rd) 这篇文章阅读效果更佳哦! ## 为什么需要重视命名? -**好的命名即是注释,别人一看到你的命名就知道你的变量、方法或者类是做什么的!** 好的命名对于其他人(包括你自己)理解你的代码有着很大的帮助! +咱们需要先搞懂为什么要重视编程中的命名这一行为,它对于我们的编码工作有着什么意义。 + +**为什么命名很重要呢?** 这是因为 **好的命名即是注释,别人一看到你的命名就知道你的变量、方法或者类是做什么的!** + +简单来说就是 **别人根据你的命名就能知道你的代码要表达的意思** (不过,前提这个人也要有基本的英语知识,对于一些编程中常见的单词比较熟悉)。 简单举个例子说明一下命名的重要性。 @@ -64,7 +92,9 @@ serviceDiscovery、Serviceinstance、LRUCacheFactory 正例: ```java -getUserInfo()、createCustomThreadPool()、setNameFormat(String nameFormat) +getUserInfo() +createCustomThreadPool() +setNameFormat(String nameFormat) Uservice userService; ``` @@ -81,7 +111,9 @@ Uservice user_service 在蛇形命名法中,各个单词之间通过下划线“\_”连接,比如`should_get_200_status_code_when_request_is_valid`、`CLIENT_CONNECT_SERVER_FAILURE`。 -蛇形命名法的优势是命名所需要的单词比较多的时候,比如我把上面的命名通过小驼峰命名法给大家看一下:“shouldGet200StatusCodoWhenRequestIsValid”。**感觉如何? 相比于使用蛇形命名法(snake_case)来说是不是不那么易读?\*\*** +蛇形命名法的优势是命名所需要的单词比较多的时候,比如我把上面的命名通过小驼峰命名法给大家看一下:“shouldGet200StatusCodoWhenRequestIsValid”。 + +感觉如何? 相比于使用蛇形命名法(snake_case)来说是不是不那么易读? 正例: @@ -103,29 +135,29 @@ void shouldGet200StatusCodoWhenRequestIsValid() { ### 串式命名法(kebab-case) -在串式命名法中,各个单词之间通过下划线“-”连接,比如`dubbo-registry`。 +在串式命名法中,各个单词之间通过连接符“-”连接,比如`dubbo-registry`。 建议项目文件夹名称使用串式命名法(kebab-case),比如 dubbo 项目的各个模块的命名是下面这样的。 -![](./pictures/dubbo-naming.png) +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/dubbo-naming.png) ## 常见命名规范 ### Java 语言基本命名规范 -**1.类名需要使用大驼峰命名法(UpperCamelCase)风格。方法名、参数名、成员变量、局部变量需要使用小驼峰命名法(lowerCamelCase)。** +**1、类名需要使用大驼峰命名法(UpperCamelCase)风格。方法名、参数名、成员变量、局部变量需要使用小驼峰命名法(lowerCamelCase)。** -**2.测试方法名、常量、枚举名称需要使用蛇形命名法(snake_case)**,比如`should_get_200_status_code_when_request_is_valid`、`CLIENT_CONNECT_SERVER_FAILURE`。并且,**测试方法名称要求全部小写,常量以及枚举名称需要全部大写。** +**2、测试方法名、常量、枚举名称需要使用蛇形命名法(snake_case)**,比如`should_get_200_status_code_when_request_is_valid`、`CLIENT_CONNECT_SERVER_FAILURE`。并且,**测试方法名称要求全部小写,常量以及枚举名称需要全部大写。** -**3.项目文件夹名称使用串式命名法(kebab-case),比如`dubbo-registry`。** +**3、项目文件夹名称使用串式命名法(kebab-case),比如`dubbo-registry`。** -**4.包名统一使用小写,尽量使用单个名词作为包名,各个单词通过 "." 分隔符连接,并且各个单词必须为单数。** +**4、包名统一使用小写,尽量使用单个名词作为包名,各个单词通过 "." 分隔符连接,并且各个单词必须为单数。** 正例: `org.apache.dubbo.common.threadlocal` 反例: ~~`org.apache_dubbo.Common.threadLocals`~~ -**5.抽象类命名使用 Abstract 开头**。 +**5、抽象类命名使用 Abstract 开头**。 ```java //为远程传输部分抽象出来的一个抽象类(出处:Dubbo源码) @@ -134,7 +166,7 @@ public abstract class AbstractClient extends AbstractEndpoint implements Client } ``` -**6.异常类命名使用 Exception 结尾。** +**6、异常类命名使用 Exception 结尾。** ```java //自定义的 NoSuchMethodException(出处:Dubbo源码) @@ -151,7 +183,7 @@ public class NoSuchMethodException extends RuntimeException { } ``` -**7.测试类命名以它要测试的类的名称开始,以 Test 结尾。** +**7、测试类命名以它要测试的类的名称开始,以 Test 结尾。** ```java //为 AnnotationUtils 类写的测试类(出处:Dubbo源码) @@ -166,19 +198,19 @@ POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架 ### 命名易读性规范 -**1.为了能让命名更加易懂和易读,尽量不要缩写/简写单词,除非这些单词已经被公认可以被这样缩写/简写。比如 `CustomThreadFactory` 不可以被写成 ~~`CustomTF` 。** +**1、为了能让命名更加易懂和易读,尽量不要缩写/简写单词,除非这些单词已经被公认可以被这样缩写/简写。比如 `CustomThreadFactory` 不可以被写成 ~~`CustomTF` 。** -**2.命名不像函数一样要尽量追求短,可读性强的名字优先于简短的名字,虽然可读性强的名字会比较长一点。** 这个对应我们上面说的第 1 点。 +**2、命名不像函数一样要尽量追求短,可读性强的名字优先于简短的名字,虽然可读性强的名字会比较长一点。** 这个对应我们上面说的第 1 点。 -**3.避免无意义的命名,你起的每一个名字都要能表明意思。** +**3、避免无意义的命名,你起的每一个名字都要能表明意思。** 正例:`UserService userService;` `int userCount`; 反例: ~~`UserService service`~~ ~~`int count`~~ -**4.避免命名过长(50 个字符以内最好),过长的命名难以阅读并且丑陋。** +**4、避免命名过长(50 个字符以内最好),过长的命名难以阅读并且丑陋。** -5.**不要使用拼音,更不要使用中文。** 注意:像 alibaba 、wuhan、taobao 这种国际通用名词可以当做英文来看待。 +**5、不要使用拼音,更不要使用中文。** 不过像 alibaba 、wuhan、taobao 这种国际通用名词可以当做英文来看待。 正例:discount @@ -186,7 +218,7 @@ POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架 ## Codelf:变量命名神器? -这是一个由国人开发的网站,网上有很多人称其为变量命名神器, Guide 在实际使用了几天之后感觉没那么好用。小伙伴们可以自行体验一下,然后再给出自己的判断。 +这是一个由国人开发的网站,网上有很多人称其为变量命名神器, 我在实际使用了几天之后感觉没那么好用。小伙伴们可以自行体验一下,然后再给出自己的判断。 Codelf 提供了在线网站版本,网址:[https://unbug.github.io/codelf/](https://unbug.github.io/codelf/),具体使用情况如下: @@ -198,17 +230,22 @@ Codelf 提供了在线网站版本,网址:[https://unbug.github.io/codelf/]( ![](pictures/vscode-codelf.png) -## 总结 - -Guide 制作了一个涵盖上面所有重要内容的思维导图,便于小伙伴们日后查阅。 - -![](pictures/naming-mindmap.png) - -## 其他推荐阅读 +## 相关阅读推荐 1. 《阿里巴巴 Java 开发手册》 2. 《Clean Code》 3. Google Java 代码指南:https://google.github.io/styleguide/javaguide.html#s5.1-identifier-name 4. 告别编码5分钟,命名2小时!史上最全的Java命名规范参考:https://www.cnblogs.com/liqiangchn/p/12000361.html +## 总结 + +作为一个合格的程序员,小伙伴们应该都知道代码表义的重要性。想要写出高质量代码,好的命名就是第一步! + +好的命名对于其他人(包括你自己)理解你的代码有着很大的帮助!你的代码越容易被理解,可维护性就越强,侧面也就说明你的代码设计的也就越好! + +在日常编码过程中,我们需要谨记常见命名规范比如类名需要使用大驼峰命名法、不要使用拼音,更不要使用中文......。 + +另外,国人开发的一个叫做 Codelf 的网站被很多人称为“变量命名神器”,当你为命名而头疼的时候,你可以去参考一下上面提供的一些命名示例。 + +最后,祝愿大家都不用再为命名而困扰!