Java – How to initialize a local variable in Java only once

finalinitializationjavavariable-assignment

In C++, the following code:

#include <stdio.h>

static const char *init()
{
    printf("in init()\n");
}

static void func()
{
    static const char *str = init();
    printf("in func()\n");
}

int main()
{
    for (int i=0; i<10; ++i) {
        func();
    }
    return 0;
}

shows that the despite the numerous invokations of the func(), str is only initialized once by printing a trace message in the function init() used to initialize str. When run, there are a total of 10 lines of trace, once for init() and 10 times for func()

In Java, shouldn't the following code do the same thing?

class test {
    private String init()
    {
        System.out.println("in init()");
        return "FOO";
    }

    private void func()
    {
        final String str = init();
        System.out.println("in func()");
    }

    public test()
    {
        for (int i=0; i<10; ++i) {
            func();
        }
    }

    public static main(String[] args)
    {
        test app = new test();
    }
}

When run, there are 20 lines of output, 10 each for init() and func().
Based on what I read about final variables, I thought it would behave the same way.
So I tried static final and it would not compile (nor just static)
Is there a way to do this? I need to call a time-consuming initialization function from
several different methods in my class, so just moving the variable to class scope wouldn't work.
Further, since local variables are not automatically initialized, I cannot include an if test for null around the variable before assigning it a value.
I suppose I could create a variable at in the class scope for each method in my class, but
managing it would be a pain to manage.
The best analogy would be something if I were to include something like the following in every method:

public myfunc1()
{
    final String funcName = java.lang.Thread.currentThread().getStackTrace()[1].getMethodName();
}
public myfunc2()
{
    final String funcName = java.lang.Thread.currentThread().getStackTrace()[1].getMethodName();
}

funcName in this case will get a unique value in each method, but the initialization is expensive.

Best Solution

The following is a fairly close approximation:

class test {

    private static final String str = init();

    private static String init()
    {
        System.out.println("in init()");
        return "FOO";
    }

    private void func()
    {
        System.out.println("in func()");
    }

    public test()
    {
        for (int i=0; i<10; ++i) {
            func();
        }
    }

    public static void main(String[] args)
    {
        test app = new test();
    }
}

Note that str is initialized when the class is loaded, not when func() is called for the first time.