Android 編碼規范全指南

在 Android 開發領域,代碼不僅是功能實現的載體,更是團隊協作與項目迭代的基礎。一套完善的編碼規范,能讓代碼從 “可運行” 升級為 “易維護、可擴展、低風險”。本文基于 Google、Square 等頂尖團隊的實踐經驗,結合國內 Android 開發的實際場景,從核心價值、基礎規范、語言特有規范、組件規范到落地執行,全方位構建 1W 字 + 的詳細編碼指南,助力團隊打造高質量代碼。

一、編碼規范的核心價值與底層邏輯

編碼規范絕非 “格式強迫癥” 的產物,而是經過千萬個項目驗證的 “降本增效” 工具。理解其底層邏輯,才能真正重視并落地執行。

1.1 為什么需要編碼規范?

(1)從 “個人代碼” 到 “團隊資產” 的轉化

一個項目的代碼往往由多名開發者共同編寫,若沒有規范,會出現 “每人一套風格” 的混亂局面:

  • 變量命名:有人用userName,有人用mUser,有人用yonghuXingming;
  • 格式排版:有人用 2 空格縮進,有人用 Tab,有人在大括號前換行;
  • 邏輯組織:有人把網絡請求寫在 Activity,有人寫在工具類。

這種混亂會導致:新人接手需花 30% 時間適應風格,而非理解業務;跨模塊修改時,因風格差異頻繁誤解邏輯。規范的本質是 “統一語言”—— 讓團隊用同一套 “代碼語法” 溝通,將代碼從 “個人作品” 轉化為 “團隊資產”。

(2)降低認知負荷:大腦的 “節能模式”

人類大腦處理信息的能力有限,雜亂的代碼會消耗額外認知資源。例如:

  • 看到a b c這樣的變量名,需逐行追溯其含義;
  • 面對無注釋的復雜邏輯,需反復調試才能理解設計意圖;
  • 格式混亂的代碼,需花費時間梳理結構。

規范通過 “標準化表達” 降低認知負荷:mUserDao一眼可知是用戶數據訪問對象;統一的縮進讓代碼層級一目了然;注釋清晰的邏輯無需反復調試。據 Google 開發者調查,遵循規范的團隊,代碼理解效率提升 40% 以上。

(3)提前規避風險:從 “事后修復” 到 “事前預防”

多數線上問題源于 “不規范的編碼習慣”:

  • Activity中定義靜態變量持有Context,導致內存泄漏;
  • Fragment用構造函數傳參,屏幕旋轉后數據丟失;
  • 網絡請求未在onDestroy中取消,導致 Activity 銷毀后回調崩潰。

規范將這些 “坑” 轉化為 “禁止項”,例如強制Fragment用newInstance傳參、要求網絡請求綁定生命周期。據統計,嚴格執行規范的項目,線上崩潰率可降低 30% 以上。

1.2 優秀編碼規范的三大特征

(1)實用性:基于場景而非 “教條”

好的規范必須結合項目實際。例如:

  • 小團隊快速迭代項目:可簡化注釋要求,優先保證開發效率;
  • 大型商業項目:需嚴格規范異常處理、權限校驗等關鍵環節;
  • 開源項目:必須強化文檔注釋,方便外部開發者使用。

避免 “為規范而規范”—— 例如要求 “所有變量必須加注釋”,反而會導致 “//userName:用戶名” 這樣的無效注釋泛濫。

(2)漸進性:從 “基礎” 到 “進階” 的分層

規范應分層次:

  • 基礎層:命名、格式、注釋(必須嚴格執行);
  • 進階層:邏輯組織、設計模式(團隊達成共識后執行);
  • 優化層:性能優化、可讀性提升(資深開發者引導)。

例如新人入職可先掌握基礎層,避免因規則過多產生抵觸;隨著經驗積累,逐步掌握高階規范。

(3)可執行:有工具輔助而非 “人工檢查”

純靠人工檢查的規范注定失敗。優秀規范需配套工具:

  • 自動格式化:Android Studio 的 Code Style 配置;
  • 靜態檢查:Lint、Checkstyle 自動檢測違規;
  • 代碼審查:將規范納入 PR(Pull Request)檢查清單。

例如通過配置 Android Studio,保存時自動格式化代碼,從源頭避免格式問題。

二、基礎規范:命名、格式與注釋的終極指南

基礎規范是所有開發者的 “共同語言”,需做到 “無歧義、易理解、可驗證”。

2.1 命名規范:讓代碼 “自解釋”

命名的終極目標是 “通過名稱完全理解含義”,無需依賴注釋。以下是各類型元素的命名規則及原理。

(1)包名(Package):體現項目結構的 “地址”

包名是代碼的 “文件夾地址”,需清晰反映模塊劃分,遵循 “從粗到細” 的層級邏輯。

  • 核心規則
  • 全部小寫,禁止下劃線、大寫字母;
  • 以反轉的公司域名開頭(避免重名);
  • 后續按 “項目名→模塊名→功能名” 劃分。
  • 結構示例
 

com.company.app.模塊.功能

  • 電商 APP 示例:
  • com.shop.app.main(主模塊)
  • com.shop.app.goods.detail(商品詳情模塊)
  • com.shop.app.cart(購物車模塊)
  • com.shop.app.user.login(用戶登錄模塊)
  • 常見錯誤
  • 用縮寫導致歧義:com.shop.app.gd(gd可能是 “goods” 或 “guide”);
  • 層級混亂:com.shop.app.login.user(登錄是用戶模塊的子功能,應改為com.shop.app.user.login);
  • 包含版本號:com.shop.app.v2.goods(版本迭代后需大規模修改包名,不合理)。
(2)類名(Class):明確職責的 “身份牌”

類是代碼的基本單元,類名需準確反映其 “職責范圍”,避免模糊表述。

  • 核心規則
  • 采用帕斯卡命名法(PascalCase):每個單詞首字母大寫,無下劃線;
  • 必須包含 “核心職責詞”:如LoginActivity中的 “Login”;
  • 用后綴區分類型:通過統一后綴讓類的角色一目了然。
  • 詳細類型與命名示例

類類型

命名規則

正面示例

反面示例

設計原理

Activity

功能 + Activity

LoginActivity(登錄頁面)、OrderDetailActivity(訂單詳情)

MainActivity(無具體功能)、Activity2(無意義)

明確頁面用途,避免后期維護時需打開類查看內容

Fragment

功能 + Fragment

UserProfileFragment(用戶資料碎片)、CommentListFragment(評論列表)

MyFragment(個人風格)、FragmentA(無意義)

Fragment 可復用,名稱需體現其獨立功能

ViewModel

數據主題 + ViewModel

OrderViewModel(訂單數據)、CartViewModel(購物車數據)

DataViewModel(模糊)、MainVM(縮寫不規范)

明確 ViewModel 管理的數據范圍,與 UI 邏輯分離

數據類(Java)

實體名

User(用戶實體)、OrderInfo(訂單信息)

UserData(冗余,“Data” 可省略)、Info1(無意義)

數據類以實體為核心,無需額外修飾

數據類(Kotlin)

實體名 + 后綴(Entity/DTO)

UserEntity(數據庫實體)、GoodsDTO(網絡傳輸對象)

User(未區分層級)、GoodsData(模糊)

區分數據在存儲、傳輸中的角色,避免混淆

適配器(Adapter)

數據類型 + Adapter

GoodsListAdapter(商品列表)、CommentAdapter(評論項)

MyAdapter(無意義)、ListAdapter(模糊)

明確適配的數據類型,避免復用時錯誤綁定

工具類(Utils)

功能 + Utils/Helper

ToastUtils(Toast 工具)、DateFormatter(日期格式化)

CommonUtils(功能模糊)、Tool(太籠統)

工具類需單一職責,名稱體現具體功能

網絡請求

接口 + Service/Api

UserApiService(用戶相關接口)、PaymentService(支付接口)

HttpService(模糊)、NetClass(不規范)

明確接口所屬業務域,便于后期接口管理

數據庫操作(Dao)

實體 + Dao

UserDao(用戶數據操作)、OrderDao(訂單數據操作)

DbHelper(模糊)、DataAccess(不具體)

清晰對應實體與數據庫操作,符合 ORM 設計思想

  • 特殊類命名:枚舉與接口
  • 枚舉(Enum):帕斯卡命名,用 “狀態 / 類型” 相關詞,如OrderStatus(訂單狀態)、PaymentMethod(支付方式);
  • 接口(Interface):功能 + able/er,如Downloadable(可下載的)、DataProvider(數據提供器);避免I前綴(如IUser),Google 規范已摒棄此風格。
(3)方法名(Method):“動詞 + 賓語” 的精準表達

方法是執行具體操作的單元,命名需讓讀者在不看實現的情況下,知道 “做什么”“輸入什么”“輸出什么”。

  • 核心規則
  • 駝峰命名法(camelCase):首字母小寫,后續單詞首字母大寫;
  • 以動詞開頭:明確操作類型(如get“獲取”、set“設置”);
  • 包含核心賓語:明確操作對象(如getUserById中的 “User”)。
  • 詳細場景與命名示例

操作類型

動詞選擇

正面示例

反面示例

設計原理

獲取數據

get(直接獲取)、load(加載,可能耗時)、fetch(遠程獲取)

getUserById(String id)(根據 ID 獲取用戶)、loadOrderList()(加載訂單列表)

getData(int a)(模糊)、get1()(無意義)

區分數據來源(內存 / 本地 / 遠程),便于理解性能特性

設置數據

set(直接設置)、update(部分更新)

setUserName(String name)(設置用戶名)、updateOrderStatus(int status)(更新訂單狀態)

change(String s)(模糊)、set2(String x)(無意義)

區分 “全量設置” 與 “部分更新”,避免誤用

提交 / 保存

save(保存到本地)、submit(提交到遠程)、commit(確認事務)

saveUserToDb(User user)(保存到數據庫)、submitOrder(Order order)(提交訂單)

send(User u)(模糊)、saveData(Object o)(類型不明確)

區分數據流向(本地 / 遠程),避免數據存儲錯誤

點擊事件

on + 事件源 + 動作

onLoginButtonClick(View view)(登錄按鈕點擊)、onItemSelected(int position)(列表項選中)

click(View v)(無事件源)、onClick1(View v)(無意義)

明確事件觸發源,便于調試時定位交互邏輯

判斷邏輯

is(是否符合狀態)、has(是否擁有)、can(是否可以)

isUserLoggedIn()(用戶是否已登錄)、hasPermission(String permission)(是否有權限)

check()(模糊)、judge()(不具體)

布爾方法用明確前綴,一眼可知返回值含義

數據轉換

parse(解析)、convert(轉換)、format(格式化)

parseJsonToUser(String json)(JSON 轉 User)、formatDate(Date date)(日期格式化)

change(String s)(模糊)、trans(Object o)(不具體)

明確轉換前后的類型,避免類型錯誤

  • 方法參數與返回值命名
    • 參數名:需包含 “類型 + 含義”,如getUserById(String userId)(而非getUserById(String id));
    • 返回值:布爾方法需包含 “判斷結果”,如isUserNameValid()(而非checkUserName())。
(4)變量與常量:精準描述 “數據內容”

變量與常量是代碼中最基礎的 “數據載體”,命名需讓讀者立刻知道 “存儲的是什么數據”。

  • 變量命名規則

變量類型

命名規則

正面示例

反面示例

設計原理

成員變量(Java)

m + 駝峰(m 表示 member)

mUserDao(用戶數據訪問對象)、mLoginStatus(登錄狀態)

userDao(未加前綴)、mX(無意義)

區分成員變量與局部變量,避免命名沖突

成員變量(Kotlin)

駝峰(無需前綴)

userDao、loginStatus

mUserDao(冗余,Kotlin 不推薦)、a(無意義)

Kotlin 通過語法區分作用域,無需前綴

局部變量

駝峰(簡潔明了)

currentPosition(當前位置)、tempUser(臨時用戶對象)

i(需追溯含義)、data(模糊)

局部變量作用域小,以 “當前語境下的含義” 為核心

集合變量

復數形式

users(用戶列表)、orders(訂單集合)

userList(冗余,“List” 可省略)、dataArray(模糊)

復數形式直觀體現 “多個元素”,比加 “List” 更簡潔

布爾變量

is/has/can + 狀態

isLoggedIn(是否已登錄)、hasUnreadMessages(是否有未讀消息)

login(非動詞)、flag(完全模糊)

布爾變量需明確 “判斷的狀態”,避免邏輯反轉錯誤

  • 常量命名規則
  • 全部大寫,下劃線分隔單詞;
  • 必須包含 “領域 + 具體值”;
  • 避免魔法數字(直接寫數字而不定義常量)。

常量類型

命名規則

正面示例

反面示例

設計原理

通用常量

領域 + 值描述

MAX_LOGIN_ATTEMPTS = 5(最大登錄嘗試次數)、DEFAULT_PAGE_SIZE = 20(默認分頁大小)

MAX = 5(無領域)、NUM1 = 20(無意義)

明確常量的適用場景,避免修改時影響無關邏輯

狀態碼

類型 + 狀態 + CODE

ORDER_STATUS_PAID = 1(訂單已支付)、NETWORK_ERROR_CODE = -1(網絡錯誤)

STATUS1 = 1(無狀態描述)、CODE = -1(模糊)

狀態碼需與業務含義綁定,避免調試時查文檔

路徑 / 鍵名

類型 + 名稱

PREFERENCE_USER_ID = "user_id"(偏好設置中的用戶 ID 鍵)、URL_LOGIN = "https://api/login"(登錄接口 URL)

KEY1 = "id"(無含義)、URL = "..."(模糊)

明確鍵的用途,避免存儲 / 讀取時鍵名錯誤

2.2 格式規范:讓代碼 “賞心悅目” 的排版邏輯

格式規范的核心是 “視覺一致性”—— 通過統一的排版,讓代碼的結構 “可視化”,減少閱讀時的視覺疲勞。

(1)縮進與換行:層級清晰的 “視覺骨架”
  • 縮進規則
  • 統一使用 4 個空格(而非 Tab):Android Studio 默認配置(Settings→Editor→Code Style→Java→Tabs and Indents);
  • 每個代碼塊(如if for class)縮進一次:子邏輯在父邏輯右側 4 個空格處;
  • 禁止 “混合縮進”(部分用空格,部分用 Tab):會導致不同編輯器顯示不一致。
  • 換行規則
  • 左大括號{必須緊跟語句,不單獨成行:
    // 正確
    if (isLogin) {// 邏輯
    }// 錯誤
    if (isLogin)
    {// 邏輯
    }

設計原理:左大括號與語句同行,可減少垂直空間占用,同時明確歸屬關系。

  • 方法之間必須空一行:
    // 正確
    public void login() {// 登錄邏輯
    }public void logout() {// 退出邏輯
    }// 錯誤(無空行)
    public void login() {// 登錄邏輯
    }
    public void logout() {// 退出邏輯
    }

設計原理:方法是獨立功能單元,空行分隔可明確邊界,便于快速定位。

  • 長語句必須換行(超過 120 字符):
    // 正確(鏈式調用換行)
    User user = userApiService.getUserById(userId).setName("新名稱").setAge(20);// 正確(參數過多換行)
    submitOrder(orderId,userId,Arrays.asList(product1, product2),new PayCallback() { ... }
    );// 錯誤(超長語句不換行)
    User user = userApiService.getUserById(userId).setName("新名稱").setAge(20);

  • 邏輯塊之間空一行:
    // 正確
    public void processOrder() {// 第一步:校驗參數if (order == null) {return;}// 第二步:查詢庫存int stock = stockDao.query(order.getProductId());// 第三步:更新訂單狀態if (stock > 0) {order.setStatus(ORDER_STATUS_PAID);} else {order.setStatus(ORDER_STATUS_OUT_OF_STOCK);}
    }// 錯誤(無空行,邏輯塊混淆)
    public void processOrder() {if (order == null) {return;}int stock = stockDao.query(order.getProductId());if (stock > 0) {order.setStatus(ORDER_STATUS_PAID);} else {order.setStatus(ORDER_STATUS_OUT_OF_STOCK);}
    }

設計原理:按邏輯步驟分隔,便于理解代碼的執行流程。

(2)括號與空格:消除 “視覺噪音” 的細節處理
  • 括號規則
  • if for while等關鍵字后必須加空格,再跟(:
    // 正確
    if (isLogin) { ... }
    for (int i = 0; i < 10; i++) { ... }// 錯誤(無空格)
    if(isLogin) { ... }
    for(int i = 0; i < 10; i++) { ... }

設計原理:關鍵字與括號間的空格,可區分 “語法關鍵字” 與 “方法調用”(如if(易誤讀為方法)。

  • 方法調用的(前無空格:
    // 正確
    getUserById(userId);
    Toast.makeText(context, "提示", Toast.LENGTH_SHORT).show();// 錯誤(有空格)
    getUserById (userId);
    Toast.makeText (context, "提示", Toast.LENGTH_SHORT).show();

設計原理:區分 “關鍵字” 與 “方法”,保持調用語法的一致性。

  • 空格規則
  • 二元運算符(+ - = ==等)前后必須加空格:
    // 正確
    int total = price + count * 2;
    if (a == b && c > d) { ... }// 錯誤(無空格)
    int total=price+count*2;
    if (a==b&&c>d) { ... }

設計原理:運算符前后空格可增強表達式的可讀性,避免因運算符密集導致誤讀。

  • 逗號,后必須加空格:
    // 正確
    getUser(id, name, age);
    String[] fruits = {"apple", "banana", "orange"};// 錯誤(無空格)
    getUser(id,name,age);
    String[] fruits = {"apple","banana","orange"};

設計原理:分隔參數或元素,避免視覺上的 “粘連”。

  • 類型轉換后的(后不加空格:
    // 正確
    String str = (String) object;// 錯誤(有空格)
    String str = (String)  object;

設計原理:類型轉換是一個整體操作,避免空格破壞連貫性。

(3)空行與對齊:劃分邏輯單元的 “視覺分隔”
  • 空行規則
  • 類成員之間空一行(靜態變量與實例變量、方法與方法):
    public class UserManager {private static final String TAG = "UserManager";private UserDao mUserDao;public UserManager(UserDao userDao) {mUserDao = userDao;}public User getUser(String id) {return mUserDao.query(id);}
    }

設計原理:區分類的不同成員,避免代碼 “堆在一起”。

  • 同一方法內的邏輯塊之間空一行:
    public void login(String username, String password) {// 第一步:校驗參數if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {throw new IllegalArgumentException("用戶名或密碼為空");}// 第二步:調用登錄接口User user = userApi.login(username, password);// 第三步:保存用戶信息if (user != null) {saveUserToLocal(user);}
    }

設計原理:按執行步驟分隔,便于理解方法的執行流程。

  • 禁止連續空行(最多空一行):
    // 錯誤(連續空行)
    public void method1() { ... }public void method2() { ... }

設計原理:過多空行會增加滾動距離,降低閱讀效率。

  • 對齊規則(可選)
  • 賦值語句可垂直對齊(非強制,但團隊內需統一):
    // 推薦(對齊后更美觀)
    private String mUserName = "default";
    private int    mUserAge  = 18;
    private boolean mIsVip   = false;// 允許(但不一致)
    private String mUserName = "default";
    private int mUserAge = 18;
    private boolean mIsVip = false;

設計原理:對齊可增強變量初始化的視覺一致性,但需避免為對齊添加過多空格。

2.3 注釋規范:代碼的 “補充說明” 而非 “重復描述”

注釋的核心是 “補充代碼無法表達的信息”,而非重復代碼邏輯。好的注釋應回答 “為什么這么做”,而非 “做了什么”。

(1)類注釋:類的 “說明書”

每個類必須有類注釋,說明其核心職責、設計意圖、使用場景等 “宏觀信息”。

  • 核心要素
  • 功能描述:該類的核心作用(1-2 句話);
  • 核心邏輯:關鍵實現思路(如 “通過本地緩存 + 網絡請求實現數據獲取”);
  • 注意事項:使用時的限制(如 “需先調用 init () 方法”);
  • 作者與日期(可選,大型項目推薦)。
  • 示例(Java)
    /*** 用戶登錄邏輯處理類* * 核心功能:* 1. 校驗登錄參數(用戶名/密碼格式)* 2. 調用登錄接口(支持普通登錄/驗證碼登錄)* 3. 登錄成功后保存用戶信息到SP和數據庫* * 設計思路:* - 采用策略模式,區分不同登錄方式(普通/驗證碼)* - 登錄結果通過回調返回,避免阻塞UI線程* * 注意事項:* - 必須在Application初始化后使用(依賴全局Context)* - 登錄過程中調用cancel()可取消請求* * @author 張三* @date 2024-05-10*/
    public class LoginManager {// 類內容
    }

  • 示例(Kotlin)
    /*** 商品列表數據管理ViewModel* * 負責從Repository獲取商品數據,并暴露給UI層:* - 支持下拉刷新(forceRefresh=true)* - 支持上拉加載更多(分頁加載)* - 數據變化通過goodsLiveData通知UI* * 數據流程:* UI觸發加載 → ViewModel調用Repository → Repository返回數據 → ViewModel更新LiveData* * 注意:* - 調用loadGoods()前需設置categoryId(商品分類ID)*/
    class GoodsListViewModel : ViewModel() {// 類內容
    }

  • 常見錯誤
  • 無注釋:新人需通讀代碼才能理解類的作用;
  • 重復代碼:如 “用戶管理類,用于管理用戶”(無實際信息);
  • 過時注釋:類邏輯修改后,注釋未更新,導致誤解。
(2)方法注釋:方法的 “使用手冊”

公共方法(尤其是對外暴露的 API)必須有注釋,說明參數含義、返回值、異常情況等 “使用細節”。

  • 核心要素
  • 功能描述:方法的核心作用(如 “根據用戶 ID 獲取用戶信息”);
  • 參數說明:每個參數的含義、約束(如 “userId:非空,長度為 11 位”);
  • 返回值說明:返回數據的含義(如 “User:用戶信息,null 表示用戶不存在”);
  • 異常說明:可能拋出的異常及觸發條件(如 “NetworkException:網絡不可用時拋出”)。
  • 示例(Java)
    /*** 根據用戶ID查詢用戶信息* * @param userId 用戶唯一標識(非空,必須為11位數字字符串)* @param forceRefresh 是否強制刷新(true:忽略本地緩存,直接請求網絡;false:優先返回緩存)* @return User 用戶完整信息(包含姓名、頭像、手機號等),null表示用戶不存在* @throws IllegalArgumentException 當userId為空或格式錯誤時拋出* @throws NetworkException 當forceRefresh=true且網絡不可用時拋出*/
    public User getUserById(String userId, boolean forceRefresh) throws NetworkException {// 方法內容
    }

  • 示例(Kotlin)
    /*** 提交訂單并獲取支付鏈接* * @param order 訂單信息(必須包含商品ID、數量、收貨地址)* @param payType 支付方式(1:微信支付,2:支付寶,其他值會拋出異常)* @return String 支付鏈接(有效期30分鐘)* @throws OrderException 訂單校驗失敗時拋出(如庫存不足)*/
    fun submitOrder(order: Order, payType: Int): String {// 方法內容
    }

  • 簡化規則
  • 私有方法:若邏輯簡單,可無注釋;若邏輯復雜,需加邏輯注釋;
  • 簡單方法:如getUserName(),可僅用一行注釋:
    /** 獲取用戶名(從當前登錄用戶中讀取) */
    public String getUserName() { ... }

(3)邏輯注釋:復雜邏輯的 “解密鑰匙”

當代碼邏輯因 “特殊需求”“性能優化”“歷史兼容” 等原因偏離常規時,必須用邏輯注釋說明 “為什么這么做”。

  • 必須添加邏輯注釋的場景

場景

示例

設計原理

特殊業務邏輯

java // 為什么減去1? // 因服務器返回的索引從1開始,客戶端需轉為0開始的索引 int position = serverIndex - 1;

解釋業務規則,避免后期修改時誤刪 “減 1” 操作

性能優化

java // 為什么用SparseArray而非HashMap? // 因key為int類型,SparseArray內存效率更高 SparseArray<User> userMap = new SparseArray<>();

說明優化依據,避免他人改為 “更熟悉” 但性能差的實現

兼容處理

java // 為什么加版本判斷? // 因API 23以下不支持setBackgroundTintList方法 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { view.setBackgroundTintList(tint); } else { // 低版本兼容邏輯 }

解釋兼容原因,避免后期刪除低版本邏輯導致崩潰

臨時解決方案

java // TODO:臨時方案(2024-06-30前修復) // 因服務器返回的日期格式錯誤(少了時區),暫時手動添加"+8" String correctTime = serverTime + "+08:00";

標記臨時邏輯,提醒后續優化,避免成為 “永久臨時方案”

  • 禁止添加的無意義注釋
    // 錯誤示例1:重復代碼
    int count = 0; // 初始化計數為0// 錯誤示例2:顯而易見的邏輯
    // 循環10次
    for (int i = 0; i < 10; i++) { ... }// 錯誤示例3:廢話注釋
    // 用戶管理類
    public class UserManager { ... }

2.4 常見格式問題與自動化工具

(1)高頻格式錯誤及修正

錯誤類型

錯誤示例

正確示例

修正工具

縮進不一致

java if (a > b) { int c = 1; int d = 2; // 縮進錯誤 }

java if (a > b) { int c = 1; int d = 2; // 正確縮進 }

Android Studio:Code→Reformat Code

大括號位置錯誤

java if (a > b) { ... } (正確示例應為左大括號緊跟)

見上文縮進規則

同上

空行過多

java public void method1() { ... } public void method2() { ... }

方法間只空一行

同上

運算符無空格

java int a=1+2;

java int a = 1 + 2;

同上

(2)自動化格式化工具
  • Android Studio 內置格式化
  • 快捷鍵:Ctrl+Alt+L(Windows)/ Cmd+Option+L(Mac);
  • 配置路徑:File→Settings→Editor→Code Style→Java/Kotlin,可導入團隊統一配置。
  • 格式化時機
  • 提交代碼前必須執行格式化;
  • 大型重構后執行格式化;
  • 推薦配置 “保存時自動格式化”(Settings→Editor→General→Save Files On Frame Deactivation→Format file)。

三、Java 特有編碼規范

Java 作為 Android 開發的傳統語言,有其特有的編碼陷阱與最佳實踐,需針對性規范。

3.1 類與對象設計:避免 “過度設計” 與 “設計不足”

(1)類的單一職責原則

一個類應只負責一項職責,避免 “萬能類”。例如:

  • 反面示例
    // 錯誤:一個類承擔過多職責(UI、網絡、數據存儲)
    public class UserActivity extends AppCompatActivity {private TextView mNameView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_user);mNameView = findViewById(R.id.tv_name);// 職責1:UI初始化mNameView.setOnClickListener(v -> { ... });// 職責2:網絡請求new Thread(() -> {String result = HttpUtil.get("https://api/user");// 更新UI}).start();// 職責3:數據存儲SharedPreferences sp = getSharedPreferences("user", MODE_PRIVATE);sp.edit().putString("name", "張三").apply();}
    }

  • 正面示例
    // 正確:拆分職責
    public class UserActivity extends AppCompatActivity {private UserViewModel mViewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 僅負責UI相關邏輯mViewModel = new ViewModelProvider(this).get(UserViewModel.class);mViewModel.getUser().observe(this, user -> {updateUI(user);});}private void updateUI(User user) { ... }
    }// 數據邏輯
    public class UserViewModel extends ViewModel {private UserRepository mRepository;public LiveData<User> getUser() {return mRepository.loadUser();}
    }// 數據獲取與存儲
    public class UserRepository {public LiveData<User> loadUser() {// 網絡請求+本地存儲邏輯}
    }

設計原理:單一職責可降低類的復雜度,便于測試和復用 —— 例如修改網絡請求邏輯時,無需改動 UI 代碼。

(2)構造方法與初始化
  • 禁止在構造方法中做耗時操作
    // 錯誤
    public class UserManager {private User mUser;public UserManager() {// 構造方法中做網絡請求(耗時)mUser = HttpUtil.get("https://api/user");}
    }

問題:構造方法被調用時(如new UserManager()),若耗時會阻塞當前線程(如 UI 線程導致 ANR)。

正確做法:提供初始化方法,在合適時機調用:

public class UserManager {private User mUser;public UserManager() {// 僅做簡單初始化}// 單獨的初始化方法public void init() {new Thread(() -> {mUser = HttpUtil.get("https://api/user");}).start();}
}
  • 避免在構造方法中依賴外部狀態
    // 錯誤
    public class OrderManager {public OrderManager() {// 依賴全局狀態,導致測試困難if (AppConfig.isDebug()) {// 調試邏輯}}
    }

正確做法:通過參數傳入依賴,而非直接依賴全局狀態:

public class OrderManager {private boolean mIsDebug;// 通過構造方法傳入依賴,便于測試(可傳入mock值)public OrderManager(boolean isDebug) {mIsDebug = isDebug;}
}

3.2 異常處理:從 “崩潰” 到 “可控”

Java 的異常處理是保證程序穩定性的關鍵,需避免 “吞噬異常” 或 “粗暴處理”。

(1)必須捕獲并處理異常
  • 禁止空 catch 塊
    // 錯誤:吞噬異常,導致問題無法排查
    try {String json = readFile("user.json");User user = new Gson().fromJson(json, User.class);
    } catch (Exception e) {// 空catch塊,無任何處理
    }

  • 正確處理方式
    try {String json = readFile("user.json");User user = new Gson().fromJson(json, User.class);
    } catch (FileNotFoundException e) {// 特定異常:文件不存在,可創建默認文件createDefaultFile();Log.e("UserManager", "用戶文件不存在,已創建默認文件", e);
    } catch (JsonSyntaxException e) {// 特定異常:JSON格式錯誤,提示用戶showErrorToast("數據格式錯誤,請重新登錄");Log.e("UserManager", "JSON解析失敗", e);
    } catch (Exception e) {// 其他異常:記錄日志,避免崩潰Log.e("UserManager", "未知錯誤", e);// 可選:上報異常到監控平臺ExceptionReporter.report(e);
    }

設計原理:不同異常有不同處理方式,需針對性處理;即使無法恢復,也需記錄日志便于排查。

(2)異常傳遞與封裝
  • 避免 “異常鏈斷裂”
    // 錯誤:丟失原始異常信息,難以定位根因
    try {// 數據庫操作
    } catch (SQLException e) {// 僅拋出新異常,未攜帶原始異常throw new BusinessException("數據操作失敗");
    }

  • 正確傳遞異常
    try {// 數據庫操作
    } catch (SQLException e) {// 攜帶原始異常,保留堆棧信息throw new BusinessException("數據操作失敗", e);
    }

  • 封裝底層異常

對調用者暴露 “業務異常”,隱藏底層實現(如數據庫、網絡):

// 底層異常(數據庫)
public class DbException extends Exception { ... }// 業務異常(對上層暴露)
public class UserNotFoundException extends BusinessException { ... }// 封裝邏輯
public User getUser() throws UserNotFoundException {try {return db.queryUser();} catch (DbException e) {// 轉換為業務異常throw new UserNotFoundException("用戶不存在", e);}
}

設計原理:上層調用者無需關心底層實現(如用數據庫還是網絡),只需處理業務異常。

3.3 集合與數組:避免 “隱性錯誤”

(1)集合初始化與使用
  • 指定初始容量
    // 正確:已知大小,指定初始容量(減少擴容次數)
    List<User> users = new ArrayList<>(100); // 預計存儲100個用戶// 錯誤:默認容量(10),存儲100個元素需多次擴容
    List<User> users = new ArrayList<>();

  • 禁止在循環中修改集合
    // 錯誤:遍歷中刪除元素會拋出ConcurrentModificationException
    List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
    for (String s : list) {if (s.equals("b")) {list.remove(s);}
    }

  • 正確方式
    // 方式1:用迭代器刪除
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {if (iterator.next().equals("b")) {iterator.remove(); // 安全刪除}
    }// 方式2:用Stream過濾(Java 8+)
    List<String> newList = list.stream().filter(s -> !s.equals("b")).collect(Collectors.toList());

(2)數組使用規范
  • 優先用集合而非數組
    // 推薦:集合支持動態擴容、便捷操作
    List<String> names = new ArrayList<>();
    names.add("張三");
    names.contains("張三");// 不推薦:數組長度固定,操作繁瑣
    String[] names = new String[10];
    names[0] = "張三";
    // 判斷是否包含需手動循環

  • 數組轉集合的坑
    // 錯誤:Arrays.asList返回的是固定大小集合,不能添加/刪除
    List<String> list = Arrays.asList("a", "b", "c");
    list.add("d"); // 拋出UnsupportedOperationException// 正確:轉為可修改的ArrayList
    List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));

3.4 線程與并發:避免 “線程安全” 問題

(1)禁止在 UI 線程做耗時操作
  • 錯誤示例
    // 錯誤:在主線程做網絡請求(導致ANR)
    public void onClick(View view) {String result = HttpUtil.get("https://api/data"); // 耗時操作updateUI(result);
    }

  • 正確示例
    public void onClick(View view) {// 開啟子線程new Thread(() -> {String result = HttpUtil.get("https://api/data");// 切回主線程更新UIrunOnUiThread(() -> updateUI(result));}).start();
    }

(2)線程安全與同步
  • 共享變量需同步
    // 錯誤:多線程修改共享變量,可能導致數據不一致
    public class Counter {private int count = 0;public void increment() {count++; // 非原子操作,多線程下可能出錯}
    }

  • 正確方式
    public class Counter {private int count = 0;// 方法同步public synchronized void increment() {count++;}// 或用原子類(更高效)private AtomicInteger atomicCount = new AtomicInteger(0);public void atomicIncrement() {atomicCount.incrementAndGet();}
    }

四、Kotlin 特有編碼規范

Kotlin 作為 Android 開發的推薦語言,其空安全、擴展函數等特性需正確使用才能發揮優勢。

4.1 空安全:從 “防崩潰” 到 “代碼清晰”

(1)非空與可空的正確使用
  • 優先聲明非空類型
    // 正確:已知非空,聲明為非空
    val userName: String = "張三"// 錯誤:可空類型但實際非空,增加調用成本
    val userName: String? = "張三" // 無需用可空

  • 可空類型必須處理空值
    // 正確:安全處理可空類型
    fun getUserAge(user: User?): Int {// 方式1:?.let(非空才執行)user?.let {return it.age}// 方式2:?:(空值默認)return user?.age ?: 0
    }// 錯誤:可空類型未處理,可能拋出NPE
    fun getUserAge(user: User?): Int {return user.age // 編譯錯誤(Kotlin強制檢查)
    }

  • 禁止濫用!!非空斷言
    // 錯誤:用!!強制非空,等同于回到Java的NPE風險
    fun getUserAge(user: User?): Int {return user!!.age // 若user為空,拋出NPE
    }

替代方案:明確處理空值,或重新設計類型(是否真的需要可空)。

(2)空安全的高級技巧
  • isNullOrEmpty判斷空集合
    // 推薦:Kotlin擴展函數,簡潔明了
    if (userList.isNullOrEmpty()) {// 空處理
    }// 不推薦:Java風格判斷
    if (userList == null || userList.isEmpty()) { ... }

  • requireNotNull做參數校驗
    fun login(username: String?, password: String?) {// 校驗非空,為空則拋出異常(帶明確信息)val name = requireNotNull(username) { "用戶名不能為空" }val pwd = requireNotNull(password) { "密碼不能為空" }// 后續可安全使用非空變量
    }

4.2 函數與屬性:簡潔而不晦澀

(1)函數簡化與可讀性平衡
  • 單表達式函數的使用
    // 正確:簡單邏輯用單表達式,簡潔
    fun add(a: Int, b: Int) = a + b// 錯誤:復雜邏輯用單表達式,可讀性差
    fun calculate(a: Int, b: Int) = if (a > b) a * 2 else (b - a) / 3 + 5 // 邏輯復雜應拆分

  • 默認參數替代重載
    // 正確:默認參數替代多個重載函數
    fun getUser(id: String,forceRefresh: Boolean = false,timeout: Int = 5000
    ) { ... }// 錯誤:Java風格重載,代碼冗余
    fun getUser(id: String) = getUser(id, false)
    fun getUser(id: String, forceRefresh: Boolean) = getUser(id, forceRefresh, 5000)
    fun getUser(id: String, forceRefresh: Boolean, timeout: Int) { ... }

(2)擴展函數與屬性
  • 擴展函數的合理范圍
    // 正確:通用功能,擴展給View
    fun View.setVisible(visible: Boolean) {visibility = if (visible) View.VISIBLE else View.GONE
    }// 錯誤:業務邏輯放入擴展函數,導致擴散
    fun View.showUserInfo(user: User) {// 業務邏輯應放在ViewModel或Presenter(this as TextView).text = user.name
    }

  • 避免擴展函數命名沖突
    // 風險:不同模塊對同一類擴展同名函數
    // 模塊A
    fun String.formatUser(): String { ... }
    // 模塊B
    fun String.formatUser(): String { ... } // 沖突

解決:添加前綴區分(如formatUserInfo),或放入不同包名。

五、Android 組件特有規范

Android 組件(Activity、Fragment 等)有其生命周期特性,規范需結合生命周期設計。

5.1 Activity 規范:頁面的 “生命周期管理”

(1)生命周期與初始化
  • 初始化放onCreate,資源釋放放onDestroy
    public class MainActivity extends AppCompatActivity {private TextView mTitleView;private BroadcastReceiver mReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 初始化視圖setContentView(R.layout.activity_main);mTitleView = findViewById(R.id.tv_title);// 初始化數據initData();// 注冊廣播(在onCreate注冊)mReceiver = new MyReceiver();registerReceiver(mReceiver, intentFilter);}@Overrideprotected void onDestroy() {super.onDestroy();// 釋放資源(與onCreate對應)unregisterReceiver(mReceiver); // 解注冊// 取消網絡請求if (mCall != null) {mCall.cancel();}}
    }

  • 禁止在onResume做初始化
    // 錯誤:onResume會多次調用(如鎖屏后解鎖),導致重復初始化
    @Override
    protected void onResume() {super.onResume();// 錯誤:每次可見都初始化(應放onCreate)mAdapter = new UserAdapter();
    }

(2)避免內存泄漏
  • 禁止靜態引用 Activity/View
    // 錯誤:靜態引用導致Activity無法回收
    public class LeakActivity extends AppCompatActivity {// 靜態引用Activitypublic static LeakActivity sInstance;// 靜態引用View(持有Activity引用)private static TextView sTitleView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);sInstance = this; // 危險sTitleView = findViewById(R.id.tv_title); // 危險}
    }

  • 內部類使用弱引用
    // 正確:內部類用弱引用避免泄漏
    public class SafeActivity extends AppCompatActivity {private MyHandler mHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mHandler = new MyHandler(this);}// 靜態內部類(不持有外部類引用)private static class MyHandler extends Handler {private WeakReference<SafeActivity> mActivityRef;public MyHandler(SafeActivity activity) {mActivityRef = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {SafeActivity activity = mActivityRef.get();if (activity != null && !activity.isFinishing()) {// 安全操作}}}
    }

5.2 Fragment 規范:可復用的 “迷你頁面”

(1)創建與傳參
  • 必須用newInstance傳參
    // 正確:用newInstance+Bundle傳參
    public class UserFragment extends Fragment {private static final String ARG_USER_ID = "user_id";private String mUserId;// 工廠方法public static UserFragment newInstance(String userId) {UserFragment fragment = new UserFragment();Bundle args = new Bundle();args.putString(ARG_USER_ID, userId);fragment.setArguments(args);return fragment;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 從Arguments獲取參數if (getArguments() != null) {mUserId = getArguments().getString(ARG_USER_ID);}}
    }// 使用方式
    UserFragment fragment = UserFragment.newInstance("123");

  • 禁止用構造函數傳參
    // 錯誤:屏幕旋轉后參數丟失(Fragment重建時用默認構造)
    public class BadFragment extends Fragment {private String mUserId;// 錯誤:非默認構造,重建時參數丟失public BadFragment(String userId) {mUserId = userId;}
    }

(2)視圖與生命周期
  • 視圖初始化放onViewCreated
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// 僅加載布局,不做視圖操作return inflater.inflate(R.layout.fragment_user, container, false);
    }@Override
    public void onViewCreated(View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);// 視圖初始化(在onViewCreated中操作View)mNameView = view.findViewById(R.id.tv_name);mNameView.setOnClickListener(v -> { ... });// 加載數據loadData();
    }

  • 視圖銷毀清理
    @Override
    public void onDestroyView() {super.onDestroyView();// 清理視圖引用(避免內存泄漏)mNameView = null;// 取消視圖相關任務(如圖片加載)if (mImageRequest != null) {mImageRequest.cancel();}
    }

5.3 ViewModel 與數據管理:UI 與數據的 “解耦”

(1)ViewModel 設計
  • ViewModel 不持有 UI 引用
    // 錯誤:ViewModel持有Activity引用
    class BadViewModel(private val activity: Activity) : ViewModel() {fun updateUI() {activity.findViewById<TextView>(R.id.tv_name).text = "更新"}
    }// 正確:通過LiveData與UI通信
    class GoodViewModel : ViewModel() {private val _userName = MutableLiveData<String>()val userName: LiveData<String> = _userNamefun loadUser() {// 加載數據后更新LiveData_userName.value = "張三"}
    }

  • 數據請求放 Repository
    // 正確:ViewModel僅管理數據,不做具體請求
    class UserViewModel(private val repository: UserRepository) : ViewModel() {fun getUser(id: String) {viewModelScope.launch {val user = repository.getUser(id) // 具體請求在Repository_user.value = user}}
    }// Repository負責數據獲取
    class UserRepository {suspend fun getUser(id: String): User {return api.getUser(id) // 網絡請求}
    }

六、規范落地:從 “文檔” 到 “習慣”

編碼規范的關鍵在于 “落地執行”,否則只是一紙空文。

6.1 團隊規范制定流程

1.收集現有問題:分析團隊現有代碼的高頻問題(如命名混亂、格式不統一);

2.制定核心規則:優先規范 “必須執行” 的基礎規則(命名、格式);

3.工具配置:將規則配置到 Android Studio、CI 流程中;

4.培訓與示例:通過示例代碼、常見錯誤對比培訓團隊;

5.定期 Review:代碼審查時將規范作為必查項,持續優化規則。

6.2 自動化檢查工具

  • Lint:Android 內置靜態檢查工具,可配置自定義規則:
// build.gradle
android {lintOptions {// 發現錯誤時中斷構建abortOnError true// 配置檢查規則(xml文件)lintConfig file("lint.xml")}
}
  • Checkstyle(Java):
  • 配置文件:checkstyle.xml(定義命名、格式規則);
  • 集成到構建:通過 Gradle 插件在編譯時檢查。
  • Detekt(Kotlin):
  • 類似 Checkstyle,針對 Kotlin 的靜態檢查工具;
  • 支持自定義規則,可檢查空安全、命名等問題。

6.3 持續優化與文化建設

  • 定期更新規范:隨著項目發展(如引入新框架),更新規范;
  • 正面激勵:表彰遵循規范的代碼,樹立榜樣;
  • 將規范融入文化:讓 “寫規范代碼” 成為團隊共識,而非強制要求。

結語

編碼規范不是 “束縛創造力的枷鎖”,而是 “釋放創造力的工具”—— 當開發者無需在命名、格式等基礎問題上花費精力,才能更專注于業務邏輯與架構設計。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90713.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90713.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90713.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[RPA] Excel中的字典處理

案例1一個Excel文件總共有2個Sheet頁&#xff0c;分別為總表和對照表通過對照表sheet頁&#xff0c;設置價格對照字典對照表循環總表sheet頁&#xff0c;根據循環到的商品名稱&#xff0c;找到對應字典中的價格&#xff0c;并計算出總價總表將總價寫入到Excel表中C列&#xff0…

基于NSGAII優化算法的車間生產調度matlab仿真

目錄 1.程序功能描述 2.測試軟件版本以及運行結果展示 3.部分程序 4.算法理論概述 5.參考文獻 6.完整程序 1.程序功能描述 車間生產調度是制造業的核心環節&#xff0c;其目標是在滿足設備約束、工序優先級等條件下&#xff0c;優化多個相互沖突的生產指標&#xff08;如…

Cmake、VS2019、C++、openGLopenCV環境安裝

在 CMake 和 Visual Studio 2019 環境下安裝和配置 OpenGL、OpenCV 以及 CUDA 可能會有些復雜&#xff0c;因為涉及的組件多且相互依賴。以下是一個詳細的指南&#xff0c;幫助您逐步完成安裝和配置。 1. 前提條件 在開始之前&#xff0c;請確保您已安裝以下軟件&#xff1a; …

視頻二維碼在產品設備說明書中的應用

在當今數字化的時代&#xff0c;傳統的產品設備說明書正面臨著一場變革。文字和圖片雖然能提供基本信息&#xff0c;但在復雜設備的安裝、操作和故障排除方面&#xff0c;往往顯得力不從心。而視頻二維碼的出現&#xff0c;為這一困境提供了完美的解決方案&#xff0c;它將冰冷…

【Pytest 使用教程】

pytest 使用 test_basic.py Pytest 完全實戰手冊 一、核心概念與基礎 1、在pytest框架下運行測試用例&#xff0c;最基礎的一共有三點。導入pytest的包寫一個方法&#xff0c;或者類。后面運行的時候&#xff0c;相當于運行這個方法&#xff0c;或者類里的方法&#xff0c;無需…

基于OpenOCD 的 STM32CubeIDE 開發燒錄調試環境搭建 DAPLINK/STLINK

需要部署一個開發環境,實現h7的板子通過daplink功能給目標板燒寫程序(同事要將這個過程用fpga實現),需要通過openocd+gdb+daplink stm32; 總結:單條命令執行太麻煩,參考4寫成腳本文件: 獨立腳本使用Openocd ? 在**“在Stm32CubeIDE環境下使用DAP-Link仿真”**一文中…

嵌入式硬件篇---zigbee無線串口通信問題

使用 ZigBee 進行無線串口通信時&#xff0c;接收異常&#xff08;如丟包、亂碼、完全無法接收&#xff09;是常見問題&#xff0c;其原因涉及射頻通信特性、網絡機制、硬件配置、環境干擾等多個層面。以下從具體機制出發&#xff0c;詳細分析可能的原因&#xff1a;一、射頻層…

【AI周報】2025年7月26日

【AI周報】2025年7月第四周觀察&#xff1a;GitHub Spark重塑開發范式&#xff0c;中美AI政策對壘升級 省流版靜態頁面周報&#xff0c;為方便各位看官快速食用&#xff0c;我準備了摘要版周報&#xff0c;歡迎訪問&#xff1a;20250726周報 引言&#xff1a;本周焦點速覽 2…

HTML:從 “小白” 到 “標簽俠” 的修煉手冊

目錄 一、HTML&#xff1a;網頁的 “骨架” 不是骷髏架 二、文本標簽&#xff1a;文字的 “華麗變身” 術 1. 標題標簽&#xff1a;文字界的 “領導班子” 2. 段落標簽&#xff1a;文字的 “專屬保姆” 3. 文本格式化標簽&#xff1a;給文字 “穿花衣” 三、鏈接標簽&…

python3GUI--基于YOLO的火焰與煙霧檢測系統By:PyQt5(詳細圖文介紹)

文章目錄一&#xff0e;前言1.引言2.正文二&#xff0e;核心內容1.數據集2.模型訓練3.界面窗口1.登錄注冊界面2.核心功能界面3.檢測告警提示窗口三&#xff0e;.核心界面模塊介紹1.頂部信息區域2.數據輸入3.參數配置4.告警設置5.操作臺6.關于7.指標變化8.異常速覽9.日志輸出10.…

基于Transform、ARIMA、LSTM、Prophet的藥品銷量預測分析

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主一、項目背景二、數據準備與預處理三、模型選擇與方法設計1. ARIMA 模型&#xff1a;傳統統計方法的基線構建2. LSTM 模型&#xff1a;引入記憶機制的深度學習方法3. Transformer 模型&#…

LLM隱藏層與logits數值的簡單理解

LLM的“隱藏層數值”和“logits數值” 代表什么,范圍是多少 “隱藏層數值”和“logits數值”是兩個關鍵概念——它們分別對應模型“理解信息”和“輸出決策”的核心環節。 一、先明確基礎:LLM的“思考”流程 LLM本質是“輸入文本→處理信息→輸出結果”的神經網絡。簡單說…

Vue》》@ 用法

使用 別名導入 // 導入 src/components/Button.vue import Button from /components/Button.vue// 導入 src/utils/helper.js import { helperFunc } from /utils/helper// 導入 src/store/index.js import store from /store

20250726-1-Kubernetes 網絡-Service存在的意義_筆記

一、Service控制器 1. Service存在的意義 1)基本場景 ?? 動態IP問題:Pod IP具有短暫性,銷毀重建后IP會變化(示例:原IP 169.130重建后變為169.132) 服務發現需求:需要穩定入口訪問同一服務的多個Pod,避免因Pod變動導致服務中斷 負載均衡需求:多個Pod副本需要統一訪…

在一個存在的包里面編寫msg消息文件

前言盡管最佳實踐是在專門的接口包中聲明接口&#xff0c;但有時在同一個包中完成接口的聲明、創建和使用會更為便捷。創建文件創建好msg/AddressBook.msg文件&#xff0c;在你的包的目錄下package.xml<buildtool_depend>rosidl_default_generators</buildtool_depend…

華為服務器操作系統openEuler介紹與安裝

一、openEuler概述 1.1、openEuler介紹 openEuler&#xff08;簡稱 “歐拉”&#xff09;是華為開源的服務器操作系統&#xff0c;是基于Linux穩定系統內核的、面向企業級的通用服務器架構平臺。能夠滿足客戶從傳統IT基礎設施到云計算服務的需求&#xff0c;打造了完善的從芯…

CUDA雜記--FP16與FP32用途

FP16&#xff08;半精度浮點數&#xff09;和FP32&#xff08;單精度浮點數&#xff09;是計算機中用于表示浮點數的兩種常見格式&#xff0c;它們在存儲空間、數值范圍、精度、計算效率等方面有顯著區別。以下從核心差異、適用場景等方面詳細說明&#xff1a; 一、核心差異&am…

Android開發中技術選型的落地方案

技術選型不是簡單地“哪個庫最火就用哪個”&#xff0c;而是一個需要綜合考慮業務、團隊、技術、維護、未來等多維度因素的系統工程。 核心目標&#xff1a; 選擇最適合當前及可預見未來項目需求的技術棧&#xff0c;確保應用高質量、高效率、可維護、可擴展、安全穩定地開發和…

Spring Boot 單元測試進階:JUnit5 + Mock測試與切片測試實戰及覆蓋率報告生成

在微服務架構盛行的今天&#xff0c;單元測試已成為保障代碼質量的核心環節。Spring Boot 生態提供了完整的測試工具鏈&#xff0c;結合 JUnit5 的現代化測試框架和 Mockito 的行為模擬能力&#xff0c;可實現從方法級到模塊級的全鏈路測試覆蓋。本文將通過實戰案例解析 JUnit5…

八股文整理——計算機網絡

目錄 OSI&#xff0c;TCP/IP&#xff0c;五層協議的體系結構 TCP/IP模型和OSI參考模型的對應關系 OSI每一層的作用如下&#xff08;理解順序依次往下&#xff09;&#xff1a; OSI分層及對應協議 以 “寄快遞” 為例類比七層模型 TCP與UDP的區別&#xff1f; TCP對應的…