2016-03-17 56 views
0

我是Java編程新手,我想我已經清楚了什麼是對象以及如何使用它們。你認爲我濫用靜力學嗎?

但是,現在我正在編寫一個程序,我注意到我已經在方法中使用了很多'static'關鍵字,並且我懷疑它是否真的是必須的,邏輯的,還是它是因爲我並沒有在腦海中想到面向對象的概念。

更具體地講,我的程序應該從一個txt文件中讀取,並把每一行中一個ArrayList,這是我的代碼:

public class FileBody { 

    private static final String SEPARATOR = ";"; 
    private static String headerField1 = "regex"; 
    private static String headerField2 = "origin"; 
    private static String headerField3 = "destination"; 
    private static final String HEADER = headerField1 + SEPARATOR + headerField2 
      + SEPARATOR + headerField3 + SEPARATOR; 

    // Getters & setters 

    public static String getHeader() { 
     return HEADER; 
    } 

    public static String getHeaderField1() { 
     return headerField1; 
    } 

    public static void setHeaderField1(String headerField1) { 
     FileBody.headerField1 = headerField1; 
    } 

    public static String getHeaderField2() { 
     return headerField2; 
    } 

    public static void setHeaderField2(String headerField2) { 
     FileBody.headerField2 = headerField2; 
    } 

    public static String getHeaderField3() { 
     return headerField3; 
    } 

    public static void setHeaderField3(String headerField3) { 
     FileBody.headerField3 = headerField3; 
    } 

    // End getters & setters 

    public static File createFileIfNotExists(String path) throws IOException { 
     File file = new File(path); 
     if (file.createNewFile()); 
     return file; 
    } 

    public static File getFile(String path) throws IOException { 
     File file = createFileIfNotExists(path); 
     return file; 
    } 

    public static boolean isEmpty(File file) throws Exception { 
     FileReader fileReader = new FileReader(file); 
     if (fileReader.read() != -1) { 
      fileReader.close(); 
      return false; 
     } else { 
      fileReader.close(); 
      return true; 
     } 
    } 

    public static void writeHeaderToEmptyFile(File file) throws Exception { 
     if (isEmpty(file)) { 
      BufferedWriter bufferedWriter = new BufferedWriter(
        new FileWriter(file, false)); 
      bufferedWriter.write(HEADER); 
      bufferedWriter.close(); 
     } else { 
      return; 
     } 
    } 

    public static ArrayList<String> getLines(File file) throws Exception { 
     ArrayList<String> lines = new ArrayList<>(); 
     BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); 
     while (bufferedReader.ready()) { 
      lines.add(bufferedReader.readLine()); 
     } 
     bufferedReader.close(); 
     return lines; 
    } 

} 

你認爲我可以使用對象做得更好?如果答案是肯定的,你能否給我這樣做的指導方針?

非常感謝您的幫助。

+2

你應該問問自己,你應該怎麼用FileBody類來表示多個文件體。 – Eran

+0

確切地說,您只能擁有一個文件實例 –

+0

不要打擾手動關閉資源 - 請嘗試使用資源。它不那麼冗長,也不太容易出錯。 –

回答

4

可變靜態字段應儘可能避免。特別是,你有什麼將不會工作,因爲他們只有一次初始化。

// only run once even if these fields are changed. 
private static final String HEADER = headerField1 + SEPARATOR + headerField2 
     + SEPARATOR + headerField3 + SEPARATOR; 

最有可能你想要的是

public static String getHeader() { 
    return headerField1 + SEPARATOR + headerField2 
     + SEPARATOR + headerField3 + SEPARATOR; 
} 

這應該是staticSEPARATOR,因爲這是一個不變的唯一領域。我會嘗試將所有其他字段設置爲非靜態字段(以及它們的getter/setter)

您在類的結尾處有一些實用程序/輔助方法。我會把它們放在另一個班,因爲它們看起來沒有關係。即對於這些方法而言具有明確的實用程序類別。例如

class FileBody { 
    public void writeHeaderToEmptyFile(File file) throws IOException { 
     if (!FileUtils.isEmpty(file)) return 
     try (Writer w = new FileWriter(file)) { 
      w.write(getHeader()); 
     } 
    } 
} 

class enum FileUtils { 
    /* no instances */ ; 

    // TODO replace all callers with new File(x); 
    public static File getFile(String filename) { 
     return new File(filename); 
    } 

    public static boolean isEmpty(File file) { 
     return file.length() > 0; 
    } 

    public static List<String> getLines(File file) throws Exception { 
     return Files.readAllLines(Paths.get(file.getAbsolutePath())); 
    } 
} 
+0

感謝您的解釋和例子,他們非常有幫助。我會照你說的去做。 – Arcones

0

讓我們快速瀏覽一下你做了什麼對與錯:

右:

你保持你的私人領域和提供的公共方法來訪問。 +1。

錯誤:

  1. 你保持靜態字段私有。私人領域只能從課堂內部進行訪問(除了反思的情況:我們現在不進入)。因此,將其標記爲靜態不會帶來額外的好處。相反,它將成爲內存開銷(在這種情況下小,但仍然)

  2. 如果根本就想讓它們成爲靜態,那麼應該不會讓它們不可變。靜態字段是類級別字段,不會將它們標記爲最終字段,您允許類的不同對象修改它們,這可能會導致數據損壞。

  3. 現在您正在使用的字符串在Java中具有單獨的內存管理機制。但是,如果你在對象引用中使用相同的代碼(將對象引用標記爲靜態),那麼你會讓對象長時間不必要地在內存中存活,這將對內存產生巨大的壓力。

+0

非常感謝您告訴我這些概念。你能否給我進一步的細節:「私人領域只能從課堂上進行訪問,所以沒有任何額外的好處,你可以將其標記爲靜態。」我知道「私人」關鍵作品的範圍,這就是公開進行獲取者和製作者的原因,但我不太瞭解你爲什麼說他們沒有增加靜態的優勢?你能舉個例子嗎? – Arcones

+0

好的。只要內存中加載了一個類,靜態對象就會保留在內存中(或者您可以說在程序的整個持續時間內)。所以當你使用靜態字段時你會阻止你的記憶(見第3點以獲得更多的參考)。所以他們必須吝嗇使用。 – theLearner