ForsakenCubist
ForsakenCubist

Reputation: 41

Is there a way to tell at runtime whether a Java final field is a constant?

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

Answers (2)

meriton
meriton

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

Louis Wasserman
Louis Wasserman

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

Related Questions