自己写的 Android 开发规范

Android 编程规范(试行)

/*******************************
 * 第一节 排版规范
 *******************************/

1.    缩进
    a.    每增加一个嵌套层级,增加 4 个空格的缩进。
    b.    考虑到不同机器上 TAB 长度不一致的问题,缩进时只使用空格,不使用 TAB。

2.    换行
    a.    左花括号不换行,右花括号独占一行,并注释说明是哪个语句块的结束。

    // OK:
    public void okExample() {
        // Something
    } // okExample()

    // NG:
    public void ngExample1() {
    // Something
    } // ngExample1()

    public void ngExample2()
    {
        // Something
    } // ngExample2()

    public void ngExample3()
        {
            // Something
        } // ngExample3()

    public void ngExample4() {
        /* Something */ }

    b.    一行只允许写一条语句,不允许将多条短语句写在一行里。

    // OK:
    var1 = 1;
    var2 = 2;
    var3 = 3;

    // NG:
    var1 = 1; var2 = 2; var3 = 3;

    c.    if 语句, for 循环, while 循环, do while 循环和 try catch 语句,
    即使语句块/循环体内只有一条语句,也请用花括号将语句块/循环体包裹起来。

    // OK:
    public String getData() {
        if (mData != null) {
            return mData;
        } // if (mData != null)
        else {
            return "null";
        } // else
    } // getData()

    // NG:
    public String getData() {
        if (mData != null) return mData; else return "null";
    } // getData()

    public String getData() {
        if (mData != null) return mData;
        else return "null";
    } // getData()

    d.    一行不得超过 80 个字符,超过时请按以下规则将语句分成多行书写:
        i.    if 语句过长时,请将条件拆分成多个 boolean 变量的形式。例如

        if (lat>0.8293 && lat<55.8271 && lng>72.004 && lng<137.8347) {
            // Something
        } // if (lat>0.8293 && lat<55.8271 && lng>72.004 && lng<137.8347)

        最好写成这样的形式:

        boolean latInRange = (lat > 0.8293 && lat < 55.8271);
        boolean lngInRange = (lng > 72.004 && lng < 137.8347);
        if (latInRange && lngInRange) {
            // Something
        } // if (latInRange && lngInRange)

        ii. for 语句和 while 语句的循环条件最好不要过长。
        实在过长时,请改写成如下的形式:

        for (exp1; ; exp3) {
            // Something
            if (!exp2) {
                break;
            } // if (!exp2)
        } // for (exp1; ; exp3)

        也就是将循环是否继续的判断 (exp2) 放到循环体里面去,按照上一条规则改写
        成 if 的形式。但要注意这里条件满足时不是继续执行循环而是退出循环,所以
        判断的条件要反过来 (!exp2)。
        while 语句同理,只要去掉 while 循环和 do 循环不包含的 exp1 和 exp3 即可。

        iii.方法头的参数部分过长时,请将参数换行书写,以第一行的参数为准左对齐。

        public void aVeryVeryLongMethod(int veryVeryLongParam1,
                                        int veryVeryLongParam2,
                                        int veryVeryLongParam3) {
            // Something
        } // aVeryVeryLongMethod()

        iv. 方法调用语句的参数部分过长时,同上一条,将参数换行书写,以第一行的
        参数为准左对齐。但有一些不同,上一条中第一个参数紧跟着左圆括号之后,不
        换行。在这里,第一个参数也请换行。且要在结尾处注释是调用的哪个方法。

        aVeryVeryLongMethod(
            veryVeryLongParam1,
            veryVeryLongParam2,
            veryVeryLongParam3
        ); // aVeryVeryLongMethod()

        v.    链式调用 (obj.m1().m2()...) 过长时,请从第二个小数点开始换行书写,
        每行调用一个方法,小数点对齐。

        StringBuilder sBuilder = new StringBuilder();
        sBuilder.append(string1)
                .append(string2)
                .append(string3); // sBuilder

3.    空格留白:
    a.    除方法声明和方法调用处外,任何位置的左圆括号前都需要加空格。
    b.    任何位置的左花括号前都需要加空格。
    c.    单目运算符和运算对象紧贴;
        双目运算符需要和两个操作对象用空格隔离;
        三目运算符不允许在程序任何位置出现。
    d.    "." 运算符前后不加空格。
    e.    表示数组的方括号请和对象或类型名紧贴。
    f.    表示泛型的尖括号请和类型名紧贴。
    g.    逗号后,以及 for 语句里的分号后需要加空格。
    下面是一段代码示例:

    public void spaceDemo() {
        // 方法声明处的括号和方法名紧贴,左花括号前加空格
        int i, len;                // 逗号后加空格
        int[] intArray;            // 方括号和类型名紧贴
        List<Integer> intList;    // 尖括号和类型名紧贴
        // 左花括号前加空格,逗号后加空格
        intArray = new int[] {1, 2, 3};
        // "." 运算符前后不加空格
        len = intArray.length;
        // 尖括号和类型名紧贴,方法调用处的括号和方法名紧贴
        intList = new ArrayList<>();

        // for: 除方法声明和方法调用处外,任何位置的左圆括号前都需要加空格
        // i = 0; i < len: 双目运算符前后加空格,for 语句里的分号后需要加空格
        // ++i: 单目运算符和运算对象紧贴,左花括号前加空格
        for (i = 0; i < len; ++i) {
            // "." 运算符前后、方法调用处的括号前后、方括号前后不加空格
            intList.add(intArray[i]);
        } // for (i = 0; i < len; ++i)
    } // spaceDemo()

4.    类撰写规范
    a.    请遵守 Java 的封装规则,对除 static final 类型的字段设置
    private 属性的访问界定符。如对特定字段有暴露需求,请再为它们
    设置公有的 getter / setter 方法。

    b.    类中的元素请按照如下顺序书写:

    ↓    常量字段 (static final 修饰)
    ↓    静态字段 (static 修饰)
    ↓    成员字段
    ↓    成员方法 (按照 protected -> public -> private 的顺序书写)
    ↓    成员内部类 (按照 protected -> public -> private 的顺序书写)

    例外:活动类中和活动生命周期相关的方法不必完全遵守上述规定。
    例如,将 onCreate() 方法放在字段的下方,将 onPause() onDestroy()
    等方法放在类的最末尾。

    c.    对于不需要创建实例的工具类、配置类、枚举类,以及单一实例的类
    (Singleton),请为它们添加限定符为 private 的无参构造器,阻止外部
    创建该类的实例。同时,对于无实例的工具类、配置类、枚举类,请确保
    类成员被 static final 关键字修饰,类方法被 static 关键字修饰。

    d.    对于只有两种状态的字段,如果其表达的含义不是“是”、“否”,则请
    不要将其定义为布尔型,而应使用枚举来描述,避免不必要的理解困难。
    对于两种以上状态的字段也同理,不使用纯数字,而使用有意义的标识符。

    下面是两个类的例子:
    (省略了部分空行以将代码压缩到一页里,实际撰写时请按照规范保留空行)

    // 枚举类
    public class BootMode {
        public static final int NORMAL = 0;
        public static final int FAST = 1;
        public static final int SAFE = 2;

        private BootMode() { /* 枚举类对外隐藏构造器 */ }
    } // BootMode Class

    // 人员类
    public class Person {
        // 使用枚举法描述性别字段,而不使用布尔型
        public static final int SEX_MALE = 1;
        public static final int SEX_FEMALE = 2;
        public static final int SEX_UNKNOWN = 0;

        // 成员字段设置为 private 属性,然后再设置 getter/setter
        private String mName;
        private int mSex;
        private int mAge;

        public String getName() { return mName; }

        public int getSex() { return mSex; }

        public int getAge() { return mAge; }

        public void setName(String name) { mName = name; }

        public void setSex(int sex) {
            // 设置枚举字段的值时注意要进行合法性检查
            if (sex == SEX_MALE || sex == SEX_FEMALE) {
                mSex = sex;
            } // if (sex == SEX_MALE || sex == SEX_FEMALE)
            else {
                mSex = SEX_UNKNOWN;
            } // else
        } // setSex()

        public void setAge(int age) { mAge = age; }
    } // Person Class

5.    方法撰写规范
    a.    方法内的临时变量统一在方法开头处声明,不要东一处西一处新建变量。

    // OK:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        TextView lblTitle;
        Button btnLogin;

        super.onCreate();
        setContentView(R.layout.activity_main);
        lblTitle = findViewById(R.id.lblMainTitle);
        lblTitle.setText(R.string.lblMainTitle);
        btnLogin = findViewById(R.id.btnMainLogin);
        btnLogin.setOnClickListener(this);
    } // onCreate()

    // NG:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate();
        setContentView(R.layout.activity_main);
        TextView lblTitle = findViewById(R.id.lblMainTitle);
        lblTitle.setText(R.string.lblMainTitle);
        Button btnLogin = findViewById(R.id.btnMainLogin);
        btnLogin.setOnClickListener(this);
    } // onCreate()

    b. 方法调用时,参数部分不能超过两层嵌套,否则须先将嵌套的各个部分
    分解成变量。另外,严禁在参数中用 new 创建匿名类实现抽象类或接口!

    // OK:
    private void initLineChart() {
        LineData data;
        LineDataSet set;
        List<Entry> entries;
        LineChart lineChart;

        entries = new ArrayList<>;
        entries.add(new Entry(0, 0));
        set = new LineDataSet(entries, "");
        data = new LineData(set);
        lineChart = findViewById(R.id.lcMain);
        lineChart.setData(data);
    } // initLineChart()

    // NG:
    private void initLineChart() {
        List<Entry> entries = new ArrayList<>;
        entries.add(new Entry(0, 0));
        LineChart lineChart = findViewById(R.id.lcMain);
        lineChart.setData(
            new LineData(
                new LineDataSet(entries, "")
            ) // new LineData()
        ); // lineChart.setData()
    } // initLineChart()

    上下两个例子,哪一种看得更清爽更易懂,高下立判。
    再举一例

    // OK:
    private void showDialog(String title, String msg) {
        AlertDialog dialog;
        DialogInterface.OnClickListener onClick;

        onClick = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dlg, int which) {
                dlg.dismiss();
            } // onClick()
        } // onClick = new DialogInterface.OnClickListener()

        dialog = new AlertDialog.Builder(this)
            .setTitle(title)
            .setMessage(msg)
            .setPositiveButton(android.R.string.ok, onClick)
            .create(); // dialog
        dialog.show();
    } // showDialog()

    // NG:
    private void showDialog(String title, String msg) {
        new AlertDialog.Builder(this)
            .setTitle(title)
            .setMessage(msg)
            .setPositiveButton(
                android.R.string.ok,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dlg, int which) {
                        dlg.dismiss();
                    } // onClick()
                } // new DialogInterface.OnClickListener()
            ) // setPositiveButton()
            .show(); // new AlertDialog.Builder(this)...
    } // showDialog()

6.    条件语句、循环语句规范
    a.    JAVA 不支持 goto 语句,跳出多重循环请使用标识位判断的方式。

    public void jumpOutExample() {
        int i, j, sum;
        boolean isOk;

        sum = 0;
        isOk = false;
        for (i = 1; i < 100; ++i) {
            for (j = i; j < 100; ++j) {
                sum += i * j;
                if (sum > 10000) {
                    isOk = true;
                    break;
                } // if (sum > 10000)
            } // for (j = i; j < 100; ++j)

            if (isOk) {
                break;
            } // if (isOk)
        } // for (i = 1; i < 100; ++i)

        // Something
    } // jumpOutExample()

    b.    在常量和变量进行比较时,请按常人习惯将变量写在左侧,将常量写在右侧。

    // OK:
    if (a == 1) {
        // Something
    } // if (a == 1)

    // NG:
    if (1 == a) {
        // Something
    } // if (1 == a)

    c.    对布尔值的判断,请不要使用 xxx == true 或者 xxx == false 的形式。

    // OK:
    if (cond1 && !cond2) {
        // Something
    } // if (cond1 && !cond2)

    // NG:
    if (cond1 == true && cond2 == false) {
        // Something
    } // if (cond1 == true && cond2 == false)

    d.    不允许使用三目运算符 (即 cond ? exp1 : exp2),请永远写成 if else 的形式。

    // OK:
    public int maxOf(int a, int b) {
        if (a > b) {
            return a;
        } // if (a > b)
        else {
            return b;
        } // else
    } // maxOf()

    // NG:
    public int maxOf(int a, int b) {
        return a > b ? a : b;
    } // maxOf()

    e.    条件表达式中不允许出现更改对象值的内容。包括但不限于:
    单目运算符 ++ --
    双目运算符 = += -= *= /= %= &= |= <<= >>=
    对象的 setter 方法

    // OK:
    while (c > 0) {
        c--;
        // Something
    } // while (c > 0)

    // NG:
    while (c-- > 0) {
        // Something
    } // while (c-- > 0)

    f.    if 语句中请将预期的分支写在 if 块中,将防熊孩子类的非预期分支
    写在 else 块中增加可读性。不要在 void 方法中使用 return 语句。

    // OK:
    public void okExample(int[] arr) {
        if (arr != null && arr.length > 0) {
            System.out.println("length=" + arr.length);
        } // if (arr != null && arr.length > 0)
    } // okExample()

    // NG:
    public void ngExample(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        } // if (arr == null || arr.length == 0)

        System.out.println("length=" + arr.length);
    } // ngExample()

    g.    switch 语句的每个 case 都要以 break; 结尾,禁止一切 case 跨越
    即使前一个 case 要复用后一个 case 里的代码也不允许以跨越形式书写,
    每个 case 必须保证完全独立于其他 case

    // OK:
    switch (status) {
        case STAT1:
            // Something1
            // Something2
            break; // case STAT1

        case STAT2:
            // Something2
            break; // case STAT2

        // More cases...
    } // switch (status)

    // NG:
    switch (status) {
        case STAT1:
            // Something1

        case STAT2:
            // Something2
            break;

        // More cases...
    } // switch (status)

    case 跨越会造成代码逻辑混乱,可读性下降。如上述 case 跨越的例子,
    当 Something2 中有关于枚举量 status 的操作时,那么此时 status 的
    值是 STAT1 还是 STAT2 呢?为了避免不必要的歧义,请勿跨越 case

/*******************************
 * 第二节 注释规范
 *******************************/

1.    *.java 代码文件头部注释 (尖括号表示要替换的内容,下同)

//
//
// <项目名称>
// 运行环境:Android <minSdk 版本>+
// 编译环境:Android Studio <IDE 版本>, SDK Platform <compileSdk 版本>
// <版权信息>
//
//

2.    xml 文件在第一行 <?xml version="1.0" encoding="utf-8"?> 后添加如下注释

<!--
======================================================================
==
== <项目名称>
== 运行环境:Android <minSdk 版本>+
== 编译环境:Android Studio <IDE 版本>, SDK Platform <compileSdk 版本>
== <版权信息>
==
== <文件名>: <文件内容>
==
======================================================================
-->

3.    类注释请遵循 Javadoc 规范写在类声明的前面。Java bean 类不写类注释。

/**
 * <类名>: <该类实现的功能>
 * <若类不为 public 则请说明限制在哪个包内使用>
 * <若类是单例模式则请说明调用哪个方法获取实例>
 *
 * @see <若有相关类请标明>
 */

4.    方法注释请遵循 Javadoc 规范写在方法声明的前面。
    Java bean 类不写方法注释;重载方法只写方法中所用到的参数即可。

/**
 * <方法名>: <方法实现的功能>
 *
 * @param <参数1> <参数含义>
 * @param ...
 * @return <方法的返回值>
 */

5.    代码注释,对于单条语句的注释,请在语句右侧或上方书写;
    对于一段代码的注释,请在代码块的上方书写,并在代码块下方添加空行。

6.    if 语句的分支, switch 语句中的 case 分支,必须写上明确的注释。
    例如对于 ListView 的 onItemClick 方法:

    public void onItemClick(AdapterView<?> a, View v, int pos, long l) {
        switch (pos) {
            case 0:
                // 这里写上列表第 0 项的具体内容
                // Something 0
                break; // case 0

            case 1:
                // 这里写上列表第 1 项的具体内容
                // Something 1
                break; // case 1

            // More cases...
        } // switch (pos)
    } // onItemClick()

7.    避免无意义的注释。注释应当描述代码所要完成的任务,而不是算法内容。

    // OK:
    if (u.isSaveStat) {
        // 用户记住了登录状态
        // Something
    } // if (u.isSaveStat)

    // NG:
    if (u.isSaveStat) {
        // 该对象的 saveStat 字段为真
        // Something
    } // if (u.isSaveStat)

8.    仅当调试需要时可以暂时将不需要但以后还有用处的代码块进行注释处理。
    最终提交的版本不可以有注释掉的代码块。

/*******************************
 * 第三节 标识符命名规范
 *******************************/

1.    通用规范
    a.    任何标识符都要遵循见名知意的原则,不可以起 a, flag, var 这样的名字。
    b.    不允许用汉语拼音命名标识符。
    c.    除约定俗成的缩写外,忌随意缩写标识符。

2.    包名(不超过 12 字符):
    全部使用小写字母,以名词命名,只允许使用一个英文单词,不可以有任何修饰定语。
    当一个包中要容纳的是特定类的集合时,请使用复数形式。

3.    类名(不超过 20 字符):
    遵循大驼峰命名规则,以名词命名,可以有定语修饰。
    除非是工具类,或者是含有数组、集合字段的 bean 类,否则不使用复数形式。

4.    字段(不超过 12 字符):
    实例变量以 m 开头,后续遵循大驼峰命名规则;
    静态变量以 s 开头,后续遵循大驼峰命名规则。
    常量 (即 static final 类型) 全大写,单词之间以下划线分隔。

5.    方法(不超过 20 字符)和参数(不超过 8 字符):
    遵循小驼峰命名规则。
    对于 void 类型的方法,一般情况下以动词开头。
    对于有参数的方法,考虑以 by, of, from, to 等介词结尾,表明方法和参数的关系。
    特殊地,对于接口方法 (触发器),请以介词 on 开头,后面写上触发条件。

6.    方法内部的临时变量(不超过 8 字符):
    遵循小驼峰命名规则。注意不要和传入的参数重名。

7.    关于 final 关键字
    final 关键字具有一定的误导性,它只能确保基本数据类型和 String 类型的值不变,
    对于其他引用类型,它并不能保证其内容不变。在此基础上,它还会破坏类的可扩展性,
    在类复用的过程中, final 关键字会带给我们一些意料之外的麻烦。因此做出以下规定:
    a.    可以用 static final 关键字来修饰类的常量。
        以此法修饰的常量对象只能是基本数据类型或 String 类型。
    b.    方法内部的局部类或匿名类要使用方法的参数或临时变量时,
        相应内容用 final 修饰。此为 Java 规定。
    c.    其他任何情况都不使用 final 关键字修饰对象,即使对象在生命周期里内容不变。

下面是一段代码示例:

// 包名全小写,仅一个英语单词 (前面的 com.example.app 是 APP 包名)
package com.example.app.tools;

public class DateTimeTools { // 类名遵循大驼峰规则
    private static final String DATE_FORMAT = "yyyy-M-d"; // 常量全大写
    private static Date sNow; // 静态字段以 s 开头,后续遵循大驼峰命名规则

    // 方法名遵循小驼峰命名规则
    public static Date getNow() {
        sNow = new Date();
        return sNow();
    } // getNow()

    // 方法名、参数名遵循小驼峰命名规则
    // 有参数的方法考虑使用介词收尾
    public static String dateStringOf(Date date) {
        String dateString;            // 临时变量遵循小驼峰命名规则
        SimpleDateFormat formatter; // 临时变量遵循小驼峰命名规则

        formatter = new SimpleDateFormat(DATE_FORMAT, Locale.CHINA);
        dateString = formatter.format(date);
        return dateString;
    } // dateStringOf()
} // DateTimeTools Class

/*******************************
 * 第四节 资源命名规范
 *******************************/

1.    控件 id 名
    遵循以下规则:
    <控件类型缩写> + <控件所属活动> + <控件名字>
    例如:lblMainTitle
    lbl:   表示该控件是一个标签控件 (Label, Android SDK 里叫 TextView)
    Main:  表示该控件属于 MainActivity 的布局中
    Title: 表示该控件是用来显示标题的。
    下面给出常见的控件类型缩写:

    Button/ImageButton  >>  btn         CheckBox        >>  chk
    ConstraintLayout    >>  cl          EditText        >>  box
    GridView            >>  gd          ImageView       >>  img
    LinearLayout        >>  ll          ListView        >>  lst
    ProgressBar         >>  ps          RadioButton     >>  opt
    RadioGroup          >>  gp          RelativeLayout  >>  rl
    ScrollView          >>  scl         SeekBar         >>  sk
    Spinner             >>  sp          Switch          >>  sw
    TextView            >>  lbl         ToolBar         >>  tb

2.    字符串资源
    a.    为了尽可能避免乱码问题,以及实现国际化,请将用户界面中使用的字符串整理到
    strings.xml 资源文件中。
    对于非格式字符串,在活动代码中使用 R.string.* 的资源 ID 号来引用。
    对于格式化字符串,使用 getString(R.string.*, ...) 方法来引用。

    // OK:
    // strings.xml:
    // <string name="lblMainTitleF">现在时间是:%s</string>
    Date now = new Date();
    TextView lblTitle = findViewById(R.id.lblMainTitle);
    lblTitle.setText(
        getString(R.string.lblMainTitleF, now.toString())
    ); // lblMainTitle.setText()

    // NG:
    Date now = new Date();
    TextView lblMainTitle = findViewById(R.id.lblMainTitle);
    lblMainTitle.setText("现在时间是:" + now.toString());

    b.    当一个字符串资源要表示
        标签的 text 属性 /
        按钮的 text 属性 /
        文本框的 hint 属性 /
        图片的 contentDescription 属性
    的值时,该资源的名字要与对应控件的完整控件名一致。

    <string name="btnLoginExec">登录</string>
    <string name="lblMainTitle">欢迎使用</string>

    c.    一个菜单资源中各项的 title 值,命名规则为:
    mnu + <所属菜单对象作用的活动名> + <菜单项名>
    当其所属菜单同时作用于多个活动时,省去第二部分。

    <string name="mnuClose">关闭</string>
    <string name="mnuMessagesFilter">筛选</string>

    d.    ListView、GridView 中各项的字符串,命名规则为:
    itm + <该列表或九宫格所属的活动名> + <当前项名>

    <string name="itmMainLocation">位置</string>
    <string name="itmSettingsAbout">关于</string>

    e.    Toast.makeText() 方法生成的贴士文字,命名规则为:tip + <贴士内容>

    <string name="tipNoInternet">无法连接服务器</string>

    f.    对话框各个部分字符串的命名规则
    标题:dlg + <对话框名> + Title
    内容:dlg + <对话框名> + Msg
    确定、取消按钮:使用 SDK 自带资源 android.R.string.ok/cancel

    <string name="dlgExitTitle">请注意</string>
    <string name="dlgExitMsg">确定要退出吗?</string>

    g.    当一个字符串资源用到了格式控制类字符,在代码中会被 getString() 方法
    解析格式时,请首先对照以上规范命名后,于结尾增加 F 标记。

    <string name="lblMainTitleF">现在时间是:%s</string>

3.    图片资源 (drawable)
    图片资源命名时,全小写,单词之间用下划线分割。
    只适配一个密度,一般情况下适配 drawable-xhdpi 即可。

/*******************************
 * 第五节 编码规范
 *******************************/

1.    不要在非活动类中添加活动的 Context 引用成员。这会造成不可预料的内存泄露问题。
    如实在需要 Context 的引用(如为了获得字符串或颜色资源),解决方法有二:
    a.    仅将引用范围限定在方法内部,即作为方法的参数传递 Context。这样可以
    保证对 Context 的引用仅限定在方法内部,不会造成内存泄漏。

    b.    调用传入的 Context 对象的 getApplicationContext() 方法获得应用层的
    Context 赋值给引用成员。其生命周期是整个 APP 运行周期,不会造成内存泄漏。

2.    将复用代码封装成方法,即使是一两行代码也可考虑封装。
    封装成方法后可以使得程序代码更加清晰地表达业务逻辑,而不是底层实现细节。
    对于和活动相关的复用代码,为了减少 Context 的传递,建议将此类方法封装至
    BaseActivity 的抽象类,再令所有本地活动都继承于 BaseActivity 即可。

3.    类的功能要明确。
    确保一个类仅完成一项任务,不要实现不相关的多项任务不务正业。
    例如,和获取服务器 JSON 数据有关的类就不要在获取到数据后自作主张对数据进行修正,
    也不要自作主张调用 Toast.makeText() 方法显示贴士,而应该设置回调方法将数据交给
    请求者进行处理。

4.    减少耦合。
    在撰写类的构造器或成员方法时,减少不必要的参数传递,尤其是非基本类型的参数。
    如果一个工具类仅为某一两个类服务,可以考虑将该类移动至和调用它的类同样的包下,
    这样就可以将该类的访问权限由 public 改为 package-private, 减少误访问的可能性。

5.    对于产生实例对象的类,考虑重写其 toString() 方法,
    返回和实例内容相关的信息,为调试增加便利。

// E.O.F

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值