When is a constant not a constant?

by Charles Miller on January 13, 2003

Apropos a discussion of the non-final-ness of final fields, a colleague came up with this gem. What does the following code do?


    // By Jed Wesley-Smith
    public String getAString() {
        //get a reference to the private field 
        //value in String class.
        java.lang.reflect.Field stringValue = 
            String.class.getDeclaredField("value");
        //make it accessible
        stringValue.setAccessible(true);
        //unsuspecting string
        String sittingDuck = "sittingDuck!!!!!";
        //black magic happening here
        stringValue.set(sittingDuck, 
              "hastaLaVistaBaby".toCharArray());
        //guess the output of this!
        return "sittingDuck!!!!!";
    }

Clarification: the value field in String isn't actually final, if it were final we wouldn't be able to change the string's value from outside the String class. The thing about final fields not really being final was a catalyst for this code, but wasn't used in it. (Regarding final fields, the JVM only prevents the changing of a final field from outside a class. Technically, a class can change its own final field at any time, and is only prevented from doing so by the compiler. So you can get around the finality of final fields using bytecode manipulation.)

Prior art: Java Specialists' Newsletter: Insane Strings

Correction of Clarification You could still pull an equivalent trick if the value field were final: it's an array, so even if the field were final, the contents of the array would be wide open.

Previously: Avoid Standardsism

Next: Think before you paint