javastringjvm

Java String pool and type casting


My question is in regard to the way Java handles String literals. It's quite clear from the Java Language Specs (JLS) that String literals are being implicitly interned - in other words, objects that are created in the String constant pool part of the heap, in contrast to the heap-based objects created when calling new String("whatever").

What doesn't seem to line up with what the JLS says is that when creating a new String using String concatenation with a casted constant String type, which should be considered as a constant String as per the JLS, apparently the JVM is creating a new String object rather than interning it implicitly. I appreciate any explanation about this particular behaviour and whether or not this is a platform-specific behaviour. I am running on a Mac OSX Snow Leopard.

public class Test
{
    public static void main(String args[])
    {
        /*
            Create a String object on the String constant pool
            using a String literal
        */
        String hello = "hello";
        final String lo = "lo"; // this will be created in the String pool as well
        /*
            Compare the hello variable to a String constant expression
            , that should cause the JVM to implicitly call String.intern()
        */
        System.out.println(hello == ("hel" + lo));// This should print true
        /*
            Here we need to create a String by casting an Object back
            into a String, this will be used later to create a constant
            expression to be compared with the hello variable
        */
        Object object = "lo";
        final String stringObject = (String) object;// as per the JLS, casted String types can be used to form constant expressions
        /*
            Compare with the hello variable
        */
        System.out.println(hello == "hel" + stringObject);// This should print true, but it doesn't :(

    }
}

Solution

  • Casting to Object is not allowed in a compile time constant expression. The only casts permitted are to String and primitives. JLS (Java SE 7 edition) section 15.28:

    > - Casts to primitive types and casts to type String

    (There's actually a second reason. object isn't final so cannot possibly by considered a constant variable. "A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable." -- section 4.12.4.)