我发生在我工作的地方碰到一个Java代码。这里的方案:有2类 - ClassAClassB

ClassA无关除了在它里面4个公共静态最终字符串值。它的目的是使用像ClassA.variable这些值(不要问我为什么,这不是我的代码)。

ClassB进口ClassA。我在ClassA编辑的字符串值,并编译它。当我跑ClassB我可以看到它是使用旧值 - 而不是新值。我不得不重新编译ClassB,以使它使用新值从ClassA! (我不得不重新编译进口ClassA其他类!)

这是仅仅是因为JDK 1.6的或者我应该早知道重新编译ClassB也!开导我。 :)

有帮助吗?

解决方案

如果从类finalClassA变量的值碰巧是编译时间常数,编译器可能已经使用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的的静态初始化运行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top