java-coding-guideline
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJava Coding Guideline
Java编码规范
CRITICAL: These rules apply to ALL Java code unless explicitly overridden by more specific skills.
重要提示:除非被更具体的规则明确覆盖,否则这些规则适用于所有Java代码。
Import Statements
导入语句
Always use explicit imports without wildcards for better code clarity and maintainability.
始终使用显式导入,避免使用通配符,以提升代码的清晰度和可维护性。
✅ Do
✅ 正确做法
java
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;java
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;❌ Don't
❌ 错误做法
java
import static org.assertj.core.api.Assertions.*;java
import static org.assertj.core.api.Assertions.*;Vertical Spacing (Readability)
垂直间距(可读性)
Use consistent vertical spacing inside classes to make diffs smaller and code easier to scan.
在类内部使用一致的垂直间距,以减少差异对比的复杂度并提升代码的易读性。
Rule
规则
- Insert exactly one blank line between:
- field blocks and the next field block (when grouped)
- fields and the first constructor
- constructors and methods
- methods and the next method
- Also insert one blank line right after the opening of a class (before the first field/initializer), unless the class is intentionally empty.
{
- 在以下内容之间插入恰好一个空行:
- 分组的字段块与下一个字段块之间
- 字段与第一个构造方法之间
- 构造方法与方法之间
- 方法与下一个方法之间
- 除非类是有意设计为空的,否则在类的左大括号之后(第一个字段/初始化器之前)也插入一个空行。
{
✅ Do
✅ 正确做法
java
public final class SomeClass {
@NonNull
private final String fieldA;
@NonNull
private final String fieldB;
public void someFunc() {
// some action
}
public String getFieldA() {
return fieldA;
}
}java
public final class SomeClass {
@NonNull
private final String fieldA;
@NonNull
private final String fieldB;
public void someFunc() {
// some action
}
public String getFieldA() {
return fieldA;
}
}❌ Don't
❌ 错误做法
java
public final class SomeClass {
@NonNull
private final String fieldA;
@NonNull
private final String fieldB;
public void someFunc() {
// some action
}
public String getFieldA() {
return fieldA;
}
}java
public final class SomeClass {
@NonNull
private final String fieldA;
@NonNull
private final String fieldB;
public void someFunc() {
// some action
}
public String getFieldA() {
return fieldA;
}
}Constructors
构造方法
Use a single primary constructor and delegate auxiliary constructors using .
this()使用单个主构造方法,辅助构造方法通过委托调用主构造方法。
this()✅ Do
✅ 正确做法
java
public final class SomeClass {
private final int field1;
private final int field2;
public SomeClass() {
this(1, 2);
}
public SomeClass(int field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
}java
public final class SomeClass {
private final int field1;
private final int field2;
public SomeClass() {
this(1, 2);
}
public SomeClass(int field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
}❌ Don't
❌ 错误做法
java
public final class SomeClass {
private final int field1;
private final int field2;
public SomeClass() {
this.field1 = 1;
this.field2 = 2;
}
public SomeClass(int field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
}java
public final class SomeClass {
private final int field1;
private final int field2;
public SomeClass() {
this.field1 = 1;
this.field2 = 2;
}
public SomeClass(int field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
}Optional Usage
Optional使用
Avoid using as return values or parameters. Use annotations instead.
Optional@Nullable避免将作为返回值或参数类型。改用注解。
Optional@Nullable✅ Do
✅ 正确做法
java
public final class SomeClass {
@Nullable
public Integer someNullable() {
if (something) return null;
return 1;
}
public void func(@Nullable Integer param) {
// do something
}
}java
public final class SomeClass {
@Nullable
public Integer someNullable() {
if (something) return null;
return 1;
}
public void func(@Nullable Integer param) {
// do something
}
}❌ Don't
❌ 错误做法
java
public final class SomeClass {
@NonNull
public Optional<Integer> someNullable() {
if (something) return Optional.ofNullable(null);
return Optional.ofNullable(1);
}
public void func(@NonNull Optional<Integer> param) {
// do something
}
}java
public final class SomeClass {
@NonNull
public Optional<Integer> someNullable() {
if (something) return Optional.ofNullable(null);
return Optional.ofNullable(1);
}
public void func(@NonNull Optional<Integer> param) {
// do something
}
}Wrapper vs Primitive Types
包装类型与基本类型
- Use wrapper types when is expected
null - Use primitive types when should not occur
null
- 当可能出现时使用包装类型
null - 当不应该出现时使用基本类型
null
✅ Do
✅ 正确做法
java
public final class SomeClass {
private final int field1;
@Nullable
private final Long field2;
public SomeClass(int field1, @Nullable Long field2) {
this.field1 = field1;
this.field2 = field2;
}
}java
public final class SomeClass {
private final int field1;
@Nullable
private final Long field2;
public SomeClass(int field1, @Nullable Long field2) {
this.field1 = field1;
this.field2 = field2;
}
}❌ Don't
❌ 错误做法
java
public final class SomeClass {
@NonNull
private final Integer field1;
@Nullable
private final Long field2;
public SomeClass(@NonNull Integer field1, @Nullable Long field2) {
this.field1 = field1;
this.field2 = field2;
}
}java
public final class SomeClass {
@NonNull
private final Integer field1;
@Nullable
private final Long field2;
public SomeClass(@NonNull Integer field1, @Nullable Long field2) {
this.field1 = field1;
this.field2 = field2;
}
}Null Comparison
空值比较
- Use for general cases
A == null - Use for Stream API or functional programming contexts
Objects.isNull
- 一般情况下使用
A == null - 在Stream API或函数式编程场景下使用
Objects.isNull
✅ Do
✅ 正确做法
java
final Integer someVariable = null;
if (someVariable == null) {
// do something
}
List<Integer> lists = new ArrayList<>();
lists.stream()
.filter(Objects::isNull)
.collect(Collectors.toList());java
final Integer someVariable = null;
if (someVariable == null) {
// do something
}
List<Integer> lists = new ArrayList<>();
lists.stream()
.filter(Objects::isNull)
.collect(Collectors.toList());❌ Don't
❌ 错误做法
java
final Integer someVariable = null;
if (Objects.isNull(someVariable)) {
// do something
}
List<Integer> lists = new ArrayList<>();
lists.stream()
.filter(p -> p == null)
.collect(Collectors.toList());java
final Integer someVariable = null;
if (Objects.isNull(someVariable)) {
// do something
}
List<Integer> lists = new ArrayList<>();
lists.stream()
.filter(p -> p == null)
.collect(Collectors.toList());Nullability Annotations
空值注解
- Use JSpecify annotations
- Apply and
@Nullableto all methods including private ones@NonNull - Avoid class-level or package-level annotations (Lombok compatibility issues)
- 使用JSpecify注解
- 为所有方法(包括私有方法)添加和
@Nullable注解@NonNull - 避免使用类级或包级注解(存在Lombok兼容性问题)
✅ Do
✅ 正确做法
java
public final class SomeClass {
@Nullable
private final Integer field1;
@NonNull
private final String field2;
@NonNull
public String func() {
return process();
}
@Nullable
private String process() {
if (field1 == null) return null;
return "awesome";
}
}java
public final class SomeClass {
@Nullable
private final Integer field1;
@NonNull
private final String field2;
@NonNull
public String func() {
return process();
}
@Nullable
private String process() {
if (field1 == null) return null;
return "awesome";
}
}❌ Don't
❌ 错误做法
java
public final class SomeClass {
private final Integer field1;
private final String field2;
public String func() {
return process();
}
private String process() {
if (field1 == null) return null;
return "awesome";
}
}java
public final class SomeClass {
private final Integer field1;
private final String field2;
public String func() {
return process();
}
private String process() {
if (field1 == null) return null;
return "awesome";
}
}Package Naming
包命名
Use all lowercase and numbers only, following Google Java Style Guide conventions.
仅使用小写字母和数字,遵循Google Java风格指南的约定。
✅ Do
✅ 正确做法
java
package com.example.project.initscript;java
package com.example.project.initscript;❌ Don't
❌ 错误做法
java
package com.example.project.initScript;java
package com.example.project.initScript;Static Factory Methods
静态工厂方法
Use only naming convention. For multiple types, use format .
ofof<Postfix>仅使用命名约定。对于多种类型,使用的格式。
ofof<后缀>✅ Do
✅ 正确做法
java
public final class SomeClass {
private final int field1;
private SomeClass(int field1) {
this.field1 = field1;
}
public static SomeClass ofDefault() {
return new SomeClass(1);
}
public static SomeClass ofSpecial() {
return new SomeClass(2);
}
}java
public final class SomeClass {
private final int field1;
private SomeClass(int field1) {
this.field1 = field1;
}
public static SomeClass ofDefault() {
return new SomeClass(1);
}
public static SomeClass ofSpecial() {
return new SomeClass(2);
}
}❌ Don't
❌ 错误做法
java
public final class SomeClass {
private final int field1;
private SomeClass(int field1) {
this.field1 = field1;
}
public static SomeClass from() {
return new SomeClass(1);
}
public static SomeClass valueOf() {
return new SomeClass(2);
}
}java
public final class SomeClass {
private final int field1;
private SomeClass(int field1) {
this.field1 = field1;
}
public static SomeClass from() {
return new SomeClass(1);
}
public static SomeClass valueOf() {
return new SomeClass(2);
}
}Resource Management
资源管理
Always use try-with-resources for resources. Never rely on finalizers.
AutoCloseable对于资源,始终使用try-with-resources。永远不要依赖finalizer方法。
AutoCloseableTry-With-Resources
Try-With-Resources
✅ Do
✅ 正确做法
java
public String readFile(@NonNull Path path) throws IOException {
try (var reader = Files.newBufferedReader(path)) {
return reader.lines().collect(Collectors.joining("\n"));
}
}
// Multiple resources
public void copyStream(@NonNull InputStream in, @NonNull OutputStream out) throws IOException {
try (in; out) { // Java 9+: can use already-declared variables
in.transferTo(out);
}
}java
public String readFile(@NonNull Path path) throws IOException {
try (var reader = Files.newBufferedReader(path)) {
return reader.lines().collect(Collectors.joining("\n"));
}
}
// Multiple resources
public void copyStream(@NonNull InputStream in, @NonNull OutputStream out) throws IOException {
try (in; out) { // Java 9+: can use already-declared variables
in.transferTo(out);
}
}❌ Don't
❌ 错误做法
java
public String readFile(@NonNull Path path) throws IOException {
BufferedReader reader = Files.newBufferedReader(path);
try {
return reader.lines().collect(Collectors.joining("\n"));
} finally {
reader.close(); // The original exception may be suppressed if one occurs here
}
}java
public String readFile(@NonNull Path path) throws IOException {
BufferedReader reader = Files.newBufferedReader(path);
try {
return reader.lines().collect(Collectors.joining("\n"));
} finally {
reader.close(); // The original exception may be suppressed if one occurs here
}
}Composition over Inheritance
组合优于继承
Prefer composition over inheritance.
优先使用组合而非继承。
✅ Do
✅ 正确做法
java
public final class SomeFeature {
public void func() { /* ... */ }
}
public final class SomeClass {
private final SomeFeature feature;
public void func2() {
feature.func();
// do something
}
}java
public final class SomeFeature {
public void func() { /* ... */ }
}
public final class SomeClass {
private final SomeFeature feature;
public void func2() {
feature.func();
// do something
}
}❌ Don't
❌ 错误做法
java
public class SomeFeature {
public void func() { /* ... */ }
}
public final class SomeClass extends SomeFeature {
public void func2() {
super.func();
// do something
}
}java
public class SomeFeature {
public void func() { /* ... */ }
}
public final class SomeClass extends SomeFeature {
public void func2() {
super.func();
// do something
}
}Immutable Objects
不可变对象
All objects should use keyword unless needed for extension or framework requirements.
final除非因扩展或框架要求需要,否则所有对象都应使用关键字。
final✅ Do
✅ 正确做法
java
public final class SomeClass {
// ...
}java
public final class SomeClass {
// ...
}❌ Don't
❌ 错误做法
java
public class SomeClass {
// ...
}java
public class SomeClass {
// ...
}Exception Catching
异常捕获
Catch only the minimum necessary exceptions.
仅捕获必要的最少异常。
✅ Do
✅ 正确做法
java
try {
// do something
} catch (IllegalArgumentException e) {
// do catch
}java
try {
// do something
} catch (IllegalArgumentException e) {
// do catch
}❌ Don't
❌ 错误做法
java
try {
// do something
} catch (RuntimeException e) {
// do catch
}java
try {
// do something
} catch (RuntimeException e) {
// do catch
}Implementing AutoCloseable
实现AutoCloseable
When implementing :
AutoCloseable- Make idempotent (safe to call multiple times)
close() - Never throw exceptions from (suppressed exceptions problem)
close() - Log errors instead of throwing them
实现时:
AutoCloseable- 确保方法是幂等的(多次调用安全)
close() - 永远不要从抛出异常(存在异常被抑制的问题)
close() - 记录错误而非抛出异常
✅ Do
✅ 正确做法
java
public final class DatabaseConnection implements AutoCloseable {
@NonNull
private final Connection connection;
private volatile boolean closed = false;
@Override
public void close() {
if (closed) return; // Idempotent: safe to call multiple times
closed = true;
try {
connection.close();
} catch (SQLException e) {
// Log only; do not throw (exceptions in close can suppress the original)
logger.warn("Failed to close connection", e);
}
}
}java
public final class DatabaseConnection implements AutoCloseable {
@NonNull
private final Connection connection;
private volatile boolean closed = false;
@Override
public void close() {
if (closed) return; // Idempotent: safe to call multiple times
closed = true;
try {
connection.close();
} catch (SQLException e) {
// Log only; do not throw (exceptions in close can suppress the original)
logger.warn("Failed to close connection", e);
}
}
}❌ Don't
❌ 错误做法
java
public final class DatabaseConnection implements AutoCloseable {
@NonNull
private final Connection connection;
@Override
public void close() throws SQLException {
connection.close(); // Not idempotent; exception propagates
}
}java
public final class DatabaseConnection implements AutoCloseable {
@NonNull
private final Connection connection;
@Override
public void close() throws SQLException {
connection.close(); // Not idempotent; exception propagates
}
}Date/Time API
日期/时间API
Use (JSR-310) exclusively. and are banned in new code.
java.timejava.util.Datejava.util.Calendar仅使用(JSR-310)。在新代码中禁止使用和。
java.timejava.util.Datejava.util.CalendarType Selection
类型选择
| Use Case | Type | Example |
|---|---|---|
| Storage/transfer (UTC) | | API timestamps, DB storage |
| User display | | Time shown in UI |
| Date only | | Birthdays, expiration dates |
| Time only | | Business hours, alarms |
| Duration | | Elapsed time, date differences |
| 使用场景 | 类型 | 示例 |
|---|---|---|
| 存储/传输(UTC) | | API时间戳、数据库存储 |
| 用户展示 | | UI中显示的时间 |
| 仅日期 | | 生日、到期日 |
| 仅时间 | | 营业时间、闹钟 |
| 时长 | | 经过的时间、日期差 |
✅ Do
✅ 正确做法
java
public final class Event {
@NonNull
private final Instant createdAt; // UTC timestamp
@NonNull
private final LocalDate eventDate; // Date only
@NonNull
private final ZoneId timeZone; // Display time zone
@NonNull
public ZonedDateTime displayTime() {
return createdAt.atZone(timeZone);
}
}Formatter reuse (thread-safe):
java
public final class DateFormats {
// DateTimeFormatter is thread-safe, so reuse as constants
public static final DateTimeFormatter ISO_DATE = DateTimeFormatter.ISO_LOCAL_DATE;
public static final DateTimeFormatter ENGLISH_DATE = DateTimeFormatter.ofPattern("MMM dd, yyyy");
private DateFormats() {}
}java
public final class Event {
@NonNull
private final Instant createdAt; // UTC timestamp
@NonNull
private final LocalDate eventDate; // Date only
@NonNull
private final ZoneId timeZone; // Display time zone
@NonNull
public ZonedDateTime displayTime() {
return createdAt.atZone(timeZone);
}
}格式化器复用(线程安全):
java
public final class DateFormats {
// DateTimeFormatter is thread-safe, so reuse as constants
public static final DateTimeFormatter ISO_DATE = DateTimeFormatter.ISO_LOCAL_DATE;
public static final DateTimeFormatter ENGLISH_DATE = DateTimeFormatter.ofPattern("MMM dd, yyyy");
private DateFormats() {}
}❌ Don't
❌ 错误做法
java
public final class Event {
@NonNull
private final Date createdAt; // Do not use java.util.Date
@NonNull
private final Calendar calendar; // Do not use java.util.Calendar
@NonNull
public String format() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // Not thread-safe
return sdf.format(createdAt);
}
}java
public final class Event {
@NonNull
private final Date createdAt; // Do not use java.util.Date
@NonNull
private final Calendar calendar; // Do not use java.util.Calendar
@NonNull
public String format() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // Not thread-safe
return sdf.format(createdAt);
}
}Legacy Interop (boundary only)
遗留代码互操作(仅在边界层)
When interfacing with legacy APIs that require , convert at the boundary:
Datejava
// Instant → Date (boundary layer only)
Date legacyDate = Date.from(instant);
// Date → Instant (convert immediately on receipt)
Instant instant = legacyDate.toInstant();当与需要的遗留API交互时,仅在边界层进行转换:
Datejava
// Instant → Date (boundary layer only)
Date legacyDate = Date.from(instant);
// Date → Instant (convert immediately on receipt)
Instant instant = legacyDate.toInstant();Additional Guidelines
其他规范
Builder Pattern
建造者模式
Use Lombok-style builders for API consistency.
使用Lombok风格的建造者以保证API一致性。
Variable and Method Naming
变量与方法命名
- Use keyword from JVM 10+
var - Use meaningful variable names
- But avoid too long variable, function, field names
- Method names should be verbs
- Avoid using 'get' prefix except for getters
- 从JVM 10+开始使用关键字
var - 使用有意义的变量名
- 但避免过长的变量、函数、字段名
- 方法名应为动词
- 除了getter方法,避免使用'get'前缀
Camel Case Convention
驼峰命名约定
Apply camel case to mixed-case words and abbreviations (e.g., "MultiNIC" becomes "MultiNic").
对混合大小写的单词和缩写应用驼峰命名法(例如,"MultiNIC"应改为"MultiNic")。
Control Flow Statements
控制流语句
Use one-liner syntax for simple if statements without braces.
对于简单的if语句,使用无大括号的单行语法。
✅ Do
✅ 正确做法
java
if (someCondition) doSomething();java
if (someCondition) doSomething();❌ Don't
❌ 错误做法
java
if (someCondition) {
doSomething();
}java
if (someCondition) {
doSomething();
}Comments
注释
- Use comments only in special cases
- TODO comments should be for immediate tasks
- Avoid unnecessary comments that restate the code
- 仅在特殊情况下使用注释
- TODO注释应针对即时任务
- 避免添加重复代码含义的不必要注释
See Also
另请参阅
Reference Guides
参考指南
For deeper understanding of specific topics:
- references/async.md - CompletableFuture and async programming patterns
- references/javadoc.md - Javadoc conventions and exception documentation
- references/lombok.md - Allowed and banned Lombok annotations
- references/security-resources.md - Security best practices, password handling, SQL injection prevention, PII masking
如需深入了解特定主题:
- references/async.md - CompletableFuture与异步编程模式
- references/javadoc.md - Javadoc规范与异常文档
- references/lombok.md - 允许和禁止使用的Lombok注解
- references/security-resources.md - 安全最佳实践、密码处理、SQL注入防护、PII掩码