Perhaps I need to be more specific.
I'm trying to do some simple source-code analysis, and I need to know whether a field is a constant variable because, in conjunction with its value, whether a field is a constant variable potentially alters the call graph. For example:
public class C {
staticint v = 0;
static final int c = 0;
static void foo(byte b) { System.out.println("byte"); }
static void foo(long i) { System.out.println("long"); }
public static void main(String[] args) {
foo(true ? v : (byte)(0));
foo(true ? c : (byte)(0));
}
}
Despite the fact that the values of both "v" and "c" are zero, this will print:
long
byte
In the first call, the result type of the ternary operator is "long" because the second and third operands undergo numeric promotion, since "v" is not a compile-time constant. In the second call, the result type of the ternary operator is "byte" because the second operand undergoes a narrowing conversion, since "c" is a compile-time constant and its value is losslessly convertible to "byte".
So, whether a field is a constant variable potentially affects my analysis, and I therefore need to determine whether a field (for which no source code may be available) is a constant variable.
> Reflection will do that for you.
For a field to be a constant variable, it must be both final and initialized with a compile-time constant expression. Reflection can tell me the first part, but not the second.
For example, consider the following field declaration:
public static final String s = "Hello World!";
The field "s" is a constant variable. However, if I amend this a bit:
public static final String s = "Hello World!".intern();
Now the field "s" is no longer a constant variable, because its initializer is no longer a compile-time constant expression.
> For a field to be a constant variable, it must be
> both final and initialized with a compile-time
> constant expression.
D'oh! Yeah, I was just thinking of the static / final flags.
A constant-valued expression is denoted in the classfile by the ConstantValue attribute in the field definition. http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1405
Once the class is loaded into memory, that information is no longer useful. Any class that references the field will have that constant value copied into its own constant pool. So it makes sense that reflection won't give you that info.
You'll have to look at the classfile itself, using a tool such as [url=http://jakarta.apache.org/bcel/]BCEL[/url]. I suspect, if you're doing any heavyweight analysis of classes, you'll want to go down that route anyway. You can probably find some good examples of its use in the [url=http://findbugs.sourceforge.net/]FindBugs[/url] project.
> You'll have to look at the classfile itself, using a
> tool such as
> [url=http://jakarta.apache.org/bcel/]BCEL[/url].
Yeah, I was afraid of that. I was hoping there would be something easier that I just overlooked, like the [url=http://java.sun.com/javase/6/docs/api/javax/lang/model/element/VariableElement.html#getConstantValue()]mechanism[/url] in the 1.6 API.
I'll probably take another look at the BCEL, though, thanks.