日本欧美一区-日本欧美一区二区三区片-日本强好片久久久久久AAA-日本-区一区二区三区A片-日本人伦一区二区三区-日本人妻A片成人免费看

電子開發 | 基礎入門 | 電路原理圖 | 梯形图实例 | PLC基础   《如果喜欢本站,请按 Ctrl+D 手动收藏!感谢您的支持》一起学习一起进步,电子开发王欢迎您!.

電子開發網

電子開發網電子設計 | 電子開發網Rss 2.0 會員中心 會員注冊

★电路公式手册,最新版《电子电路公式计算器》,电路公式查询手册 电路公式计算器【电子从业人员必备手册】
☆十天学会单片机实例100 c语言 chm格式。资料内容详细,覆盖例子多,内容广【电子从业人员必备手册】
搜索: 您現在的位置: 電子開發網 >> 編程學習 >> Java >> 正文

JAVA開發規范

作者:佚名    文章來源:本站原創    點擊數:405    更新時間:2023/10/1

一、編程規范

(一)命名規范:(命名要望文知意,不要嫌長)

  1. 包名要統一小寫

  1. 類名、接口名遵從駝峰式命名,DO / BO /DTO / VO / AO/PO例外

例子:MarcoPolo / UserDO / XmlService / TcpUdpDeal

  1. 方法名、參數名、成員變量、局部變量都統一使用 lowerCamelCase 風格

例子:localValue / getHttpMessage() / inputUserId

  1. 常量命名全部大寫,單詞間下劃線隔開

例子:MAX_STOCK_COUNT

  1. 枚舉類名要以Enum為后綴,且枚舉成員名稱要全大寫,和常量命名一樣

例子:枚舉類名 ProcessStatusEnum 枚舉成員名稱 SUCCESS/UNKOWN_REASON

  1. Service/DAO層方法命名:

  1. 獲取單個對象的方法用get做前綴

  1. 獲取多個對象的方法用list做前綴

  1. 獲取統計值的方法用count做前綴

  1. 插入的方法用save/insert做前綴

  1. 刪除的方法用remove/delete做前綴

  1. 修改的方法用update做前綴

  1. 領域模型命名

  1. 查詢數據庫對象:xxxPO

  1. 業務邏輯層對象:xxxBO

  1. 接收客戶端參數的對像:xxxVO

  1. 層級之間的數據傳輸對象:xxxDTO

(二)常量定義

  1. 不允許任何魔法值(即未經定義的常量)直接出現在代碼中。常量的復用層次有五層:跨應用共享常量、應用內共享常量、子工程內共享常量、包內共享常量、類內共享常量

  1. 跨應用共享常量:放置在二方庫中,通常是client.jar中的constant目錄下

  1. 應用內共享常量:放置在一方庫中,通常是modules中的constant目錄下

  1. 子工程內部共享常量:即在當前子工程的constant目錄下

  1. 包內共享常量:即在當前包下單獨的constant目錄下

  1. 類內共享常量:直接在類內部private static final定義

  1. 如果變量值在一個范圍內變化,且帶有名稱之外的延展屬性,定義為枚舉類

例子:數字就是延伸信息,標識星期幾

public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6),SUNDAY(7);}

(三)代碼格式

  1. 方法體內的執行語句組、變量的定義語句組、不同的業務邏輯之間或者不同的語義之間插入一個空行。

  1. 單行字符數限制不超過 120 個,超出需要換行,換行時遵循如下原則:

  1. 第二行相對第一行縮進 4 個空格,從第三行開始,不再繼續縮進,參考示例。

  1. 運算符與下文一起換行。

  1. 方法調用的點符號與下文一起換行。

  1. 4方法調用時,多個參數,需要換行時,在逗號后進行。

  1. 在括號前不要換行

  1. 適當加空格進行格式整理(idea使用用快捷鍵ctrl+alt+L快速整理)

(四)OOP規范

  1. 所有覆寫的方法,必須加@Override注解。可以準確判斷是否覆蓋成功。另外,如果在抽象中對方法簽名進行修改,其實現類會馬上編譯報錯

  1. 外部正在調用或者二方庫依賴的接口,不允許修改方法簽名,避免對接口調用方產生影響。接口過時必須加@Deprecated 注解,并清晰地說明采用的新接口或者新服務是什么。

  1. 調用equals方法比較時,應使用常量或確定有值的對象來調用equals方法,并且包裝類對象之間的比較,全部使用 equals 方法比較

  1. 關于基本數據類型和包裝數據類型的使用標準:

  1. 所有的POJO類屬性必須使用包裝數據類型

  1. RPC方法的返回值和參數必須使用包裝數據類型

  1. 所有的局部變量推薦使用基本數據類型

  1. 構造方法里面禁止加入任何業務邏輯,如果有初始化邏輯,請放在 init 方法中

  1. 類內方法定義順序依次是:公有方法或保護方法 > 私有方法 > getter/setter方法。

說明:公有方法是類的調用者和維護者最關心的方法,首屏展示最好;保護方法雖然只是子類關心,也可能是“模板設計模式”下的核心方法;而私有方法外部一般不需要特別關心,是一個黑盒實現;因為承載的信息價值較低,所有 Service 和 DAO 的 getter/setter 方法放在類體

  1. 循環體內,字符串的連接方式,使用 StringBuilder 的 append 方法進行擴展。

說明:反編譯出的字節碼文件顯示每次循環都會 new 出一個 StringBuilder 對象,然后進行append 操作,最后通過 toString 方法返回 String 對象,造成內存資源浪費

  1. 類成員與方法訪問控制從嚴:

  1. 如果不允許外部直接通過 new 來創建對象,那么構造方法必須是 private。

  1. 工具類不允許有 public 或 default 構造方法。

  1. 類非 static 成員變量并且與子類共享,必須是 protected。

  1. 類非 static 成員變量并且僅在本類使用,必須是 private。

  1. 類 static 成員變量如果僅在本類使用,必須是 private。

  1. 若是 static 成員變量,必須考慮是否為 final。

  1. 類成員方法只供類內部調用,必須是 private。

  1. 類成員方法只對繼承類公開,那么限制為 protected。

說明:任何類、方法、參數、變量,嚴控訪問范圍。過于寬泛的訪問范圍,不利于模塊解耦

(五)集合處理

  1. 在 subList 場景中,高度注意對原集合元素個數的修改,會導致子列表的遍歷、增加、刪除均會產生 ConcurrentModificationException 異常。并且不要在 foreach 循環里進行元素的 remove/add 操作。remove 元素請使用 Iterator方式,如果并發操作,需要對 Iterator 對象加鎖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//正例:
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if (刪除元素的條件) {
        iterator.remove();
    }
}
//反例:
List list = new ArrayList();
list.add("1");
list.add("2");
for (String item : list) {
    if ("1".equals(item)) {
        list.remove(item);
    }
}
  1. 使用集合轉數組的方法,必須使用集合的 toArray(T[] array),傳入的是類型完全一樣的數組,大小就是 list.size()。

說明:使用 toArray 帶參方法,入參分配的數組空間不夠大時,toArray 方法內部將重新分配

內存空間,并返回新數組地址;如果數組元素大于實際所需,下標為[ list.size() ]的數組

元素將被置為 null,其它數組元素保持原值,因此最好將方法入參數組大小定義與集合元素

個數一致。

  1. 使用工具類 Arrays.asList()把數組轉換成集合時,不能使用其修改集合相關的方法,它的 add/remove/clear 方法會拋出 UnsupportedOperationException 異常。

說明:asList 的返回對象是一個 Arrays 內部類,并沒有實現集合的修改方法。Arrays.asList體現的是適配器模式,只是轉換接口,后臺的數據仍是數組。

  1. 泛型通配符<? extends T>來接收返回的數據,此寫法的泛型集合不能使用 add 方法,而<? super T>不能使用 get 方法,做為接口調用賦值時易出錯。

說明:擴展說一下 PECS(Producer Extends Consumer Super)原則:第一、頻繁往外讀取內容的,適合用<? extends T>。第二、經常往里插入的,適合用<? super T>。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* ? extends T 表示T或T的子類
* ? super T   表示T或T的父類
* ?  表示可以是任意類型
**/
class Gent<T> {
    public void test(){
        System.out.println("gent");
    }
}
class SupC {
    public void test(){
        System.out.println("supC");
    }
}
class Bc extends SupC {
    //入參只能是SupC或SupC的子類
    public void testExtends(gent<? extends SupC> o){
        System.out.println("Bc");
    }
    //入參只能是Bc或Bc的父類
    public void testSuper(gent<? super Bc> o){
        System.out.println("Bc");
    }
    //入參可以是任意類型
    public void testSuper(gent<?> o){
        System.out.println("gent");
    }
}
  1. 合理利用好集合的有序性(sort)和穩定性(order),避免集合的無序性(unsort)和不穩定性(unorder)帶來的負面影響。

說明:有序性是指遍歷的結果是按某種比較規則依次排列的。穩定性指集合每次遍歷的元素次序是一定的。如:ArrayList 是 order/unsort;HashMap 是 unorder/unsort;TreeSet 是order/sort。

  1. 利用 Set 元素唯一的特性,可以快速對一個集合進行去重操作,避免使用 List 的contains 方法進行遍歷、對比、去重操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//兩個Set比較找出交集、差集、并集
public static void  setCompare() {
    Set<Integer> result = new HashSet<Integer>();
    Set<Integer> set1 = new HashSet<Integer>() {<!-- -->{
        add(1);
        add(3);
        add(4);
    }};
    System.out.println("set1 = " + set1.toString());
     
    Set<Integer> set2 = new HashSet<Integer>() {<!-- -->{
        add(1);
        add(2);
        add(3);
    }};
    System.out.println("set2 = " + set2.toString());
    //交集:set1和set2相同的元素
    result.clear();
    result.addAll(set1);
    result.retainAll(set2);
    System.out.println("交集:" + result);
    //result結果:[1, 3]
    //差集:元素存在set1,但不存在set2
    result.clear();
    result.addAll(set1);
    result.removeAll(set2);
    System.out.println("差集:" + result);
    //result結果:[4]
     
    //并集:set1的set2的元素之和
    result.clear();
    result.addAll(set1);
    result.addAll(set2);
    System.out.println("并集:" + result);
    //result結果:[1, 2, 3, 4]
}

(六)并發處理

  1. 高并發時,同步調用應該去考量鎖的性能損耗。能用無鎖數據結構,就不要用鎖;能鎖區塊,就不要鎖整個方法體;能用對象鎖,就不要用類鎖。

說明:盡可能使加鎖的代碼塊工作量盡可能的小,避免在鎖代碼塊中調用 RPC 方法。

  1. 并發修改同一記錄時,避免更新丟失,需要加鎖。要么在應用層加鎖,要么在緩存加鎖,要么在數據庫層使用樂觀鎖,使用 version 作為更新依據。

說明:如果每次訪問沖突概率小于 20%,推薦使用樂觀鎖,否則使用悲觀鎖。樂觀鎖的重試次數不得小于 3 次。

  1. 避免 Random 實例被多線程使用,雖然共享該實例是線程安全的,但會因競爭同一seed 導致的性能下降。

說明:Random 實例包括 java.util.Random 的實例或者 Math.random()的方式。正例:在 JDK7 之后,可 以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要編碼保證每個線程持有一個實例。

  1. HashMap 在容量不夠進行 resize 時由于高并發可能出現死鏈,導致 CPU 飆升,在開發過程中可以使用其它數據結構或加鎖來規避此風險

(七)控制語句

  1. 在一個 switch 塊內,每個 case 要么通過 break/return 等來終止,要么注釋說明程序將繼續執行到哪一個 case 為止;在一個 switch 塊內,都必須包含一個 default 語句并且放在最后,即使它什么代碼也沒有。

  1. 在 if/else/for/while/do 語句中必須使用大括號。即使只有一行代碼,避免采用單行的編碼方式:if (condition) statements;

  1. 表達異常的分支時,少用 if-else 方式,這種方式可以改寫成:if (condition) {...return obj;}// 接著寫 else 的業務邏輯代碼;

說明:如果非得使用 if()...else if()...else...方式表達邏輯,避免后續代碼維護困難,請勿超過 3 層。

正例:超過 3 層的 if-else 的邏輯判斷代碼可以使用衛語句、策略模式、狀態模式等來實現,

衛語句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//改造前(看著亂,不清楚每個邏輯分支的具體條件)
//當 a等于1
if (a == 1){
    //當 b等于2
    if (b == 2){
        ...
    } else {
        //當 b不等于1
        //c等于3
        if (c == 3){
            ...
        }
    }
}else{
    //當 a不等于1
    //當 d等于4
    if(d == 4){
        ...
    }
}
//改造后(從上到下,看著清晰明了,并清楚每個邏輯分支對應的條件)
//情況一:當 a等于1 并 b等于2
if(a == 1&&b == 2){
    ...
}
//情況二:當 a等于1 并 b不等于2 并 c等于3
if(a == 1&&b != 2&&c == 3){
    ...
}
//情況三:當 a不等于1 并 d等于4
if(a != 1&&d == 4){
    ...
}

策略模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
 * 實現不同動物發出不同聲音
 * 如:狗--汪汪 貓--喵喵  牛--哞哞  羊--咩咩
 * @author gz
 * */
//改造前 (后期加多種動物類型,每次都需要修改共用的邏輯,易出錯,且不易維護)
public class AnimalCryTest {
    private static final String DOG = "狗";
    private static final String CAR = "貓";
    private static final String CATTLE = "牛";
    private static final String SHEEP = "羊";
    /**
     * 動物的叫聲
     * @param animalName 動物名稱
     */
    public static void animalCry(String animalName){
        if (DOG.equals(animalName)){
            System.out.println(animalName+"----汪汪");
        }else if (CAR.equals(animalName)){
            System.out.println(animalName+"----喵喵");
        }else if (CATTLE.equals(animalName)){
            System.out.println(animalName+"----哞哞");
        }else {
            System.out.println(animalName+"----咩咩");
        }
    }
     
    public static void main(String[] args) {
        // 狗--汪汪
        animalCry(DOG);
        // 貓--喵喵
        animalCry(CAR);
        // 牛--哞哞
        animalCry(CATTLE);
        // 羊--咩咩
        animalCry(SHEEP);
    }
}
//改造后(后期加多種動物類型,只需要實現對應功能的接口,各個邏輯是相互獨立的,不易出錯,易維護)
/**
* 1、定義一個接口
**/
interface Animal {
    /**
     * 動物叫聲
     */
    void animalCry();
}
/**
* 2、創建實現該接口的實現類
**/
class Dog implements Animal {
    @Override
    public void animalCry() {
        System.out.println("狗----汪汪");
    }
}
class Car implements Animal {
    @Override
    public void animalCry() {
        System.out.println("貓----喵喵");
    }
}
class Cattle implements Animal {
    @Override
    public void animalCry() {
        System.out.println("牛----哞哞");
    }
}
class Sheep implements Animal {
    @Override
    public void animalCry() {
        System.out.println("羊----咩咩");
    }
}
/**
* 3、多態性質,根據實例化對象的不同,調用實例化對象對應的具體方法
**/
public class AnimalCryTest {
    public static void main(String[] args) {
        // 創建狗的實例對象,并調用其對應的animalCry方法  狗--汪汪
        Animal dog = new Dog();
        dog.animalCry();
        // 創建貓的實例對象,并調用其對應的animalCry方法  貓--喵喵
        Animal car = new Car();
        car.animalCry();
        // 創建牛的實例對象,并調用其對應的animalCry方法  牛--哞哞
        Animal cattle = new Cattle();
        cattle.animalCry();
        // 創建羊的實例對象,并調用其對應的animalCry方法  羊--咩咩
        Animal sheep = new Sheep();
        sheep.animalCry();
    }
}

狀態模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/**
 * 在"投了25分錢"的狀態下"轉動曲柄",會售出糖果;而在"沒有25分錢"的狀態下"轉動曲柄"會提示請先投幣。
 * 四個狀態:
 * 1、沒有硬幣狀態
 * 2、投幣狀態
 * 3、出售糖果狀態
 * 4、糖果售盡狀態
 * 四個動作:
 * 1、投幣
 * 2、退幣
 * 3、轉動出糖曲軸
 * 4、發糖
 * @author gz
 */
//改造前
public class NoPatternGumballMachine{
    /*
     * 四個狀態
     */
    /**沒有硬幣狀態*/
    private final static int NO_QUARTER = 0;
    /**投幣狀態*/
    private final static int HAS_QUARTER = 1;
    /**出售糖果狀態*/
    private final static int SOLD = 2;
    /**糖果售盡狀態*/
    private final static int SOLD_OUT = 3;
    private int state = SOLD_OUT;
    private int candyCount = 0;
    public NoPatternGumballMachine(int count) {
        this.candyCount = count;
        if(candyCount > 0)
            state = NO_QUARTER;
    }
    /*
     * 四個動作
     */
    /**
     * 投幣
     */
    public void insertQuarter() {
        if(NO_QUARTER == state){
            System.out.println("投幣");
            state = HAS_QUARTER;
        }
        else if(HAS_QUARTER == state){
            System.out.println("請不要重復投幣!");
            returnQuarter();
        }
        else if(SOLD == state){
            System.out.println("已投幣,請等待糖果");
            returnQuarter();
        }else if(SOLD_OUT == state){
            System.out.println("糖果已經售盡");
            returnQuarter();
        }
    }
    /**
     * 退幣
     */
    public void ejectQuarter() {
        if(NO_QUARTER == state){
            System.out.println("沒有硬幣,無法彈出");
        }
        else if(HAS_QUARTER == state){
            returnQuarter();
            state = NO_QUARTER;
        }
        else if(SOLD == state){
            System.out.println("無法退幣,正在發放糖果,請等待");
        }else if(SOLD_OUT == state){
            System.out.println("沒有投幣,無法退幣");
        }
    }
    /**
     * 轉動出糖曲軸
     */
    public void turnCrank() {
        if(NO_QUARTER == state){
            System.out.println("請先投幣");
        }
        else if(HAS_QUARTER == state){
            System.out.println("轉動曲軸,準備發糖");
            state = SOLD;
        }
        else if(SOLD == state){
            System.out.println("已按過曲軸,請等待");
        }else if(SOLD_OUT == state){
            System.out.println("糖果已經售盡");
        }
    }
    /**
     * 發糖
     */
    public void dispense() {
        if(NO_QUARTER == state){
            System.out.println("沒有投幣,無法發放糖果");
        }
        else if(HAS_QUARTER == state){
            System.out.println("this method don't support");
        }
        else if(SOLD == state){
            if(candyCount > 0){
                System.out.println("分發一顆糖果");
                candyCount --;
                state = NO_QUARTER;
            }
            else{
                System.out.println("抱歉,糖果已售盡");
                state = SOLD_OUT;
            }
        }else if(SOLD_OUT == state){
            System.out.println("抱歉,糖果已售盡");
        }
    }
    /**
     * 退還硬幣
     */
    protected void returnQuarter() {
        System.out.println("退幣……");
    }
}
//改造后
//1、定義一個接口或者抽象類,抽象出幾個行為狀態
public abstract class State {
    /**
     * 投幣
     */
    public abstract void insertQuarter();
    /**
     * 退幣
     */
    public abstract void ejectQuarter();
    /**
     * 轉動出糖曲軸
     */
    public abstract void turnCrank();
    /**
     * 發糖
     */
    public abstract void dispense();
    /**
     * 退還硬幣
     */
    protected void returnQuarter() {
        System.out.println("退幣……");
    }
}
// 2、為每個狀態實現接口或基類
/**
 * 沒有硬幣的狀態
 */
public class NoQuarterState extends State{
    GumballMachine gumballMachine;
    public NoQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    @Override
    public void insertQuarter() {
        System.out.println("你投入了一個硬幣");
        //轉換為有硬幣狀態
        gumballMachine.setState(gumballMachine.hasQuarterState);
    }
    @Override
    public void ejectQuarter() {
        System.out.println("沒有硬幣,無法彈出");
    }
    @Override
    public void turnCrank() {
        System.out.println("請先投幣");
    }
    @Override
    public void dispense() {
        System.out.println("沒有投幣,無法發放糖果");
    }
}
/**
 * 投硬幣的狀態
 */
public class HasQuarterState extends State{
    GumballMachine gumballMachine;
    public HasQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    @Override
    public void insertQuarter() {
        System.out.println("請不要重復投幣!");
        returnQuarter();
    }
    @Override
    public void ejectQuarter() {
        returnQuarter();
        gumballMachine.setState(gumballMachine.noQuarterState);
    }
    @Override
    public void turnCrank() {
        System.out.println("轉動曲軸,準備發糖");
        gumballMachine.setState(gumballMachine.soldState);
    }
    @Override
    public void dispense() {
        System.out.println("this method don't support");
    }
}
/**
 * 出售的狀態
 */
public class SoldState extends State{
    GumballMachine gumballMachine;
    public SoldState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    @Override
    public void insertQuarter() {
        System.out.println("已投幣,請等待糖果");
        returnQuarter();
    }
    @Override
    public void ejectQuarter() {
        System.out.println("無法退幣,正在發放糖果,請等待");
    }
    @Override
    public void turnCrank() {
        System.out.println("已按過曲軸,請等待");
    }
    @Override
    public void dispense() {
        int candyCount = gumballMachine.getCandyCount();
        if(candyCount > 0){
            System.out.println("分發一顆糖果");
            candyCount--;
            gumballMachine.setCandyCount(candyCount);
            if(candyCount > 0){
                gumballMachine.setState(gumballMachine.noQuarterState);
                return;
            }
        }
        System.out.println("抱歉,糖果已售盡");
        gumballMachine.setState(gumballMachine.soldOutState);
    }
}
/**
 * 售盡的狀態
 */
public class SoldOutState extends State{
    GumballMachine gumballMachine;
    public SoldOutState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    @Override
    public void insertQuarter() {
        System.out.println("糖果已經售盡");
        returnQuarter();
    }
    @Override
    public void ejectQuarter() {
        System.out.println("沒有投幣,無法退幣");
    }
    @Override
    public void turnCrank() {
        System.out.println("糖果已經售盡");
    }
    @Override
    public void dispense() {
        System.out.println("糖果已經售盡");
    }
}
//3、將糖果機的動作委托到狀態類
public class GumballMachine extends State{
    public State noQuarterState = new NoQuarterState(this);
    public State hasQuarterState = new HasQuarterState(this);
    public State soldState = new SoldState(this);
    public State soldOutState = new SoldOutState(this);
    private State state = soldOutState;
    private int candyCount = 0;
    public GumballMachine(int count) {
        this.candyCount = count;
        if(count > 0)
            setState(noQuarterState);
    }
    @Override
    public void insertQuarter() {
        state.insertQuarter();
    }
    @Override
    public void ejectQuarter() {
        state.ejectQuarter();
    }
    @Override
    public void turnCrank() {
        state.turnCrank();
    }
    @Override
    public void dispense() {
        state.dispense();
    }
    public void setState(State state) {
        this.state = state;
    }
    public State getState() {
        return state;
    }
    public void setCandyCount(int candyCount) {
        this.candyCount = candyCount;
    }
    public int getCandyCount() {
        return candyCount;
    }
}

從代碼里面可以看出,糖果機根據此刻不同的狀態,而使對應的動作呈現不同的結果。這份代碼已經可以滿足我們的基本需求,但稍微思考一下,你會覺得這種實現代碼似乎,功能太復雜了,擴展性很差,沒有面向對象的風格。

假設由于新需求,要增加一種狀態,那每個動作方法我們都需要修改,都要重新增加一條else語句。而如果需求變更,某個狀態下的動作需要修改,我們也要同時改動四個方法。這樣的工作將是繁瑣而頭大的。

可以發現,這種模式下,糖果機根本不需要清楚狀態的改變,它只用調用狀態的方法就行。狀態的改變是在狀態內部發生的。這就是"狀態模式"。

如果此時再增加一種狀態,糖果機不需要做任何改變,我們只需要再增加一個狀態類,然后在相關的狀態類方法里面增加轉換的過程即可

  1. 除常用方法(如 getXxx/isXxx)等外,不要在條件判斷中執行其它復雜的語句,將復雜邏輯判斷的結果賦值給一個有意義的布爾變量名,以提高可讀性。

說明:很多 if 語句內的邏輯相當復雜,閱讀者需要分析條件表達式的最終結果,才能明確什么樣的條件執行什么樣的語句,那么,如果閱讀者分析邏輯表達式錯誤呢?

1
2
3
4
5
6
7
8
9
10
正例:
// 偽代碼如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
...
}
反例:
if ((file.open(fileName, "w") != null) && (...) || (...)) {
...
}

(八)注釋規范

  1. 類、類屬性、類方法的注釋必須使用 Javadoc 規范,使用/**內容*/格式,不得使用// xxx 方式

  1. 所有的抽象方法(包括接口中的方法)必須要用 Javadoc 注釋、除了返回值、參數、異常說明外,還必須指出該方法做什么事情,實現什么功能。

  1. 方法內部單行注釋,在被注釋語句上方另起一行,使用//注釋。方法內部多行注釋使用/ /注釋,注意與代碼對齊。

  1. 所有的枚舉類型字段必須要有注釋,說明每個數據項的用途。

  1. 代碼修改的同時,注釋也要進行相應的修改,尤其是參數、返回值、異常、核心邏輯等的修改。代碼和注釋要同步更新

  1. 對于注釋的要求:第一、能夠準確反應設計思想和代碼邏輯;第二、能夠描述業務含義,使別的程序員能夠迅速了解到代碼背后的信息。注釋要盡可能精簡準確、表達到位,要避免過多過濫的注釋。

  1. 特殊注釋標記,請注明標記人與標記時間。注意及時處理這些標記,通過標記掃描,經常清理此類標記。線上故障有時候就是來源于這些標記處的代碼。

  1. 待辦事宜(TODO):( 標記人,標記時間,[預計處理時間])表示需要實現,但目前還未實現的功能。這實際上是一個 Javadoc 的標簽,目前的 Javadoc還沒有實現,但已經被廣泛使用。只能應用于類,接口和方法(因為它是一個 Javadoc 標簽)。

  1. 錯誤,不能工作(FIXME):(標記人,標記時間,[預計處理時間])在注釋中用 FIXME 標記某代碼是錯誤的,而且不能工作,需要及時糾正的情況。

(九)其他

  1. 獲取當前毫秒數 System.currentTimeMillis(); 而不是 new Date().getTime();說明:如果想獲取更加精確的納秒級時間值,使用 System.nanoTime()的方式。在 JDK8 中,針對統計時間等場景,推薦使用 Instant 類

  1. 不要在controller層加任何復雜的邏輯

  1. 任何數據結構的構造或初始化,都應指定大小,避免數據結構無限增長吃光內存

  1. 一個方法體不要過長,要對邏輯進行拆分,盡量不要超過80行

Tags:java,編程入門,開發規范  
責任編輯:admin
請文明參與討論,禁止漫罵攻擊。 昵稱:注冊  登錄
[ 查看全部 ] 網友評論
    没有任何评论
關于我們 - 聯系我們 - 廣告服務 - 友情鏈接 - 網站地圖 - 版權聲明 - 在線幫助 - 文章列表
返回頂部
刷新頁面
下到頁底
晶體管查詢