2014-11-14 113 views
1

這裏是我的代碼:不能將值分配給最後一個變量

public String getGPA() { 
     String gpa = null; 
     final String responseBody1; 
     new Thread(new Runnable(){ 
      public void run() 
      { 
       try { 
        HttpGet httpGet_gpa = new HttpGet("https://somedomain.com" + getRegId() + "&format=P"); 
        HttpResponse response = httpClient.execute(httpGet_gpa); 
        responseBody1 = EntityUtils.toString(response.getEntity()); 
       } catch (ClientProtocolException cpe) { 
        // Ignore 
       } catch (IOException ioe) { 
        // Ignore 
       } 
      } 
     }).start(); 
     Document gpa_doc = Jsoup.parse(responseBody1); 
     Element p = gpa_doc.select("p").first(); 
     gpa = p.text().replace("Your overall GPA (Grade Point Average) to date is:", ""); 
     return gpa; 
    } 

我得到這個錯誤:cannot assign a value to final variable responseBody1。這是什麼意思?我嘗試刪除最終的修飾符,但它告訴我我需要做出最終修改,但是當我這樣做時,我得到了這個錯誤。任何線索爲什麼發生這種情況,以及如何解決它?

回答

1

這就是與匿名類相關的問題。由於Java的黑魔法創建了一個類的實例化環境的副本,將變量傳遞給內部類,所以您必須將它們聲明爲final。更改responseBody1不會更改原始變量,而是本地引用它(因爲String是不可變的,所以您不會獲得您的想法)。

您應該通過包裝或外部類的方法。

0

最終的屬性意味着你保證不要修改變量。這就是爲什麼你不能修改你的變量。

如果你被迫使用最終,它是超級簡單:只是不喜歡這樣

String newString = responseBody1; 

然後修改newString隨你便

編輯:

才意識到,這不是你想要什麼。您可以使用您將在匿名類調用

更新功能:

private static String responseBody1; 

public String getGPA() { 
    new Thread(new Runnable(){ 
     public void run() 
     { 
      fetchResponse(); 
     } 
    }).start(); 
    Document gpa_doc = Jsoup.parse(responseBody1); 
    Element p = gpa_doc.select("p").first(); 
    gpa = p.text().replace("Your overall GPA (Grade Point Average) to date is:", ""); 
    responseBody1 = null; 
    return gpa; 
} 

public static void fetchResponse(){ 
try { 
     HttpGet httpGet_gpa = new HttpGet("https://somedomain.com" + getRegId() + "&format=P"); 
     HttpResponse response = httpClient.execute(httpGet_gpa); 
     responseBody1 = EntityUtils.toString(response.getEntity()); 
    } catch (ClientProtocolException cpe) { 
    } catch (IOException ioe) {} 
} 

現在我不知道,如果它必須是一個靜態函數和靜態responseBody1。但我很確定。

+0

如果你不能修改它,'final'和'static'有什麼區別?另外,我需要在通過'EntityUtils.toString'加載一些數據後訪問'responseBody1',但我無法訪問數據,因爲我需要將該變量設置爲'final',並且一旦將其設置爲最終I無法將任何數據加載到該線程上,然後從線程外部讀取 – SomeProgrammer123 2014-11-14 23:40:05

+0

靜態意味着在類中只會有一個變量的實例。這意味着這個類的任何對象都可以訪問相同的變量。關於responseBody1,我編輯了我的答案。只需用你的try catch創建一個靜態函數,然後在run()中調用該函數() – Gaktan 2014-11-14 23:43:48

+0

@Gaktan這個靜態函數將做什麼?如果它返回'String',那麼線程中的'run()'方法將不得不爲函數結果分配一些東西,並且你還沒有解決問題。也許你應該發佈一個代碼示例來演示你的解決方案。 – ajb 2014-11-14 23:50:34

1

如果您創建一個實現接口的匿名類(如Runnable),則它訪問的任何本地變量必須爲final,並且必須在該點確定它們的值。匿名類不允許以外部方法可以看到更改的方式更改這些變量。 (這是Java的一個特性;其他語言允許改變外部局部變量。)

我不能推薦解決方案,因爲它在我看來像你的方法無論如何不會工作。你創建一個新的線程,並使用start(),它看起來像你期待這個線程修改responseBody1。但是你的方法會嘗試使用responseBody1的值。你不能分辨線程是否已經到達修改responseBody1的地步,因爲你沒有做任何事情來等待線程或以任何方式與它同步。關於設計的其他內容將需要改變。

然而,一個可能的解決方案是定義包含String構件一類新的:

static class StringHolder { 
    String responseBody1; 
} 

然後創建一個new StringHolderfinal局部變量分配給此。儘管無法更改對StringHolder的引用,但線程仍可以更改responseBody1成員。