[英]public static final variable in an imported java class
我碰巧在我的工作场所遇到过Java代码。 这是场景:有两个类 - ClassA
和ClassB
。
ClassA
中除了4个公共静态最终字符串值之外什么都没有。 它的目的是使用像ClassA.variable
这样的值(不要问我原因,这不是我的代码)。
ClassB
导入ClassA
。 我在ClassA
编辑了字符串值并对其进行了编译。 当我运行ClassB
我可以看到它使用的是旧值 - 而不是新值。 我不得不重新编译ClassB
以使其使用ClassA
新值! (我不得不重新编译导入ClassA
其他类!)
这只是因为JDK 1.6或我之前应该知道重新编译ClassB
! 开导我。 :)
如果类ClassA
中的final
变量的值恰好是编译时常量,则编译器可能已使用ClassA
它们内联到类中,而不是生成运行时引用。 我想,这就是你所描述的情况。
例:
public class Flags {
public static final int FOO = 1;
public static final int BAR = 2;
}
public class Consumer {
public static void main(String[] args) {
System.out.println(Flags.FOO);
}
}
在此示例中,编译器可能会将FOO
的值合并到为Consumer
生成的代码中,而不是生成等效的运行时引用。 如果稍后更改FOO
的值,则必须重新编译Consumer
以使其使用新值。
这是一种优化,在编译程序的效率和速度方面具有一些优点。 例如,内联该值可能会在使用它的表达式中进一步优化,例如:
int x = Flags.FOO * 10;
在这个例子中,内联值(这里:1)使编译器能够注意到,乘法没有区别,并且可以完全省略。
这是二进制兼容性问题。 在编译时解析对常量字段的引用。 你看到的行为是正确的; 如果更改A类中的值,则必须重新编译客户端(B类)。 为避免此类问题,请考虑使用Java 5.0版中引入的枚举类型添加常量。
假设ClassA看起来像这样:
public class ClassA {
public static final int FOO = 1;
public static final int BAR = 2;
}
如果重新编译它,ClassB将继续使用旧值。 我想这可能取决于编译器,但我认为这是典型的行为。 如果您不希望每次ClassA中的常量更改时重新编译ClassB,您将必须执行以下操作:
public class ClassA {
public static final int FOO = CONST(1);
public static final int BAR = CONST(2);
public static int CONST(int i) { return i; }
}
因为现在javac不愿意内联常量。 相反,当ClassA的静态初始化程序运行时,它将调用CONST(int)方法。
你为什么要单独编译这些类?
使用像maven或ant这样的构建系统,或者让IDE执行它。
唯一安全的做法是重新编译每个依赖于java类的java,这个java已经改变,直到每个可以生成的类都被重新编译。
如果您没有在交换机中使用这些值,则可以执行以下操作:
public class A
{
public static final int FOO;
public static final String BAR;
static
{
FOO = 42;
BAR = "Hello, World!";
}
}
然后编译器将不再对使用它们的其他类中的值进行硬编码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.