Umesh Kushwaha Umesh Kushwaha - 1 month ago 7
Java Question

Is it possible to re-reference any final String variable

I have written a same program in two different way and both are giving me different output. i am not able to understand why. please correct me. In first program i am getting this output

Original: Umesh

Changed: Xmesh

And in second program i am getting this output.

Original: Umesh

Changed: Umesh

Program-1

import java.lang.reflect.Field;

public class SomeClass {
public static void main(final String[] args) throws Throwable {
final String s = "Umesh";
changeString(s);
}

// We need a method so the compiler won't inline "s":
static void changeString(final String s) throws Throwable {

System.out.println("Original: " + s);
final Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
final char[] value = (char[]) field.get(s);
value[0] = 'X';
System.out.println("Changed: " + s);
}
}


Program-2

import java.lang.reflect.Field;

public class SomeClass {
public static void main(final String[] args) throws Throwable {
final String s = "Umesh";
System.out.println("Original: " + s);
final Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
final char[] value = (char[]) field.get(s);
value[0] = 'X';
System.out.println("Changed: " + s);
}

}

Answer

The comment in the first program sort of explains why:

// We need a method so the compiler won't inline "s":
static void changeString(final String s) throws Throwable {

As defined by this section of the Java Language Specification (bold is to emphasize the effect of this constant String):

A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28). Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9), and definite assignment (§16 (Definite Assignment)).

The second program has s considered constant because it meets the condition in the above definition whereas the first program has s passed as a method argument. This is why the sysouts in the second program will print the same value as the compiler has resolved the value of s at compile time.

This is also mentioned in section 13.1:

A reference to a field that is a constant variable (§4.12.4) must be resolved at compile time to the value V denoted by the constant variable's initializer.

If such a field is static, then no reference to the field should be present in the code in a binary file, including the class or interface which declared the field. Such a field must always appear to have been initialized (§12.4.2); the default initial value for the field (if different than V) must never be observed.

If such a field is non-static, then no reference to the field should be present in the code in a binary file, except in the class containing the field. (It will be a class rather than an interface, since an interface has only static fields.) The class should have code to set the field's value to V during instance creation (§12.5).

Comments