##Passed by value? No!##
In Lucee all variables are passed by reference always (also in ACF BTW), simply because there is no other way to do it.
Java is supporting primitive types (char,int,boolean,short,long,double,byte) BUT this types are not used in Lucee, simply because we store all data in maps (java.util.Map) and maps only can store Objects.
So if you use for example a number in Lucee, you are using an object from the class java.lang.Double what is a wrapper class for the primitive type “double”.
This example will show you:
executing that example gives you an output like this:
You can see the classes of the objects and the hashcode of the objects, hashcode are unique for every instance, so you clearly see that you have the same object inside the function as you have outside.
So objects are passed by reference always!
##But what about …##
###“passby” with arguments###
You can use the argument “passby” with cfargument (hidden feature in Lucee for backward compatibility for older applications, for example “transfer”)
<cfargument name="arg" passby="value">
this does not really pass by value, it simply clones the object before passing by reference, so it is the same as you would do the following
##ACF is passing arrays by value##
The same as above it only simulates this, in fact they are cloned and pass by reference.
Again passing objects by value is impossible in the JVM.
As @kliakos already explained the following classes are immutable (java.lang… String,Long,Short,Integer,Character,Boolean,Integer …), so if you do the following code
str = "bl";
str &= "ah";
dump(str == "blah"); // equal operator
dump(str === "blah"); // identical operator
hash before - 3146
hash after - 3026417
You do not manipulate an existing string, it is producing a new string, as you can see in the hash dump.
So the point is not that objects are passed by value, problem is that they are immutable, in java we use the class java.lang.StringBuilder or java.lang.StringBuffer (thread safe) to manipulate Strings.
of course you can also use them in CFML as following
But speed wise this is not worth doing it, because the overhead you have with reflection is more than what you win by avoiding to create new objects.
Lucee is well aware of StringBu… objects and can handle them the SAME way as String, so you can do things like this:
1: sb = createObject("java","java.lang.StringBuilder").init("Susi");
4: sb&=" Sorglos";
but this is still producing a new string on line 4, we was already considering to append " Sorglos" in this case to the existing object, but this would break backward compatiblity (also to ACF).
But we could think about it for the Lucee dialect.