简体   繁体   English

导入的java类中的public static final变量

[英]public static final variable in an imported java class

I happen to come across a Java code at my work place. 我碰巧在我的工作场所遇到过Java代码。 Here's the scenario: There are 2 classes - ClassA and ClassB . 这是场景:有两个类 - ClassAClassB

ClassA has nothing except 4 public static final string values inside it. ClassA中除了4个公共静态最终字符串值之外什么都没有。 Its purpose is to use those values like ClassA.variable (don't ask me why, it's not my code). 它的目的是使用像ClassA.variable这样的值(不要问我原因,这不是我的代码)。

ClassB imports ClassA . ClassB导入ClassA I edited the string values in ClassA and compiled it. 我在ClassA编辑了字符串值并对其进行了编译。 When I ran ClassB I could see it was using the old values - not the new values. 当我运行ClassB我可以看到它使用的是旧值 - 而不是新值。 I had to recompile ClassB to make it use new values from ClassA ! 我不得不重新编译ClassB以使其使用ClassA新值! (I had to recompile other classes that imports ClassA !) (我不得不重新编译导入ClassA其他类!)

Is this just because of JDK 1.6 or I should have known earlier to recompile ClassB also! 这只是因为JDK 1.6或我之前应该知道重新编译ClassB Enlighten me. 开导我。 :) :)

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. 如果类ClassA中的final变量的值恰好是编译时常量,则编译器可能已使用ClassA它们内联到类中,而不是生成运行时引用。 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. 在此示例中,编译器可能会将FOO的值合并到为Consumer生成的代码中,而不是生成等效的运行时引用。 If the value of FOO changes later on, you will have to re-compile Consumer in order to have it use the new value. 如果稍后更改FOO的值,则必须重新编译Consumer以使其使用新值。

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. 在这个例子中,内联值(这里:1)使编译器能够注意到,乘法没有区别,并且可以完全省略。

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). 如果更改A类中的值,则必须重新编译客户端(B类)。 To avoid such problems consider adding constants using an enum type, introduced in Java release 5.0. 为避免此类问题,请考虑使用Java 5.0版中引入的枚举类型添加常量。

Suppose ClassA looks like this: 假设ClassA看起来像这样:

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. 如果重新编译它,ClassB将继续使用旧值。 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: 如果您不希望每次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; }
}

Becuase now javac is unwilling to inline the constants. 因为现在javac不愿意内联常量。 Instead it will call the CONST(int) method when ClassA's static initializer runs. 相反,当ClassA的静态初始化程序运行时,它将调用CONST(int)方法。

Why are you trying to compile the classes individually? 你为什么要单独编译这些类?

Use a build system like maven or ant or just let your IDE do it. 使用像maven或ant这样的构建系统,或者让IDE执行它。

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. 唯一安全的做法是重新编译每个依赖于java类的java,这个java已经改变,直到每个可以生成的类都被重新编译。

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. 然后编译器将不再对使用它们的其他类中的值进行硬编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM