Java 无法为最终变量赋值

Java 无法为最终变量赋值,java,android,http,final,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

这是我的密码:

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;
    }

我收到错误:
无法为最终变量responseBy1赋值。这是什么意思?我尝试删除最终修改器,但它告诉我需要将其设置为最终修改器,但当我这样做时,我会出现错误。关于为什么会发生这种情况以及如何解决它的任何线索?

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


您应该传递外部类的包装器或方法。

最终属性意味着您保证不修改变量。这就是为什么不能修改变量

如果你被迫使用期末考试,那非常简单:就这样做吧

String newString = responseBody1;
然后根据需要修改新闻字符串

编辑:

只是意识到这不是你想要的。您可以使用将在匿名类中调用的函数

更新:

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) {}
}

现在我不确定它是否必须是一个静态函数和一个静态响应。但是我猜是这样的。

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

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

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

static class StringHolder {
    String responseBody1;
}

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

如果不能修改
final
static
之间的区别是什么?另外,我需要在通过
EntityUtils.toString
加载一些数据后访问
responseBody1
,但我无法访问数据,因为我需要将变量设置为
final
,一旦设置为final,我就无法加载任何数据,然后从threadStatic外部读取数据,这意味着一个类中只有一个变量实例。这意味着这个类的任何对象都可以访问同一个变量。关于responseBody1,我编辑了我的答案。创建一个包含try-catch的静态函数,并在run()内调用该函数@Gaktan该静态函数做什么?如果它返回
字符串
,线程中的
run()
方法将不得不为函数结果赋值,而您还没有解决问题。也许您应该发布一个代码示例来演示您的解决方案。