在导入的Java类的公共静态最终变量
题
我发生在我工作的地方碰到一个Java代码。这里的方案:有2类 - ClassA
和ClassB
ClassA
无关除了在它里面4个公共静态最终字符串值。它的目的是使用像ClassA.variable
这些值(不要问我为什么,这不是我的代码)。
ClassB
进口ClassA
。我在ClassA
编辑的字符串值,并编译它。当我跑ClassB
我可以看到它是使用旧值 - 而不是新值。我不得不重新编译ClassB
,以使它使用新值从ClassA
! (我不得不重新编译进口ClassA
其他类!)
这是仅仅是因为JDK 1.6的或者我应该早知道重新编译ClassB
也!开导我。 :)
解决方案
如果从类final
的ClassA
变量的值碰巧是编译时间常数,编译器可能已经使用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)。使编译器注意到,该乘法没有差别,并且可以产品总数被省略
其他提示
这是一个二进制兼容性问题。引用常量字段在编译时得到解决。您所看到的行为是正确的;如果你在课堂上的变化值,那么你将不得不重新编译客户端(B类)。为了避免这样的问题,考虑使用枚举类型,在Java引入添加常量5.0版
为什么你想单独编班?
使用一个构建系统,像行家或蚂蚁或只是让你的IDE做到这一点。
唯一安全的事情是重新编译所有的依赖已经改变,直到每一个可能来实现已重新编译类的Java类的Java的。
如果您没有一个开关使用的值可以做到这一点,而不是:
public class A
{
public static final int FOO;
public static final String BAR;
static
{
FOO = 42;
BAR = "Hello, World!";
}
}
,则编译器将不再硬在于使用它们的其它类的代码的值。
假设ClassA的看起来像这样:
public class ClassA {
public static final int FOO = 1;
public static final int BAR = 2;
}
如果你重新编译,ClassB的会继续使用旧的价值观念。我想这可能取决于编译器,但我认为这是典型行为。如果你不想重新编译ClassB的每次在ClassA的变化恒定的,你必须做这样的事情:
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的不愿内联常数。相反,它会调用CONST(int)方法时ClassA的的静态初始化运行。