ColdFusion is built on top of Java. This is huge part of why ColdFusion is such a sexy programming language. Because of this relationship, all of the ColdFusion data types (String, Query, Struct, Array, etc.) are really just custom Java classes that are built on top of things like strings, record sets, hash tables, collections, etc.. While this is an undocumented feature, this structure gives our beloved ColdFusion objects dot-style invocable methods that hook directly into the underlying Java objects.
For example, ColdFusion strings can be used in such a way:
<cfset strValue = "This is my ColdFusion string value." /> <cfset strValue = strValue.Trim() /> <cfset strValue = strValue.ReplaceAll( ... ) /> <cfset strValue = strValue.ReplaceFirst( ... ) /> <cfset arrParts = strValue.Split( ... ) />
Now, this makes way for some hugely powerful functionality (such as the use of Java's regular expressions which are much more powerful that ColdFusion's regular expressions), but again, I stress that this is totally undocumented.
At CFUNITED-07, I attended the final FAQ session and asked the speakers if Adobe was planning to document these beautiful, underlying Java methods that can be called directly on the ColdFusion objects. Ray Camden stepped up here and pretty much smacked my inquiry down. He did not do this in a negative way (Ray's the man, we all know that), he was merely pointing out the fact that if you use undocumented features and then ColdFusion's implementation changes, you might screw over your clients.
I can respect this answer and I went on my way, a bit disheartened with my tail between my legs.
But then, I had an epiphany! Not only can you access these underlying Java methods on the String object, ColdFusion forces you to! It wants you to! It pulls you close against her and whispers softly, "Go ahead, play with my underlying Java methods".
Here's what I realized; let's say you wanted to be good and not invoke the underlying Java methods of the ColdFusion string. To get around this, you could use ColdFusion's Create Object() method to create a real Java String object and initialize it with a ColdFusion string. This would give you access to all the Java String methods:
<!--- Since we don't want to use the Java methods on the string, let's create an actual Java string and then use the methods on that. ---> <cfset objString = CreateObject( "java", "java.lang.String" ).Init( JavaCast( "string", "I am a ColdFusion string in Java" ) ) /> <!--- At this point, objString is now a Java String and we can use it's object methods to manipulate the inner value. ---> <cfset objString = objString.ReplaceFirst( JavaCast( "string", "ColdFusion" ), JavaCast( "string", "Sexy ColdfFusion" ) ) /> <!--- Output the new string value. Convert the Java string to a ColdFusion string using the ToString() method. ---> #ToString( objString )#
As you can see, we are creating a real Java string object so that we can use the .Replace First() method. We are then converting that Java String object to a ColdFusion string and outputting the value. Running the above code, we get the following output:
I am a Sexy ColdFusion string in Java
Ok, now here's the twist - when you create a Java String object using Create Object(), ColdFusion doesn't allow you to keep the Java object. Instead, it takes that object and immediately converts it into a ColdFusion string object (ColdFusion strings really are Java strings, so there is no conversion, but I am trying to make a point). To prove this, let's create two Java objects using Create Object() and then test what kind of values they are:
<!--- Create one Java String object that holds a Java String instance with explicit value. ---> <cfset objJavaString = CreateObject( "java", "java.lang.String" ).Init( JavaCast( "string", "Hello" ) ) /> <!--- Create ont Java StringBuffer object that is empty. ---> <cfset objJavaBuffer = CreateObject( "java", "java.lang.StringBuffer" ).Init() /> <!--- Check to see if these JAVA OBJECT are considered simple values or complext objects. They are both created in the same way and should act accordingly. ---> IsSimpleValue: #IsSimpleValue( objJavaString )#<br /> IsObject: #IsObject( objJavaString )#<br /> <br /> IsSimpleValue: #IsSimpleValue( objJavaBuffer )#<br /> IsObject: #IsObject( objJavaBuffer )#<br />
Here, we are creating two Java Objects, one of type String and one of type StringBuffer. Running the above code we get the following output:
As you can see, ColdFusion is telling us that the Java String is NOT an object, but rather a ColdFusion simple value. Furthermore, it is telling us that the Java StringBuffer IS an object. Both of these were created in the same way, so why do they act differently? Simple - ColdFusion will not allow you to keep a Java String object - it will take that object and immediately convert it into a ColdFusion string (again, I'm trying to make a point).
So what does this all mean? Basically, it means that ColdFusion is forcing you to use ColdFusion strings even when accessing the underlying Java methods. While this cannot necessarily be extended to include all ColdFusion data types, I think this makes it very clear that ColdFusion wants you access the underlying Java String methods directly on ColdFusion string values; it's forcing you to.
Want to use code from this post? Check out the license.