0

I use "token", instance of the ValueContainer class declared as final, in order to save data received from a JSON request. Inside the anonymous function, Response.Listener(), I set the value of token and it works.

Log.d("myTag", "token value1:" + token.getValue());

This line displays a correct value (non null). However, when I check the value of token.getValue() again (this time outside the anonymous function)

Log.d("myTag", "token value2:" + token.getValue());

I get token.getValue() = null. I don't understand why token's value seems to be reset to null. Am I missing something?

The full code:

public class MainActivity extends AppCompatActivity {

class ValueContainer<T> {
    private T value;

    public ValueContainer() { }

    public ValueContainer(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final ValueContainer<String> token = new ValueContainer<String>();
    String getTokenUrl = "http://www.someurl.com/?somekey=somevalue";

    JsonObjectRequest getTokenRequest = new JsonObjectRequest(
            Request.Method.GET, getTokenUrl, null, new Response.Listener<JSONObject>() {

        @Override
        public void onResponse(JSONObject response) {
            try {
                token.setValue(response.getString("token"));
                Log.d("myTag", "token value1:" + token.getValue());

                mainTextView.append("Response: JsonObjectRequest successful: get_token: " + token.getValue() + "\n");
            } catch (JSONException e) {
                mainTextView.append("Response: JSONException: getString():" + e);
            }
        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            mainTextView.append("Response: JsonObjectRequest failed: " + error + "\n");
        }
    });
    Log.d("myTag", "token value2:" + token.getValue());
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
flexilef
  • 3
  • 2
  • yes in tokenvalue 2 you are using token instance you have created above in line final ValueContainer token = new ValueContainer(); but in tokenvalue 1 you are seting value it is callback method which may call later – Khizar Hayat Mar 01 '16 at 06:13
  • "tokenvalue 2" gets printed *before* "tokenvalue 1", doesn't it? So it did not get reset. It was not set *yet*. Also, `final` does not do anything to prevent the contained value from changing. – Thilo Mar 01 '16 at 06:20
  • Ahh that makes sense. Thanks. Is there a way to ensure that tokenvalue2 does get set before it's printed? – flexilef Mar 01 '16 at 06:29
  • Possible duplicate of [Final variable manipulation in Java](http://stackoverflow.com/questions/1249917/final-variable-manipulation-in-java) – Radu Ionescu Mar 01 '16 at 06:54

1 Answers1

1

You can change the "real content" of a "final" Object, but you can't change it's address, as the example said blew.

 String stringTest = "test String";

 StringBuffer normalTest = new StringBuffer(stringTest);
 normalTest = normalTest.append(" end");
 normalTest.delete(0, 5);
 System.out.println(normalTest);

 final StringBuffer finalTest = new StringBuffer(stringTest);
// finalTest = finalTest.append(" end"); // can't work;
 finalTest.delete(0, 5);
 System.out.println(finalTest);

you can test by your code as

//token =  new Token("...")// can't work
token.changeTheToken("...")// work ok
  • 1
    Your example is good, But in general final has nothing to do with the content inside it, as java doesn't have **Object Immutability**, `final` is about the `reference` of an object or `address` as explained above – Murtaza Khursheed Hussain Mar 01 '16 at 10:06