簡體   English   中英

在Java中初始化最終變量的問題

[英]Problems initializing a final variable in Java

我一直在努力解決Java中的一個問題並且它已經開始找到我了,我真的想不出一個正確的解決方法。

我有一個最終的對象屬性,但是動態的。 也就是說,我希望值在指定后保持不變,但每個運行時的值可以不同。 所以我在課程開頭宣布了班級變量 - 比如說private final FILE_NAME; 然后,在構造函數中,我為它賦值 - 比如說FILE_NAME = buildFileName();

當我在buildFileName()方法中拋出異常的代碼時,問題就開始了。 所以我在構造函數中嘗試這樣的東西:

try{
   FILE_NAME = buildFileName();
}
catch(Exception e){
   ...
   System.exit(1);
}

現在我有一個錯誤 - “空白的最終字段FILE_NAME可能尚未初始化。” 這是我開始對Java的嚴格編譯器感到有些惱火的地方。 我知道這不會是一個問題,因為如果它到達catch,程序將退出...但編譯器不知道,因此不允許此代碼。 如果我嘗試在catch中添加一個虛擬賦值,我會得到 - “可能已經分配了最終字段FILE_NAME。” 我顯然不能在try-catch之前分配一個默認值,因為我只能分配一次。

有任何想法嗎...?

怎么樣

String tempName = null;
try{
   tempName = buildFileName();
}
catch(Exception e){
   ...
   System.exit(1);
}
FILE_NAME = tempName;

try {
   FILE_NAME = buildFileName();
} catch (Exception e){
   ...
   System.exit(1);
   throw new Error();
}

或者有人喜歡:

private static final String FILE_NAME = fileName();

private static String fileName() {
    try {
        return buildFileName();
    } catch (Exception e){
        ...
        System.exit(1);
        throw new Error();
    }
}

但是在靜態初始化器中調用System.exit可能是一個壞主意。 它會破壞你的單元測試。

再想一想,我想我剛想出了一個解決方案! - 使用中間變量。

String fileName = null;
try{
   fileName = buildFileName();
}
catch(Exception e){
   ...
   System.exit(1);
}
FILE_NAME = fileName;

不知道為什么我這么久才想到這個......

我個人只會拋出一個錯誤 - 如果你的錯誤流設計得當,System.exit()應該是多余的。 如果拋出錯誤,你的程序可能不會闖入荒野......?

與OP的問題一樣,我必須能夠找到一種方法,將值分配給要從文件系統上的.properties文件讀入的最終字段,因此我的應用程序無法知道這些值。發生了。 使用通用方法調用將.properties文件的內容讀取到應用程序啟動時的Properties對象后分配值是一個Hail Mary傳遞,謝天謝地。 它也限制了沒有。 每次應用程序加載到內存中時,只需通過代碼檢查以查看Properties對象當前是否為null,就必須將文件讀取一次。 但是當然,一旦被分配,最終字段的值不能被改變,除非通過在運行時操作字段的修改定義來改變其“最終”狀態(如在SO上的某些其他地方所討論的,例如https://stackoverflow.com / a / 3301720/1216686 - 偷偷摸摸,但我喜歡它!)。 代碼示例,為簡潔起見省略了典型的運行時錯誤檢查,例如NPE:

import java.util.Properties;

public class MyConstants {

  private static Properties props; // declared, not initialized,
                                   // so it can still be set to
                                   // an object reference.

  public static String MY_STRING = getProperty("prop1name", "defaultval1");
  public static int MY_INT = Integer.parseInt(getProperty("prop2name", "1"));
  // more fields...

  private static String getProperty(String name, String dflt) {
   if ( props == null ) {
     readProperties();
   }
   return props.getProperty(name, dflt);
  } 

  private static void readProperties() {
     props = new Properties(); // Use your fave way to read
                      // props from the file system; a permutation
                      // of Properties.load(...) worked for me.
  } 

  // Testing...
  public static void main(String[] args) {
      System.out.println(MY_STRING);
      System.out.println(MY_INT);
  }

}

這使您可以外部化要讀入應用程序的屬性,並仍然將用於保存其值的字段標記為“最終”。 它還允許您保證最終字段值的返回值,因為Properties類中的getProperty()允許方法的調用代碼傳遞一個默認值,以便在外部找不到屬性的鍵值對時使用.properties文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM