如何只在Java中初始化一个局部变量一次

Xaq*_*Xaq 5 java final initialization variable-assignment

在C++中,以下代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

表明尽管有很多func()的调用,str只是通过在用于初始化str的函数init()中打印跟踪消息来初始化一次.运行时,总共有10行跟踪,一次用于init(),10次用于func()

在Java中,下面的代码不应该做同样的事情吗?

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

运行时,有20行输出,每行为init()func().基于我读到的关于最终变量的内容,我认为它的行为方式相同.所以我尝试了静态final,它不会编译(也不是静态)有没有办法做到这一点?我需要从我的类中的几个不同方法调用一个耗时的初始化函数,所以只是将变量移动到类范围是行不通的.此外,由于局部变量没有自动初始化,我不能包含if测试为null在为变量赋值之前围绕变量.我想我可以在类的范围内为我的类中的每个方法创建一个变量,但是管理它会很难管理.如果我在每种方法中都包含以下内容,那么最好的比喻就是:

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

在这种情况下,funcName将在每个方法中获得唯一值,但初始化是昂贵的.

NPE*_*NPE 5

以下是一个非常接近的近似值:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

注意,str在加载类时初始化,而不是在func()第一次调用时初始化.


And*_*mas 2

限定符final通过单个方法调用使变量保持不变。

由于您希望每个实例都有一个值,因此可以在方法外部使用实例成员变量。

private final String str = init();

private void func()
{
    System.out.println("in func()");
}
Run Code Online (Sandbox Code Playgroud)

如果您希望所有实例的所有方法调用都使用单个值,则可以在方法外部使用静态成员变量。

private static final String str = init();

private void func()
{
    System.out.println("in func()");
}
Run Code Online (Sandbox Code Playgroud)