无法为最终变量赋值

时间:2014-11-14 23:31:31

标签: java android http final

这是我的代码:

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。这是什么意思?我尝试删除最终修饰符,但它告诉我我需要让它最终,但是当我这样做时,我得到了那个错误。关于为什么会发生这种情况以及如何解决问题的任何线索?

3 个答案:

答案 0 :(得分:1)

这是与匿名类相关的问题。由于Java的黑魔法创建了实例化类以将变量传递给内部类的环境的副本,因此必须将它们声明为final。更改responseBody1不会更改原始变量,而是更改它的本地引用(因为String是不可变的,您将无法获得您的想法)。

您应该通过外部类的包装器或方法。

答案 1 :(得分:1)

如果创建实现接口的匿名类(例如Runnable),则它访问的任何局部变量必须为final,并且必须在该点确定它们的值。匿名类不允许以外部方法可以看到更改的方式更改这些变量。 (这是Java的一个特性;其他语言允许更改外部局部变量。)

我不推荐一个解决方案,因为它看起来像你的方法无论如何都不会起作用。您创建一个新线程并在其上使用start(),看起来您希望此线程修改responseBody1。但是您的方法会尝试使用responseBody1的值。您无法判断线程是否已达到修改responseBody1的程度,因为您没有做任何事情来等待线程或以任何方式与线程同步。关于设计的其他一些事情需要改变。

但是,一种可能的解决方案是定义一个包含String成员的新类:

static class StringHolder {
    String responseBody1;
}

然后创建一个new StringHolder并为此分配一个final局部变量。虽然无法更改对StringHolder的引用,但线程仍可以更改responseBody1成员。

答案 2 :(得分: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。但我猜是这样。