public static final variable in an imported java class

笑着哭i 提交于 2019-12-18 14:19:14

问题


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. :)


回答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.




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/1693091/public-static-final-variable-in-an-imported-java-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!