杰瑞科技汇

Google Java编码规范有哪些核心要点?

核心理念

在深入细节之前,请记住最重要的两条原则:

Google Java编码规范有哪些核心要点?-图1
(图片来源网络,侵删)
  1. 代码的编写主要是为了给人阅读的,只是顺便让机器执行。 (Code is written to be read by humans, and only incidentally for machines to execute.)
  2. 我们遵循这份规范,不是为了规范而规范,而是为了利用集体的智慧,让所有人的代码看起来都像是同一个人写的。 (We follow these rules not to stifle creativity, but to leverage the collective wisdom of the community to produce code that is readable, maintainable, and consistent.)

格式规范

这部分是最容易统一和自动化的。

大括号

  • 使用 K&R 风格:左大括号与语句同行,右大括号单独成行。

    // 正确
    public long calculate() {
        long sum = 0;
        for (int i = 0; i < 10; i++) {
            sum += i;
        }
        return sum;
    }
    // 错误 (Allman 风格)
    public long calculate()
    {
        // ...
    }
  • 空块:一个空的块状结构可以简洁地写成 ,除非它是一个多语句的 iffor 语句的一部分,在这种情况下,即使它是空的,也应包含注释。

    // 正确
    void doNothing() {}
    // 正确 (带注释)
    void doNothing() {
        // This is intentionally left empty.
    }

缩进

  • 使用 2 个空格进行缩进,不要使用制表符
  • 连续行对齐:当一行代码过长需要换行时,通常在逗号 后换行,并将后续代码缩进一级(2个空格)。
    Method(
        param1, param2, param3,
        param4, param5);

空格

  • 关键字与括号之间:无空格。
    if (condition) { ... }
  • 方法名与左括号之间:无空格。
    MyMethod(param);
  • 二元/三元运算符:在运算符两侧使用空格。
    int sum = a + b;
    String name = (firstName != null) ? firstName : "Unknown";
  • 逗号、分号:后面使用空格。
    int[] arr = {1, 2, 3};
    for (int i = 0; i < 10; i++) { ... }

行长度

  • 软限制为 100 个字符,超过此限制时,应考虑换行。
  • 硬限制为 120 个字符,超过此限制的代码需要经过团队的特殊批准。
  • 例外import 语句、@Annotations 和命令行等无法换行的行可以超过限制。

换行

  • 换行的首要目标是提高可读性

    Google Java编码规范有哪些核心要点?-图2
    (图片来源网络,侵删)
  • 逗号 后换行通常是最佳选择。

  • 运算符前换行通常比在运算符后换行更易读。

    // 优选
    String longName = thisIsAVeryLongVariableName + thisIsAnotherVeryLongVariableName;
    // 可接受
    String longName = thisIsAVeryLongVariableName +
        thisIsAnotherVeryLongVariableName;

命名规范

清晰、一致的命名是代码可读性的基石。

元素 规范 示例
类名 PascalCase (大驼峰) List, HttpRequest
接口名 PascalCase (大驼峰) Runnable, List (接口名通常用名词或形容词)
方法名 camelCase (小驼峰) calculateSum(), onClick()
变量名 camelCase (小驼峰) myVariable, userName
常量名 UPPER_SNAKE_CASE MAX_VALUE, DEFAULT_TIMEOUT
类成员 (非静态) camelCase (小驼峰) myInstance
类成员 (静态) UPPER_SNAKE_CASE static final int MAX_SIZE = 100;
包名 全部小写,点分隔 com.example.myproject
测试类 Test LoginTest, UserServiceTest

额外建议

  • 避免缩写:除非是像 i, j, k 这样的循环变量,或者 max, min, avg 等广为人知的缩写,否则,应使用完整的单词。

    Google Java编码规范有哪些核心要点?-图3
    (图片来源网络,侵删)
    // 不好
    int usrNmb;
    // 好
    int userNumber;
  • 避免使用下划线 _:除了常量和枚举值外,不要在标识符中使用下划线。


Java 语言特性

限制使用 @Override

  • 必须使用:当重写父类或实现接口的方法时,必须使用 @Override 注解。
  • 推荐使用:对于实现接口的方法,也推荐使用 @Override 注解,因为它能清晰地表明实现关系。

捕获空的异常

  • 禁止:不要捕获像 Exception, RuntimeException, Error 这样宽泛的异常。
  • 禁止:不要捕获异常后不做任何处理(只打印日志或 e.printStackTrace()),如果确实不需要处理,应该重新抛出(throw)或包装后重新抛出。

使用标准的异常类型

  • 优先使用 Java 标准库中定义的异常,而不是自己创建异常。
    • IllegalArgumentException: 参数非法。
    • IllegalStateException: 对象状态不正确。
    • NullPointerException: 对象为 null。
    • IndexOutOfBoundsException: 数组或列表越界。

使用运行时异常

  • 除非一个异常是预期调用者必须处理的情况(如文件不存在、网络中断),否则应使用继承自 RuntimeException 的异常(非受检异常),这样可以减少 try-catch 块的嵌套,使代码更简洁。

静态成员访问

  • 使用类名来访问静态成员,而不是通过实例。

    // 好
    boolean flag = MyUtils.isStaticMethodValid();
    // 不好
    MyUtils utils = new MyUtils();
    boolean flag = utils.isStaticMethodValid();

Finalizers (终结器)

  • 避免使用finalize() 方法是不可预测的,并且在性能和安全性方面存在问题,通常有更好的替代方案(如 try-with-resources)。

其他重要规范

@Nullable 和 @NonNull

  • 强烈推荐:使用 @Nullable@NonNull 注解来明确地表示一个变量、参数或返回值是否可以为 null,这能极大地帮助静态分析工具(如 Error Prone)在编译时发现潜在的 NPE 错误。

    // 方法可能返回 null
    @Nullable
    public String getNullableValue() { ... }
    // 参数不能为 null
    public void process(@NonNull String data) { ... }

依赖注入

  • 推荐使用:依赖注入(如通过构造函数注入)优于在类内部 new 一个依赖对象,这降低了类之间的耦合度,使得单元测试更容易。

不可变性

  • 推荐:尽可能创建不可变对象,不可变对象是线程安全的,更容易理解和推理。
  • 一个不可变对象应该满足:
    1. 所有字段都是 final 的。
    2. 对象在创建后,其状态不会发生改变。

最佳实践和原则

避免过度设计

  • YAGNI (You Ain't Gonna Need It):只实现当前需要的功能,不要为了“未来可能用到”而添加不必要的代码。

限制每个文件的顶级类数量

  • 一个文件一个类:一个 .java 文件应该只包含一个顶级类(或接口)。
  • 例外:如果一个文件中包含多个紧密相关的枚举,可以放在同一个文件中。

限制使用 导入

  • 不要使用import com.example.*;,这会降低代码的可读性,因为你无法一眼看出一个类来自哪个具体的包。
  • 正确做法:明确导入每个需要的类。

限制使用原生类型

  • 优先使用包装类:在需要表示“无值”概念的地方,优先使用包装类(如 Integer 而不是 int),因为包装类可以为 null
  • 例外:在性能敏感的代码(如数组、集合)中,可以使用原生类型以提高效率。

如何获取和实施

  1. 官方源码:最新的规范始终在 GitHub 上。
  2. 自动化检查
    • Checkstyle: 可以根据 Google 规范配置,作为构建步骤的一部分自动检查代码格式。
    • Error Prone: 一个编译器插件,可以发现很多潜在的错误,包括 NPE。
    • Spotless / Lombok: 可以在构建时自动格式化代码,确保所有代码风格一致。

遵循这些规范,你的 Java 代码将更加专业、易于维护,并能与其他开发者的代码无缝协作。

分享:
扫描分享到社交APP
上一篇
下一篇