导入的 java 类中的公共静态最终变量
我碰巧在工作场所遇到了一段Java代码。场景如下:有 2 个类 - ClassA
和 ClassB
。
ClassA
除了里面有 4 个公共静态最终字符串值之外什么都没有。它的目的是使用像 ClassA.variable 这样的值(不要问我为什么,这不是我的代码)。
ClassB
导入 ClassA
。我编辑了 ClassA 中的字符串值并编译了它。当我运行 ClassB 时,我可以看到它使用的是旧值,而不是新值。我必须重新编译 ClassB
才能使其使用 ClassA
中的新值! (我必须重新编译导入 ClassA
的其他类!)
这仅仅是因为 JDK 1.6 还是我应该早点知道重新编译 ClassB
!启发我。 :)
I happen to come across a Java code at my work place. Here's the scenario: There are 2 classes - ClassA
and ClassB
.
ClassA
has nothing except 4 public static final string values inside it. Its purpose is to use those values like ClassA.variable
(don't ask me why, it's not my code).
ClassB
imports ClassA
. I edited the string values in ClassA
and compiled it. When I ran ClassB
I could see it was using the old values - not the new values. I had to recompile ClassB
to make it use new values from ClassA
! (I had to recompile other classes that imports ClassA
!)
Is this just because of JDK 1.6 or I should have known earlier to recompile ClassB
also! Enlighten me. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果类
ClassA
中的final
变量的值恰好是编译时常量,则编译器可能已使用ClassA
将它们内联到类中而不是生成运行时引用。我想,这就是你所描述的案例中发生的情况。示例:
在此示例中,编译器可能会将
FOO
的值合并到为Consumer
生成的代码中,而不是生成等效的运行时引用。如果FOO
的值稍后发生变化,您将必须重新编译Consumer
才能使其使用新值。这是一种优化,在程序编译的效率和速度方面具有一些优势。例如,内联该值可能会在使用它的表达式中启用进一步的优化,例如:
在本例中,内联该值(此处:1)使编译器能够注意到,乘法没有区别,可以省略总而言之。
If the values of the
final
variables from classClassA
happen to be compile-time constants, the compiler might have inlined them into the classes usingClassA
instead of generating a run-time reference. I think, this is what happened in the case you described.Example:
In this example, the compiler will likely incorporate the value of
FOO
into the code generated forConsumer
instead of generating the equivalent run-time reference. If the value ofFOO
changes later on, you will have to re-compileConsumer
in order to have it use the new value.This is an optimization, which has a few advantages with respect to efficiency and speed of the program compiled. For example, inlining the value might enable further optimizations in the expressions, which use it, for example:
In this example, inlining the value (here: 1) enables the compiler to notice, that the multiplication makes no difference, and can be omitted alltogether.
这是一个二进制兼容性问题。对常量字段的引用在编译时解析。您所看到的行为是正确的;如果更改 A 类中的值,则必须重新编译客户端(B 类)。为了避免此类问题,请考虑使用 Java 版本 5.0 中引入的枚举类型添加常量。
It's a binary compatibility issue. References to constant fields are resolved at compile time. The behaviour you are seeing is correct; if you change the values in class A then you will have to re-compile the client (class B). To avoid such problems consider adding constants using an enum type, introduced in Java release 5.0.
假设 ClassA 看起来像这样:
如果重新编译它,ClassB 将继续使用旧值。我想这可能取决于编译器,但我认为这是典型的行为。如果您不想每次 ClassA 中的常量更改时都重新编译 ClassB,则必须执行以下操作:
因为现在 javac 不愿意内联常量。相反,当 ClassA 的静态初始化程序运行时,它将调用 CONST(int) 方法。
Suppose ClassA looks like this:
If you recompile it, ClassB will continue using the old values. I guess it could depend on the compiler, but I think this is the typical behaviour. If you don't want to recompile ClassB everytime a constant in ClassA changes, you'll have to do something like this:
Becuase now javac is unwilling to inline the constants. Instead it will call the CONST(int) method when ClassA's static initializer runs.
你为什么要尝试单独编译这些类?
使用 Maven 或 ant 等构建系统,或者让您的 IDE 来完成。
唯一安全的做法是重新编译依赖于已更改的 java 类的每个 java,直到重新编译所有可能受影响的类。
Why are you trying to compile the classes individually?
Use a build system like maven or ant or just let your IDE do it.
The only safe thing to do is to recompile every java which depends of a java class which has changed until every class which could be effected has been re-compiled.
如果您不使用开关中的值,则可以这样做:
然后编译器将不再对使用它们的其他类中的值进行硬编码。
If you are not using the values in a switch you can do this instead:
then the compiler will no longer hard code the values in the other classes that are using them.