Referring to a non-final variable data inside an inner class
Im doing a program in GWT. Here is the snippet where Im having problem
private String[] populateRSSData() {
1==>> String[] data = null;
try {
new RequestBuilder(RequestBuilder.GET,
"../database.php?action=populaterss").sendRequest(null,
new RequestCallback() {
@Override
public void onResponseReceived(Request request,
Response response) {
2==>> data=response.getText().split("~");
}
@Override
public void onError(Request request, Throwable exception) {
Window.alert(exception.getMessage());
}
});
} catch (RequestException e) {
Window.alert(e.getMessage());
}
return data;
}
Now the problem arises that I get an error that the variable 1==>>
data
should be declared final
. But if I declare it as final
then i cannot store the datas in 2==>>
The error i get
Cannot refer to a non-final variable data inside an开发者_高级运维 inner class defined in a different method RSS_Manager.java
Please suggest
Even if you manage to get over the error, the function will not do what you intend it to do. The callback you are creating will be notified asynchronously of the response received from server while your method populateRSSData() will return immediately.
You need to rethink your design taking the asynchrony into account.
EDIT: see Getting Used to Asynchronous Calls
EDIT: Quote from the above link
The important issue to understand is that that the code that follows the RPC call invocation will be executed while the actual round trip to the server is still in progress. Although the code inside the onSuccess() method is defined inline with the call, it will not be executed until both the calling code returns back to the JavaScript main loop, and the result message from the server returns.
An easy way out - declare data
as a list of Strings and make the list final. You can always add elements to final list (you just can`t assign a different list to the final variable).
So for your code:
private String[] populateRSSData() {
final List<String> data = new ArrayList<String>();
try {
new RequestBuilder(RequestBuilder.GET,
"../database.php?action=populaterss").sendRequest(null,
new RequestCallback() {
@Override
public void onResponseReceived(Request request,
Response response) {
data.addAll(Arrays.asList(response.getText().split("~"));
}
@Override
public void onError(Request request, Throwable exception) {
Window.alert(exception.getMessage());
}
});
} catch (RequestException e) {
Window.alert(e.getMessage());
}
return data.toArray(new String[data.size()]);
}
You need to use a different data structure for data
which is mutable - you can modify a final
variable, but not assign to it. Perhaps a java.util.Vector
or similar would suit your needs here.
You should either make the data variable a class member (if possible), or wrap it with some object declared as final.
Variables used inside local inner classes must be declared as final. See also: method local innerclasses accessing the local variables of the method.
--EDIT--
Tahir Akhtar pointed out something very important. Besides the general points I mentioned, there is a flaw in your design - the callback is used for asynchronous response. The response may arrive long after the method terminates, so the result will not be assigned yet.
精彩评论