static initialization ordering, are there any guar...
# lucee
d
static initialization ordering, are there any guarantees?
Copy code
import Foo.Bar; // does this trigger a classload of Foo.Bar, or just fixup mappings
component {
    function init() {
        var x = Bar::staticProp; // guaranteed to be init'd?
    }
}
d
you can import that way?
d
yeah but I don't know if it triggers a classload or just patches the mapping lookups
d
I understand your question now. You should try it
d
oh it works, I don't know if it's guaranteed to always work though
d
oh
is this a lucee only feature?
d
maybe so
d
so in your test, is it init'd?
d
@zackster is "Bar::staticProp" guaranteed init'd IF there is a static initializer in Bar for
staticProp
?
yes it is initialized as expected, I want to know if there are any gotchas here though
a
"what happened when you tried it" would be my first response
And if it works then you can say "yeah that thing I asked about works" or if not "oh this thing I expected to work didn't seem to work, here's the code, here's the error, here's what I expected, and here's how my expectations weren't met. So what's up with that?"
d
yeah, the thing I asked about works, but I don't understand what happens when I say Bar::Baz.
I would like insight into the above if anyone has it available. Thanks!
a
It'd be interesting to see what happens if you put a
writeOutput("did this run?")
in the static constructor. When would that appear? On the import? On the access of the static variable?
d
yes, that's a good thing to look into, I'm just about that right now.
1
a
As for
// guaranteed to be init'd?
... no it's absolutely not guaranteed to be inited. Static variables belong to the class, not an object instance of the class. One does not need an object instance of Foo to access Foo::bar
That's the whole thing about static properties.
(and BTW normally I would try code questions I ask, but I CBA cranking up a CFML server to test ATM, and trycf is no help for this sort of thing)
I would expect that the static constructor would be loaded when you first use the static operator on the class name (eg:
Foo::
)
And only once for the lifetime of the JVM. After that first load... it's done.
d
yes, I would also expect uttering
Bar::
would trigger a classload of Bar.cfc, i don't see anything that promises that, so I'm being paranoid.
a
Which is pretty reasonable in CFML situations, sure
I have only used static variables/methods minimally, but they have always behaved as I would expect
👍 1
However I have never needed to understand the timing of their existence; it's been sufficient that when I go
Foo::BAR
that I get an expected value.
Perhaps not an emphatic answer to your question, but you know what I'm like and if anything wasn't to my expectation I'd've made sure to whine about it.
d
talking this out helped me figure out the simple sanity check: while the server is running, create a new CFC file, and access it somewhere exactly once and only in a static way yes, it triggers a classload
d
how do you access it only in a static way?
d
only ever say
SomeComponent::someStaticProp
1
d
ah I see
a
And just an import doesn't trigger it?
(I'd not expect it to)
d
From the lucee docs, I don't understand the second statement "if the component is loaded"
Copy code
// Example3.cfc
Component {
	//instance constructor body
	dump("this is executed every time a new instance is created");
	//static constructor body
	static {
		dump("this is executed only if the component is loaded for the first time");
	}
}
d
if the jvm has the cf-generated class file loaded or not
1
a
Good question. @David Rogers if you adjust your test to only create an instance of
SomeComponent
, but never access any of its static stuff, does its "class" still load?
(I would presume: "yes" again)
d
yes, createObject and new trigger a classLoad (if it hasn't already been loaded)
2
a
I like doing tests like these to get a better uderstanding of what's going on.
Nice work fella
🤘 1
d
Thanks I just learned something new. Now I would just like to know what the benefit is of using static constructs, and some use cases. If either of you have a minute to explain I would really appreciate it.
d
if you got static data, pop it in a static block
d
I guess its that simple. access your static data without the need of creating instances of that class.
a
d
i think they pulled the
static {}
initializer block syntax from java
(in response to "...and I don't know why they chose
static { }
instead of
staticInit() {}
)
1
d
Adam good article
@David Rogers ACF 2021 now supports static constructs too
I found my answer
d
i guess we pay for pathmap lookup everytime we say
Foo::
?
Copy code
import Foo;

sys = createObject("java", "java.lang.System");

function benchSlow() {
    var result = [];
    for (i = 0; i < 100; i++) {
        var start = sys.nanotime();
        var v = Foo::someProp;
        var end = sys.nanotime();
        result.append(end - start)
    }
    writedump((result.avg() / 1e6) & "ms"); // 0.0130ms
}

function bench2() {
    var result = [];
    var someProp = Foo::someProp;

    for (i = 0; i < 100; i++) {
        var start = sys.nanotime();
        var v = someProp;
        var end = sys.nanotime();
        result.append(end - start)
    }
    writedump((result.avg() / 1e6) & "ms"); // .0007ms
}
d
@Adam Cameron why do you use this syntax?
Copy code
static {
   static.CACHE_KEY = "BRICKONE"
}
is
static
scope inside the static block better or required?
a
The pseudo-constructor is only run when objects are created, not when the class is loaded. So if you want static values to be set on the class without an instance of it ever being created, you need to have those assignments in the static initialisation block.
1
a
Just some additional video about static functions by micha

https://youtu.be/B5ILIAbXBzo

👍🏾 1
👏🏾 1
The code of the videos 👆
d
@Andreas I forgot to mention that the video is a really good explanation of how it works and how it can be used.
👍 1