【问题标题】:How to initialize a local variable in Java only once如何在Java中只初始化一次局部变量
【发布时间】:2013-06-04 00:37:27
【问题描述】:

在 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;
}

表明,尽管 func() 被多次调用,str 仅通过在函数 init() 用于初始化 str。运行时,总共有10行trace,一次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();
    }
}

运行时有20行输出,init()func()各10行。 根据我对 final 变量的了解,我认为它的行为方式相同。 所以我尝试了 static final,但它无法编译(也不只是 static) 有没有办法做到这一点?我需要调用一个耗时的初始化函数 我的班级中有几种不同的方法,因此仅将变量移动到班级范围是行不通的。 此外,由于局部变量不会自动初始化,因此在为变量赋值之前,我不能在变量周围包含 if 测试。 我想我可以在类范围内为类中的每个方法创建一个变量,但是 管理它会很痛苦。 如果我在每个方法中都包含以下内容,最好的类比是:

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 在这种情况下会在每个方法中得到一个唯一的值,但是初始化很昂贵。

【问题讨论】:

  • 您需要将字符串 str 和函数 init() 设为静态
  • str 不能是 static,它不会编译。 init() 不能是 static,因为它依赖于实例数据。

标签: java initialization variable-assignment final


【解决方案1】:

以下是相当接近的近似值:

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();
    }
}

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

【讨论】:

  • 如果init() 确实需要上下文,直到类构造或更晚才初始化的成员,将str 初始化为null 并让init() 只做它很长的事情if (str == null)
  • 不幸的是,这并没有提供答案,这就是为什么我在问题的末尾提供了更多示例或 myfunc1() 和 _myfunc2()
【解决方案2】:

final 限定符通过单个方法调用使变量成为常量。

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

private final String str = init();

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

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

private static final String str = init();

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

【讨论】:

  • 不是问题,对每个多次调用的成员函数进行一次初始化调用。见最后的例子:myfunc1()myfunc2()
  • 您也可以使用实例成员来做到这一点 - 只需为 C 中使用静态局部变量的每个方法使用不同的实例成员。
  • 我知道,正如问题中所述,我正在寻找一种更易于管理的解决方案,而不是为我的类中的每个方法创建一个实例变量。
  • 没有太多需要管理的东西。与 C/C++ 的主要区别在于它的 位置(以及选择是按实例还是按类)。如果您愿意,可以将成员字段放在每个方法之前。
猜你喜欢
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 2015-08-23
  • 2016-04-29
  • 1970-01-01
  • 2021-03-17
  • 2016-09-07
  • 1970-01-01
相关资源
最近更新 更多