程式碼風格

警告

本文档是针对旧版 SpongeAPI 编写的,目前已不再维护。虽然相应的代码依然能在对应的 API 下工作,但相关政策、方针及链接可能有所变化。请在必要时参阅最新的文档获得相关信息。

我們遵循 Google’s Java Style Guidelines 以及一些補充與更動,詳述於下。

小訣竅

您可以將我們的程式碼風格用於 Eclipse 或 IntelliJ IDEA,使 IDE 正確地為您的程式碼進行排版。請參見 準備開發 以瞭解更多資訊。

  • 行尾

    • 在提交時使用 Unix 行尾(\n)

      • Windows 的 Git 使用者可以用 git config --global core.autocrlf true 來讓 Git 進行自動轉換

  • 欄寬

    • Javadocs:80字元

    • 程式碼:150字元

    • 若對可讀性有所助益,請自由換行

  • 縮排

    • 使用4個空格來縮排,不要只用2個空格

  • 空行

    • 在 class、interface、enum 等宣告的第一個成員之前(例如在 class Example { 之後)以及在最後一個成員之後放置一個空行

  • 檔頭

    • 檔頭必須包含專案的授權協議標頭。使用 licenseFormat Gradle 任務來自動添加。

  • Import

    • Import 必須按照以下順序進行分組,每組之間由一個空行分隔

      • Static import

      • 所有其他 import

      • java import

      • javax import

    • 這與Google的風格不同,因為 import 不是按照 top-level package 分組的,它們都被分在同一個組。

  • 例外

    • 對於要被忽略的例外,將例外變數命名為 ignored

  • 屬性存取

    • 使用 this 存取 所有的 欄位(Field)

  • Javadocs

    • 不要使用 @author

    • 將額外段落包進 <p></p>

    • 在每個「@子句」內的描述中,首字母大寫,即 @param name Player to affect ,不要有句號

程式碼慣例

  • 使用 Optionals 而不是在 API 中回傳 null

  • 接受 null 的方法參數必須註解為 @Nullable (來自 javax.*),預設所有的方法和參數都是 @Nonnull

  • 使用 Google Preconditions 進行 null 和參數檢查。

Gist

雖然我們強烈建議您閱讀 Google 的 Java 慣例,但這兩份文件都相當長。 為了讓您快速入門,下面是格式正確的程式碼範例:

/*
 * This file is part of Sponge, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered.org <https://www.spongepowered.org>
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.example.java;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;
import java.util.Optional;

public class Example {

    private static final Logger log = LoggerFactory.getLogger(Example.class);
    private static final Random random = new Random();
    private final String id = "test";

    /**
     * Returns an identifier approximately half of the time.
     *
     * <p>A static instance of {@link Random} is used to calculate the
     * outcome with a 50% chance.</p>
     *
     * @return The ID, if available
     */
    public Optional<String> resolveId() {
        log.info("ID requested");

        if (random.nextBoolean()) {
            return Optional.of(this.id);
        } else {
            return Optional.empty();
        }
    }

    /**
     * Returns an identifier approximately half of the time.
     *
     * <p>A static instance of {@link Random} is used to calculate the
     * outcome with a 50% chance. If the outcome is to not return the ID,
     * the given fallback ID is returned.</p>
     *
     * @param fallback A fallback name to return
     * @return The ID half of the time, the given fallback the other half
     */
    public String resolveId(String fallback) {
        return resolveId().orElse(fallback);
    }

}