Reputation: 41
I'd like to be able to differentiate at runtime (presumably using reflection), between these two cases, where the former has a final field defined at initialization (i.e. a constant), and the latter defines it through the constructor.
class MyClass {
final int value = 42;
public MyClass() {
}
}
class MyClass {
final int value;
public MyClass() {
value = 42;
}
}
I've tried doing this by examining the Field's access flags and modifiers, but have not found anything relevant.
Is there a way to do this?
Upvotes: 2
Views: 76
Reputation: 70584
We can investigate this by disassembling the class file. If we compile
public class Test {
final int foo = 42;
final int bar;
Test() {
bar = 42;
}
}
and then disassemble it with javap -v Test.class
, we get:
final int foo;
descriptor: I
flags: (0x0010) ACC_FINAL
ConstantValue: int 42
final int bar;
descriptor: I
flags: (0x0010) ACC_FINAL
stackoverflow.Test();
descriptor: ()V
flags: (0x0000)
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #13 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 42
7: putfield #15 // Field foo:I
10: aload_0
11: bipush 42
13: putfield #17 // Field bar:I
16: return
As you can see, the information you seek is present in the ConstantValue attribute for use by the Java compiler. However, this attribute serves no purpose at runtime (the field value is set through putfield
irrespective of whether the value is constant), so the runtime does not read this information when it loads a class, and doesn't expose it through reflection. You would therefore need to parse the class file yourself, for instance using the new class file API introduced as a preview feature in JDK 22, or any other class file library.
Note that this assumes the field to be declared final, and its value to be a compile time constant expression.
Upvotes: 1
Reputation: 198391
No. One is just syntactic sugar for the other, so there's no actual difference at runtime that reflection can identify.
Upvotes: 0