雷火电竞-中国电竞赛事及体育赛事平台

歡迎來到入門教程網(wǎng)!

Java編程

當前位置:主頁 > 軟件編程 > Java編程 >

Java編程中的一些常見問題匯總

來源:本站原創(chuàng)|時間:2020-01-10|欄目:Java編程|點擊:

本文列舉了我在周圍同事的Java代碼中看到的一些比較典型的錯誤。顯然,靜態(tài)代碼分析(我們團隊用的是qulice)不可能發(fā)現(xiàn)所有的問題,這也是為什么我要在這里列出它們的原因。

如果你覺得少了什么,請不吝賜教,我會很樂意把它們加上。

下面列出的所有這些錯誤基本都與面向?qū)ο缶幊逃嘘P(guān),尤其是Java的OOP。

類名

讀下這篇短文“什么是對象”。類應該是真實生活中的一個抽象實體,而不是什么“validators”,“controller”, “managers”這些東西。如果你的類名以”er”結(jié)尾的話——那它就是個糟糕的設(shè)計。

當然了,工具類也是反模式,比如說Apache的StringUtils, FileUtils, 以及IOUtils。上面這些都是糟糕設(shè)計的代表。延伸閱讀:OOP中工具類的替代方案。

當然,不要使用前綴或者后綴來區(qū)分類和接口。比方說,這些名字就是錯誤的:IRecord, IfaceEmployee, 或者RecordInterface。通常來說,接口名應該是真實生活中的實體的名字,類名應該可以說明它的實現(xiàn)細節(jié)。如果這個實現(xiàn)沒有什么特別可說明的,可以把它叫作Default, Simple或者類似的什么。比如說:

復制代碼 代碼如下:

class SimpleUser implements User {};
class DefaultRecord implements Record {};
class Suffixed implements Name {};
class Validated implements Content {};

方法名

方法可以返回值也可以返回void。如果方法返回值的話,它的名字應該能說明它返回了什么,比如說(永遠也不要使用get前綴):

復制代碼 代碼如下:

boolean isValid(String name);
String content();
int ageOf(File file);

如果它返回void,那么它的名字應該要說明它做了什么。比如:

復制代碼 代碼如下:

void save(File file);
void process(Work work);
void append(File file, String line);

剛才提到的這些規(guī)則只有一個例外——JUnit的test方法不算。下面將會說到這個。

test方法的名字

在JUnit的測試用例中,方法名應該是沒有空格的英文語句。用一個例子來說明會更清楚一些:

復制代碼 代碼如下:

/**
 * HttpRequest can return its content in Unicode.
 * @throws Exception If test fails
 */
public void returnsItsContentInUnicode() throws Exception {
}

你的JavaDoc里的第一句話的開頭應該是你要測試的那個類的名字,然后是一個can。因此,你的第一句話應該是類似于“somebody can do something”。

方法名也是一樣的,只是沒有主題而已。如果我在方法名中間加一個主題的話,我就能得到一個完整的句子,正如上面那個例子中那樣:“HttpRequest returns its content in unicode”。

請注意test方法的名字是不以can開頭的。只有JavaDoc里的的注釋會以can開頭。除此之外,方法名不應該以動詞開頭。

實踐中最好將測試方法聲明為拋出Exception的。

變量名

避免組合的變量名,比如說timeOfDay, firstItem,或者httpRequest。類變量及方法內(nèi)的變量都是如此。變量名應該足夠長,避免在它的可見作用域內(nèi)產(chǎn)生歧義,但是如果可以的話也不要太長。名字應該是單數(shù)或復數(shù)形式的名詞,或者是一個適當?shù)目s寫。比如:

復制代碼 代碼如下:

List<String> names;
void sendThroughProxy(File file, Protocol proto);
private File content;
public HttpRequest request;

有的時候,如果構(gòu)造方法要將入?yún)⒈4娴揭粋€新初始化的對象中的時候,它的參數(shù)和類屬性的名字可能會沖突。這種情況,我建議是去掉元音,使用縮寫。

示例:

復制代碼 代碼如下:

public class Message {
  private String recipient;
  public Message(String rcpt) {
    this.recipient = rcpt;
  }
}

很多時候,看一下變量的類名就知道變量該取什么名字了。就用它的小寫形式就好了,像這樣就很靠譜:

復制代碼 代碼如下:

File file;
User user;
Branch branch;

然而,基礎(chǔ)類型的話,永遠不要這么做,比如Integer number或者String string。

如果存在多個不同性質(zhì)的變量的話,可以考慮下使用形容詞。比如:

復制代碼 代碼如下:

String contact(String left, String right);

構(gòu)造方法

不考慮異常的話,應該只有一個構(gòu)造方法用來將數(shù)據(jù)存儲到對象變量中。其它構(gòu)造方法則使用不同的參數(shù)來調(diào)用這個構(gòu)造方法。比如說:

復制代碼 代碼如下:

public class Server {
  private String address;
  public Server(String uri) {
    this.address = uri;
  }
  public Server(URI uri) {
    this(uri.toString());
  }
}

一次性變量

無論如何都應該避免使用一次性變量。這里我所說的“一次性“指的是只使用一次的變量。比如下面這個:

復制代碼 代碼如下:

String name = "data.txt";
return new File(name);

上述的變量只會使用一次,因此這段代碼可以重構(gòu)成這樣:
復制代碼 代碼如下:

return new File("data.txt");

有的時候,比較罕見的情況中——主要是為了格式更好看些——可能會用到一次性變量。然而,還是應當盡量避免這種情況。

異常

毋庸贅言,永遠不要自己吞掉異常,而是應該當它盡量往上傳遞。私有方法應該始終把受檢查異常往外面拋。

不要使用異常來進行流程控制。比方說下面這段代碼就是錯誤的:

復制代碼 代碼如下:

int size;
try {
  size = this.fileSize();
} catch (IOException ex) {
  size = 0;
}

那如果IOException提示“磁盤已滿”的話該怎么辦?你還會認為這個文件大小為0,然后繼續(xù)往下處理?

縮進

關(guān)于縮進,主要的規(guī)則就是左括號要么在該行的末尾,要么就在同一行上閉合(對于右括號來說則相反)。比如說,下面這個就不正確,因為第一個左括號沒有在同一行上閉合,而它后面還有別的字符。第二個括號也有問題,因為它前面有字符,但對應的開括號又沒在同一行上:

復制代碼 代碼如下:

final File file = new File(directory,
  "file.txt");

正確的縮進應該是這樣的:
復制代碼 代碼如下:

StringUtils.join(
  Arrays.asList(
    "first line",
    "second line",
    StringUtils.join(
      Arrays.asList("a", "b")
    )
  ),
  "separator"
);

關(guān)于縮進,第二條重要的規(guī)則就是同時一行中應該盡量多寫一些——上限是80個字符。上面的那個例子并不滿足這點,它還可以收縮一下:
復制代碼 代碼如下:

StringUtils.join(
  Arrays.asList(
    "first line", "second line",
    StringUtils.join(Arrays.asList("a", "b"))
  ),
  "separator"
);

多余的常量

當你希望在類的方法中共享信息的時候,應當使用類常量,這些信息應該是你這個類所特有的。不要把常量當作字符串或數(shù)值字面量的替代品來使用——這是非常糟糕的實踐方式,它會對代碼造成污染。常量(正如OOP中的任何對象一樣)應當在真實世界中有它自己的含義??聪逻@些常量在真實生活中的意思是什么:

復制代碼 代碼如下:

class Document {
  private static final String D_LETTER = "D"; // bad practice
  private static final String EXTENSION = ".doc"; // good practice
}

另一個常見的錯誤就是在單元測試中使用常量來避免測試方法中出現(xiàn)冗余的字符串或者數(shù)值的字面量。不要這么做!每個測試方法都應該有自己專屬的輸入值。

在每個新的測試方法中使用新的文本或者數(shù)值。它們是相互獨立的。那么為什么它們還要共享同樣的輸入常量呢?

測試數(shù)據(jù)耦合

下面是測試方法中數(shù)據(jù)耦合的一個例子:

復制代碼 代碼如下:

User user = new User("Jeff");
// maybe some other code here
MatcherAssert.assertThat(user.name(), Matchers.equalTo("Jeff"));

最后一行中,”Jeff”和第一行中的同一個字符串字面值發(fā)生了耦合。如果過了幾個月,有人想把第三行這個值換一下,那么他還得花時間找出同一個方法中哪里也使用了這個”Jeff”。

為了避免這種情況,你最好還是引入一個變量。

上一篇:Java編程學習的幾個典型實例詳解

欄    目:Java編程

下一篇:詳解Java面向?qū)ο缶幊讨蟹椒ǖ氖褂?/a>

本文標題:Java編程中的一些常見問題匯總

本文地址:http://www.jygsgssxh.com/a1/Javabiancheng/8478.html

網(wǎng)頁制作CMS教程網(wǎng)絡編程軟件編程腳本語言數(shù)據(jù)庫服務器

如果侵犯了您的權(quán)利,請與我們聯(lián)系,我們將在24小時內(nèi)進行處理、任何非本站因素導致的法律后果,本站均不負任何責任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有