3

Assume we have a simple class:

public with sharing class SomeClass {

    public String property {
        get;
        set;
    } {
        property = 'Default Property Value';
    }

    public final String finalProperty {
        get;
        set { finalProperty = value; }
    } {
        finalProperty = 'Default Final Property Value';
    }

    public final String finalAutoProperty {
        get;
        set;
    } {
        finalAutoProperty = 'Default Final AutoProperty Value';
    }

}

Anonymous Execution

SomeClass instance = new SomeClass();
instance.property = 'New Property Value';
instance.finalProperty = 'New Final Property Value'; // Works
instance.finalAutoProperty = 'New Final AutoProperty Value'; // Fails with

System.FinalException: Final variable has already been initialized Class.SomeClass.__sfdc_finalAutoProperty

However, as @sfdcfox сorrectly noticed, neither instance.finalProperty = 'New Final Property Value'; nor instance.finalAutoProperty = 'New Final AutoProperty Value'; reassignments couldn't be compiled within another method giving:

Final members can only be assigned in their declaration, init blocks, or constructors

This behavior gives me questions because:

  1. final keyword ApexDocs doesn't mention that the final keyword affects the behavior of properties and the Apex Properties page doesn't mention the final keyword. But the final keyword does affect apex properties.
  2. Is it undocumented expected behavior or a new bug?
  3. Why it is possible to reassign the property value within anonymous execution via default setter, but not via auto-generated setter?
5
  • 1
    Possibly you've done something "wrong." I tested your second code block, and I get the expected error. Can you please provide a Short, Self Contained, Correct (Compilable), Example that compiles?
    – sfdcfox
    Commented Apr 26, 2021 at 19:24
  • Well, then, possibly I've done something wrong. I can't reproduce the behavior you describe. The final code block, how are you calling it? When I try to write a method that duplicates this, it works. Here's my example, for reference. gist.github.com/brianmfear/e2f3e54130eb97d754b586cc8960f772
    – sfdcfox
    Commented Apr 26, 2021 at 19:56
  • My bad. Actually, It was possible to reassign a final property value via its explicit setter from anonymous execution. So either I will rewrite the question, or delete it. Sorry for the wasted time. Commented Apr 26, 2021 at 20:00
  • 1
    Exec Anon is a bit "weird" sometimes, which might explain things. If you still want me to look, I'd be happy to, just include the exec anon code.
    – sfdcfox
    Commented Apr 26, 2021 at 20:02
  • @sfdcfox I've Updated the question, and I hope it still makes some sense. Commented Apr 26, 2021 at 20:22

1 Answer 1

3

If you don't provide a property for the final default getter setter property, it also runs just fine instead of "System.FinalException: Final variable has already been initialized".

Generally speaking, Exec Anon is weird, because it's basically a hack to the existing runtime. It doesn't allow classes that are nested, nor can you have static variables in those classes, etc, as if the entire code was wrapped in a class, but you can also intersperse methods and classes with executable code, as if it were not.

Also, you may want to read more about Execute Anonymous. It has a wide range of unusual rules that differ from normal gameplay. For example:

Unlike classes and triggers, anonymous blocks execute as the current user and can fail to compile if the code violates the user's object- and field-level permissions.

This is apparently one of those holes in the system. This behavior is clearly showing that the Exec Anon script is called as if it were executing in a constructor context, even though it allows DMLs (which are normally not allowed in a constructor or getter).

I can't say for certain if this is a bug, but this is definitely an Exec Anon exception to the normal rules for execution. If you're a prolific user of Exec Anon, you may very well find many strange and wonderful quirks hidden within.

However, as far as normal, compiled Apex code goes, you must always follow the prescribed directions as written in the documentation, or you will likely come across compilation errors, weird runtime behavior, etc.

1
  • Thank you for your reply. It is clear now that anonymous execution is full of weirdness. Apart from it, final keyword page doesn't mention properties at all (only does mention member variables). Also, Apex Properties page doesn't mention the final keyword. Commented Apr 26, 2021 at 21:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .