对 class 加载时未知的常量使用 final 和 static

Usage of final and static for a constant that is unknown at class load-up

在 class 中,我声明了一个字段,该字段从分配开始就不会更改。 class.

的所有实例也共享此字段(或者更准确地说是常量)

出于上述两个原因,我使用

final

static

声明常量时的关键字。

但是,因为我同时使用了 final 和 static,所以我需要在声明中赋值,因为常量是在加载 class 时赋值的。不幸的是,在这种情况下,这无法完成,因为程序从一开始就不知道该值,只有在实例化 class 时才知道(因为它的值由程序计算)。因此,必须根据传递给它的参数在 class 的构造函数中为其分配值。

如前所述,这在 java 中是非法的。

我不知道如何解决这个问题。一切都表明我应该同时使用 static 和 final,因为该字段由 class 的所有实例共享,并且从为其分配值的那一刻起就不会改变。

此外,根据 Android 文档,使用 final 关键字具有以下优点:

accesses to [a final field] will use a relatively inexpensive "string constant" instruction instead of a field lookup.

此外,使用 static 关键字的优点是所有实例只使用一个字段,而不是每个实例使用一个字段。

因此,出于性能原因,我能够同时使用这两个关键字非常重要。

总结:我需要同时使用 final 和 static,但是,因为常量的值在 class 加载时未知,所以我不能这样做。是否有解决方法,以便我仍然可以使用 final 和 static 作为常量?

没有。如果静态字段是最终的,则必须内联初始化它:

public static final String CONSTANT = "blah";

或在静态初始化程序中:

public static final String CONSTANT;
static {
    CONSTANT = "blah";
}

关于如何解决它,这听起来像是一个奇怪的设计,你想在构造函数中初始化值,但它被所有实例使用。构造第二个实例时会发生什么?是否忽略了该参数的值?

我建议你用静态方法替换你的静态常量,因为你实际上需要控制某个值是否已经被初始化:

public final class MyConstants
{
    private MyConstants(){}

    private static <type> constant1;

    public static void setConstant1(<type> value)
    {
        if (constant1==null)
        {
            throw new IllegalStateException("Constant1 clready initialized");
        }
        else
        {
            constant1=value;
        }
    }

    public static <type> getConstant1()
    {
        if (constant1==null)
        {
            throw new IllegalStateException();
        }
        return constant1;
    }
}

通过这种方式,您可以向常量添加一个协议 class:常量必须在第一次初始化之前 一次 并且只初始化一次用过。

使用singleton

这里的想法是使用单例对象来保存单个实例。该实例可以在您需要创建时在运行时创建。

您可以让实例随心所欲。一旦初始化,就不能再更改。最终的、静态的和运行后可初始化的。

您可以稍微阅读一下如何使用 singletons here

编辑:

正如评论中指出的那样,请务必了解单例的缺点。如果您有兴趣,popular post 中有更多信息。