参考方法时最终的静态变化是什么?

时间:2014-04-24 20:03:55

标签: java static final

final static字段的值在引用方法时是否会发生变化?例如,如果您运行以下代码:

private static final String example = Example.getExampleString();

当方法example返回不同的内容时,getExampleString()的值是否会发生变化?

4 个答案:

答案 0 :(得分:3)

您问题中的代码是初始值设定项。因此,Example.getExampleString()在变量首次在内存中定义时被称为一次,之后,example将包含函数返回的值,一次被调用

因此,如果您运行程序两次,变量可能会为每次运行设置不同的值,但是一旦设置了变量,就无法在程序运行时更改它。

举个例子,试试这个:

import java.util.Random;

public class VarTest {
    private static final Random rng = new Random();
    private static final String example = Integer.toString(rng.nextInt());

    public static void main(String[] args) {
        System.out.println(example);
        System.out.println(rng.nextInt());
        System.out.println(rng.nextInt());
        System.out.println(example);
    }
}

如果您运行此程序,您会看到nextInt每次调用都会返回不同的值,但example在程序中保持不变。如果再次运行它,example可能与上次运行时不同,但example在运行时仍未更改。 (由于example的工作原理,您可能需要在两次运行之间等待几秒钟或几分钟才能看到Random的不同值。)

答案 1 :(得分:1)

不,它不能。 examplefinal,并在初始化类时初始化为getExampleString()返回的参考值。由于它是final,因此无法使用其他参考值重新分配变量。

您可以通过反射来完成,但这与您在初始化表达式中调用的方法无关。

答案 2 :(得分:0)

忘记变量最终为静态的部分,方法本身只调用一次以提供String。

答案 3 :(得分:0)

既然您询问是否可以,那么答案是 ,不幸的是是
但是你需要记住final字段的目的是让程序员只设置一次它的值,所以你永远不应该试图改变它
以下是您如何做到这一点的示例,但这仅用于(不良)教育目的。


由于Example.getExampleString()的结果不能被视为编译时常量表达式,因此example不被视为常量变量,因此其值不会在使用example的代码中内联。所以基于this answer,您可以执行类似

的操作
class Example {

    private static final String example = Example.getExampleString();

    private static String getExampleString() {
        return "foo";
    }

    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

        field.set(null, newValue);
    }

    public static void main(String[] args) throws Exception {
        System.out.println(Example.example);
        setFinalStatic(Example.class.getDeclaredField("example"), "bar");
        System.out.println(Example.example);
    }
}

将返回

foo
bar

因此,在这种情况下,您可以更改example字段的值。