public static final variable in an imported java class
Asked Answered
P

5

18

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

Ptyalin answered 7/11, 2009 at 13:53 Comment(0)
L
23

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.

Loehr answered 7/11, 2009 at 14:10 Comment(2)
so, you're saying public static final is compile time constant? didn't know that. thought it was just a constant and can't be modified in runtime! thanks for your help.Ptyalin
Good anwser. If you want to see that the variable is being inlined, you can use javap to see how the class was compiled, e.g. "javap -c Flags".Papyraceous
W
3

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.

Weiland answered 7/11, 2009 at 14:19 Comment(0)
T
3

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.

Tabshey answered 22/8, 2012 at 1:45 Comment(0)
A
2

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.

Axilla answered 7/11, 2009 at 15:37 Comment(1)
One or other of the classes may not be under your control.Agonist
G
2

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.

Gerita answered 7/11, 2009 at 20:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.