导入的 java 类中的公共静态最终变量

发布于 2024-08-10 20:17:19 字数 461 浏览 6 评论 0原文

我碰巧在工作场所遇到了一段Java代码。场景如下:有 2 个类 - ClassAClassB

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

┾廆蒐ゝ 2024-08-17 20:17:19

如果类 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)使编译器能够注意到,乘法没有区别,可以省略总而言之。

If the values of the final variables from class ClassA happen to be compile-time constants, the compiler might have inlined them into the classes using ClassA instead of generating a run-time reference. I think, this is what happened in the case you described.

Example:

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);
    }
}

In this example, the compiler will likely incorporate the value of FOO into the code generated for Consumer instead of generating the equivalent run-time reference. If the value of FOO changes later on, you will have to re-compile Consumer 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:

int x = Flags.FOO * 10;

In this example, inlining the value (here: 1) enables the compiler to notice, that the multiplication makes no difference, and can be omitted alltogether.

故笙诉离歌 2024-08-17 20:17:19

这是一个二进制兼容性问题。对常量字段的引用在编译时解析。您所看到的行为是正确的;如果更改 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.

分開簡單 2024-08-17 20:17:19

假设 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) 方法。

Suppose ClassA looks like this:

public class ClassA {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

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:

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; }
}

Becuase now javac is unwilling to inline the constants. Instead it will call the CONST(int) method when ClassA's static initializer runs.

夜巴黎 2024-08-17 20:17:19

你为什么要尝试单独编译这些类?

使用 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.

一笑百媚生 2024-08-17 20:17:19

如果您不使用开关中的值,则可以这样做:

public class A
{
    public static final int FOO;
    public static final String BAR;

    static
    {
        FOO = 42;
        BAR = "Hello, World!";
    }
}

然后编译器将不再对使用它们的其他类中的值进行硬编码。

If you are not using the values in a switch you can do this instead:

public class A
{
    public static final int FOO;
    public static final String BAR;

    static
    {
        FOO = 42;
        BAR = "Hello, World!";
    }
}

then the compiler will no longer hard code the values in the other classes that are using them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文