# :-: elsfs 開源項目java代碼規范
[TOC]
## 1. 介紹
本文檔是elsfs Java源代碼編碼標準的完整定義,編程語言Java源文件被描述為elsfs樣式,前提是必須遵守此處的規則。
與其他編程風格指南一樣,所涵蓋的問題不僅涉及格式的美學問題,還涉及其他類型的約定或編碼標準。然而,本文件主要關注我們普遍遵循的硬性規則,并避免提供無法明確執行的建議(無論是通過人工還是工具)。
### 1.1. 術語解釋
在本文件中,除非另有說明:
1. 類一詞包括 普通類(ordinary class)、枚舉類(enum class)、接口(interface)或注釋類型(@interface)。
2. 成員(類)這一術語被廣泛地用于表示嵌套類、字段、方法或構造函數;也就是說,除了初始化器和注釋之外的所有類頂層內容。
3. 術語“注釋”始終指的是實現注釋。我們不使用“文檔注釋”這個短語,而是使用通用術語“Javadoc”。
**其他“術語注解”將會在文檔中不定時出現。**
### 1.2. 指南解釋
本文檔中的示例代碼是非規范性的。也就是說,雖然示例采用elsfsf樣式,但它們可能沒有唯一的方式來表達代碼。示例中做出的可選格式選擇不應被強制作為規則。
## 2. 源文件的基本條件
### 2.1. 文件名稱
原文件名必須和頂級類(只有一個 java特性)的名字一致且區分大小寫,擴展名“.java”
### 2.2. 文件編碼
文件編碼格式為:UTF-8
### 2.3. 特殊字符
#### 2.3.1. 空白字符
除了行終止符之外,源文件允空格使用ASCII水平空格(0x20)
這意味著:
1. 字符串和字符文字中的所有其他空白字符都需要進行轉義
2. 制表符不能用于縮進
#### 2.3.2 特殊字符轉義
對于任何具有特殊轉義(\b、\t、\n、\f、\r、\“、\'和\\)的字符,都會使用該序列,而不是相應的八進制(例如\012)或Unicode(例如\u000a)轉義。
參考The Java? Tutorials
[Characters (The Java? Tutorials > Learning the Java Language > Numbers and Strings) (oracle.com)](https://docs.oracle.com/javase/tutorial/java/data/characters.html)
#### 2.3.3 非ASCII的字符
對于其余非ASCII字符,使用實際的Unicode字符(例如∞)或等效的Unicode轉義符(例如\\ u221e)。選擇哪一種編碼只取決于哪種編碼更易于閱讀和理解,盡管Unicode可以在字符串文字外轉義,強烈建議不要使用注釋。
**提示:** 在Unicode轉義的情況下,甚至在偶爾使用實際的Unicode字符時,解釋性的注釋都是非常有幫助的。
**例子:**
| 例子 | 討論說明 |
| --- | --- |
| String unitAbbrev = "μs"; | 即使沒有注釋也比較清楚 |
| String unitAbbrev = "\u03bcs"; // "μs" | 允許,但是沒有理由這樣做 |
|String unitAbbrev = "\u03bcs"; // Greek letter mu, "s"| 允許,但是容易出錯 |
|String unitAbbrev = "\u03bcs"; | 沒有注釋,讀者根本不知道這是什么。 |
|return '\ufeff' + content; // byte order mark | 允許,對不可打印的字符使用轉義符,必要時可以注釋。|
**提示:**不要因為擔心某些程序可能無法正確處理非ASCII字符而降低代碼的可讀性。如果真的發生了這種情況,那么這些程序就壞了,必須進行修復。
## 3 源文件結構
### 3.1 許可證或版權信息(如果有)
如果許可證或版權信息屬于文件的一部分,那么就把許可放在文件里。
### 3.2 包聲明
package語句聲明不能換行,列限制 [4.4 列限制:100]()不適用于包聲明
### 3.3 導入
#### 3.3.1 不允許使用通配符導入
不允許靜態或其他形式的通配符導入
#### 3.3.2 不允許導入聲明與導入聲明之間存在空格
導入語句不允許換行 [4.4 列限制:100]()不適用導入語句
#### 3.3.3 導入聲明排序和間距
導入語句的排序方式如下:
1. 將所有靜態導入放在一個塊中。
2. 將所有非靜態導入放在一個塊中。
如果同時存在靜態和非靜態導入,則用一條空行分隔這兩個塊。導入語句之間沒有其他空行。
在每個塊中,導入的名稱以ASCII排序順序顯示。(**注意**:這與導入語句的ASCII排序順序不同,因為“.”在“;”之前排序。)
#### 3.3.4 禁止靜態導入類
靜態導入不能用于靜態嵌套類,它們是通過普通導入來導入的。
### 3.4 類的聲明
#### 3.4.1 只有一個頂級類聲明
每一個頂級類都一個在自己獨立的原文件中
#### 3.4.2 類的內容順序
對于類的成員和初始化器的選擇順序,可能會對可學習性產生很大的影響。但是,并沒有一個正確的做法;不同的類可能會以不同的方式來排序它們的內容。
重要的是每個類都使用某種邏輯順序,如果需要的話,其維護者可以解釋這個順序。例如,新方法不應該習慣性地添加到類的末尾,因為那樣會導致按照添加日期排序的順序,這不是一個邏輯順序。
##### 3.4.2.1 重載:分不割
具有相同名稱的方法出現在一個單獨的連續組中,組中沒有其他成員。對于多個構造函數(它們總是具有相同的名稱),也適用相同的規則。即使在不同的方法之間存在修飾符(如static或private),也適用此規則。
## 4 格式化
術語注記:塊狀結構體是指類體、方法體或構造函數體。注意,在4.8.1 數組初始化中,任何數組初始化都可以可選擇地被視為塊狀結構體。
### 4.1 花括號
#### 4.1.1 可選使用大括號
花括號與if、else、for、do和while語句一起使用,即使主體為空或僅包含一個語句。其他可選的花括號(例如lambda表達式中的花括號)仍然可選。
#### 4.1.2 非空快結構:K&R樣式
花括號(braces)按照Kernighan和Ritchie風格(“埃及花括號”)來配對非空塊和塊狀結構:
* 除以下詳細說明的情況外,在開括號前沒有換行。
* 將開括號后的內容進行換行。
* 在閉合的大括號前添加換行符。
* 在關閉的大括號后面換行,只有當該大括號結束了一個語句或者結束了一個方法、構造函數或者命名類的主體時。例如,如果大括號后面是else或者逗號,則不會在大括號后面換行。
異常:在這些規則允許以分號(;)結尾的單個語句的地方,可以出現一個語句塊,并且該塊的開括號前面有一個行斷裂。這些塊通常被引入以限制局部變量的范圍,例如在switch語句內部
**例子:**
~~~
return () -> {
while (condition()) {
method();
}
};
return new MyClass() {
@Override public void method() {
if (condition()) {
try {
something();
} catch (ProblemException e) {
recover();
}
} else if (otherCondition()) {
somethingElse();
} else {
lastThing();
}
{
int x = foo();
frob(x);
}
}
};
~~~
第4.8.1節“枚舉類”給出了對枚舉類的幾個例外。
#### 4.1.3 空快結構
一個空的代碼塊或類似代碼塊的構造可以使用K&R風格(如4.1.2節所述)。或者,可以在打開后立即關閉,中間沒有字符或行分隔符({}),除非它是多代碼塊語句(直接包含多個代碼塊的語句:if/else或try/catch/finally)的一部分。
**例子:**
~~~
// This is acceptable
void doNothing() {}
// This is equally acceptable
void doNothingElse() {
}
~~~
~~~
// This is not acceptable: No concise empty blocks in a multi-block statement
try {
doSomething();
} catch (Exception e) {}
~~~
### 4.2 快縮進:2個空格
每次打開一個新的代碼塊或類似代碼塊的構造時,縮進增加兩個空格。當代碼塊結束時,縮進返回上一個縮進級別。在整個代碼塊中,縮進級別適用于代碼和注釋(見第4.1.2節“非空代碼塊:K&R風格”中的示例)。
### 4.3 每行一個陳述
每個語句后面都跟著一個換行符。
### 4.4 列限制 100
Java代碼有一個100字符的列限制。“字符”表示任何Unicode編碼點。除非下面另有說明,否則任何超過此限制的行必須按第4.5節“換行”中所述進行行包裝。
每個Unicode碼點都計為1個字符,即使它的顯示寬度更大或更小。例如,如果使用全角字符,則可以選擇在比此規則嚴格要求的位置更早的地方換行。
**異常(xceptions):**
1. 無法遵守列限制的行(例如Javadoc中的長URL,或長JSNI方法引用)。
2. 包聲明和導包聲明(見第3.2節包聲明和第3.3節導包聲明)。
3. 注釋中的命令行,可以被復制并粘貼到shell中。
4. 在極少數情況下需要非常長的標識符,允許其超過列限制。在這種情況下,周圍代碼的有效換行方式應由java-format生成。
### 4.5 換行
**術語注解:**當一段代碼在單行中無法合法地占用一行時,將該代碼拆分成多行,這個活動就叫做換行。
沒有一種全面、確定的公式可以精確地告訴你在任何情況下如何進行折行。很多時候,對于同一段代碼,存在多種有效的折行方式。
***注意:**盡管換行的常見原因是避免超過列限制,但即使是實際上能夠適應列限制的代碼也可能由作者自行決定進行換行。*
**提示:**提取方法或局部變量可以在不需要換行的情況下解決問題。
#### 4.5.1 折行
折行的首要原則是:傾向于在更高的句法層面進行折行。同時:
1. 當一行在非賦值運算符處斷開時,斷點出現在該符號之前。
這也適用于以下“類似操作符”的符號:
* 點分隔符(.)
* 方法引用的兩個冒號(:)
* 在類型約束中()使用ampersand
* 在catch塊中的管道(catch(FooException|BarException e))。
2. 當一行在賦值運算符處斷開時,通常在該符號之后斷開,但是兩種方式都是可以接受的。
* 這也適用于增強for循環(“foreach”)語句中的“賦值運算符-樣”冒號。
3. 方法或構造器的名稱保留附著在其后跟隨的開放圓括號(**(**)上。
4. 逗號(,)保持與其前面的標記相連。
5. lambda表達式中箭頭兩側的代碼行不會被分割,除非lambda的主體只包含一個不帶花括號的表達式,此時箭頭后可緊隨一個代碼行。例如:
~~~
MyLambda<String, Long, Object> lambda =
(String label, Long value, Object obj) -> {
...
};
Predicate<String> predicate = str ->
longExpressionInvolving(str);
~~~
**注意**:換行的主要目標是擁有清晰的代碼,而不一定是適合最小行數的代碼。
#### 4.5.2 換行空4個格的情況(java 17)推薦
### 4.6 空白
#### 4.6.1 垂直空白
一個單獨的空白行總是會出現:
1. 在類的連續成員或初構造器之間:字段、構造函數、方法、嵌套類、靜態初始化程序和實例初始化程序。
* **例外**:兩個連續字段(它們之間沒有其他代碼)之間的空行是可選的。這些空行根據需要用于創建字段的邏輯分組。
* Exception:枚舉常量之間的空行在第4.8.1節中有所介紹。
2. 按照本文件其他部分的要求(例如第3節“源文件結構”和第3.3節“導入語句”)。
在任何可以改善可讀性的地方,也可以出現一個空行,例如在語句之間將代碼組織成邏輯子部分。類中第一個成員或初始化器之前或最后一個成員或初始化器之后,空行既不鼓勵也不阻止。
多行連續空白行是允許的,但從來不是必需的。
#### 4.6.2 空格
除了語言或其他樣式規則要求的地方,以及除了文字、注釋和Javadoc之外,單個ASCII空格也僅出現在以下地方。
1. 將任何保留字(如if、for或catch)與緊隨其后的開圓括號(())分離,位于同一行內
2. 將任何保留字(例如 else 或 catch)與在該行的開頭跟在它前面的結束花括號(})分離
3. 在任何開大括號({})之前,除兩種情況外:
* `@SomeAnnotation({a, b})`(沒有空格)
* String\[\]\[\] x = {{"foo"}}; 不需要在兩者{{之間留有空格
4. 在任何二元或三元運算符的兩邊。這也適用于以下“類似運算符”的符號:
* 在泛型中:<T extends Foo>
* 處理多個異常的用于捕獲塊:catch (FooException | BarException e)
* 增強for循環(“foreach”)語句中的冒號(:)
* lambda表達式中的箭頭:(String str) -> str.length()
* 方法引用的雙冒號:Object::toString
* 點號分隔符(.):object.toString
5. 在任何內容與雙斜杠(//)之間,該雙斜杠開始一個注釋。允許使用多個空格。
6. 在開始注釋的雙斜杠(//)和注釋的文本之間。允許使用多個空格。
7. 在聲明的類型和變量之間:*List<String> list*
8. 僅在數組初始值設定項的兩個大括號內可選
* * `new int[] {5, 6}`and`new int[] { 5, 6 }`are both valid
9. 1. 在類型批注和 或 之間。`[]``...`
這條規則從來沒有被解釋為要求或禁止在一行的開始或結束處有額外的空間;它只涉及內部空間。
#### 4.6.3 水平對齊
術語注釋:水平對齊是在代碼中添加可變數量的額外空格的做法,目的是使某些標記直接出現在前幾行的某些其他標記下方。
這種做法是允許的,但代碼風格從來沒有要求。它甚至不需要在已經使用過的地方保持水平對齊。
下面是一個沒有對齊,然后使用對齊的示例:
~~~
private int x; // this is fine
private Color color; // this too
private int x; // permitted, but future edits
private Color color; // may leave it unaligned
~~~
提示:對齊可以提高可讀性,但會給將來的維護帶來問題。考慮一下未來只需要觸及一條線的變化。這種更改可能會使以前令人愉快的格式被破壞,這是允許的。更常見的情況是,它會提示編碼器(也許是您)調整附近行上的空白,可能會觸發一系列級聯的重新格式化。這一行更改現在有了一個“爆炸半徑”。這在最壞的情況下可能會導致毫無意義的繁忙工作,但在最好的情況下,它仍然會破壞版本歷史信息,減慢審閱者的速度,并加劇合并沖突。
### 4.7 分組圓括號:推薦
只有當作者和審核者都認為省略了可選的分組圓括號不會引起代碼的誤解,而且使用它們也不會使代碼更容易閱讀時,才可以省略它們。假定每個讀者都記住了Java操作符優先級表是不合理的。
### 4.8 具體類結構
#### 4.8.1 聲明一個變量
每個變量聲明(字段或局部變量)只聲明一個變量:聲明如int a、b;不使用。
異常:在for循環的頭中可以接受多個變量聲明。
#### 4.8.2 在需要的時候才申請變量
局部變量不習慣在包含它們的作用域或塊狀構造的開頭進行聲明,而是在首次使用時(在合理范圍內)附近進行聲明,以最小化它們的作用域。局部變量聲明通常有初始化器,或者在聲明后立即進行初始化。
### 4.8.3 Arrays
#### 4.8.3.1數組初始值設定項:可以是“類塊”
任何數組初始值設定項都可以選擇性地格式化為“類似塊的構造”。例如,以下內容都是有效的(不是詳盡的列表):
~~~
new int[] { new int[] {
0, 1, 2, 3 0,
} 1,
2,
new int[] { 3,
0, 1, }
2, 3
} new int[]
{0, 1, 2, 3}
~~~
#### 4.8.3.2 沒有C-Style數組聲明
使用這個形式`String[] args`, 而不是`String args[]`.
#### 4.8.4 Switch語句
術語注釋:switch塊的大括號內是一個或多個語句組。每個語句組包含一個或多個switch標簽(要么是case FOO:,要么是default:),后面跟著一個或多個語句(或者對于最后一個語句組,后面跟著零個或多個語句)。
##### 4.8.4.1 縮進
與其他任何塊一樣,switch塊的內容縮進+2。
在switch標簽之后,有一個換行符,并且縮進級別增加+2,就仿佛一個塊被打開了一樣。以下的switch標簽返回先前的縮進級別,就像一個塊被關閉一樣。
##### 4.8.4.2 解釋
在一個switch塊內,每個語句組要么突然終止(使用break、continue、return或拋出異常),要么使用注釋標記以表示執行會或可能會繼續到下一個語句組。任何傳達“fall through”思想的注釋都是足夠的(通常為// fall through)。在switch塊的最后一個語句組中不需要這種特殊的注釋。例如:
~~~
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
~~~
注意,在case 1之后不需要注釋,只有在語句組的末尾才需要注釋。
##### 4.8.4.3 default 標簽
每個switch語句都包含一個default語句組,即使它不包含任何代碼。
例外:如果為枚舉類型添加了顯式案例并且涵蓋該類型的所有可能值,則可以省略default語句組。這使得IDE或其他靜態分析工具能夠發出警告,如果漏掉了任何情況。
#### 4.8.5 注釋
##### 4.8.5.1 注解類型使用
## 5 命名
- 項目介紹
- 代碼規范
- Java代碼規范指南
- Java規范
- ADEA格式化配置Java
- ADEA_checkstyle檢查規范配置
- maven代碼規范檢查配置
- maven格式化代碼配置
- gradle檢查代碼配置
- gradle代碼格式化配置
- 編碼檢查配置
- vscode代碼格式化配置java
- Eclipse代碼格式化配置java
- 前端和TypeScrity規范指南
- TypeScript規范
- 數據庫規范
- 關系型數據庫規范指南
- 關系型數據庫設計規范
- 非關系型數據庫設計規范
- redis設計規范
- ES數據庫設計規范
- git規范指南
- 提交日志規范
- 分支規范
- 開發環境
- Windows開發環境指南安裝指南
- Mac開發環境安裝指南
- 生產部署指南
- redhat裸機環境部署
- redhat_docker環境部署
- Ubuntu裸機環境部署
- Ubuntu_docker環境部署
- docker集群環境部署
- k8s集群環境部署
- 二開指南
- 前端
- 后端
- 后臺開發
- java編程基礎
- lombok 使用及技巧
- java 工具類使用
- stream 使用及其技巧
- lambda 使用及其技巧
- java微服務基礎
- nacos 服務注冊與發現作用
- gateway網關的作用
- loadBalancer 負載均衡器作用
- sentinel 流量保護作用
- sate分布式事務
- 認證授權
- 可選功能
- swagger文檔
- 前端開發
- 前端代碼結構
- 適配spring_native模式
- 適配micronaut框架
- 適配quarkus框架
- 常見問題