4

The documentation is confusing me, and I was hoping to get a little help. For the final KW it says seemingly contractory things:

**Final variables can only be assigned a value once,** either when you declare a variable or in initialization code. You must assign a value to it in one of these two places.


Static final **variables can be changed** in static initialization code or where defined.

**Member final variables can be changed** in initialization code blocks, constructors, or with other variable declarations.

So, I tested it out, and I get this error System.FinalException: Final variable has already been initialized Am I missing something or is the documentation off??

public class finalTester {

    public final String whereIsthis = 'in declaration';


    {
        system.debug('in initialization');
        system.debug('whereIsThis' + whereIsthis);
        whereIsthis = 'in Init block A';
        system.debug('whereIsThis' + whereIsthis);
        whereIsthis = 'in Init block B'; // bombs! - Final variable has already been defined
        system.debug('whereIsThis' + whereIsthis);
    }



    public finalTester(){
        system.debug('whereIsThis' + whereIsthis);
        whereIsthis = 'in constructor';

        system.debug('whereIsThis' + whereIsthis);
    whereIsthis = 'in constructor a';

        system.debug('whereIsThis' + whereIsthis);

    }

}

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_keywords_final.htm

1
  • It is interesting that this value is set at run-time. I had always imagined it worked more similarly to a C pre-processor directive. I might guess that the typical use in a language that uses classical inheritance would be to provide "read-only" properties that class extensions can access, but not change.
    – martin
    Commented Sep 6, 2015 at 7:29

2 Answers 2

6

If you don't give the variable an initial value when you declare it, you can assign it a value at a later time. That's why the documentation says it can be changed.

In your code, you should be able to do the following:

public class finalTester {

public final String whereIsthis;

{

   whereIsthis = 'Static Initialization Code';
   system.debug('whereIsThis' + whereIsthis);
}

   {    
      return whereIsthis;
   }

}

This was successfully tested in Dev Console running as anonymous Apex.

3
  • 1
    I agree, although the wording is confusing. They probably should just stick with saying "assigned" or "set". The word "change" seems to imply more than the change from a null value.
    – martin
    Commented Sep 6, 2015 at 8:40
  • i ran that test earlier, and then i after the debug statement, i did whereisThis = 'number 2 init'; and that failed. i think what it means is that you can set it once in the initiaialization block if it's not set, or if potentially in the contstuctor too. thanks guys. Commented Sep 6, 2015 at 17:14
  • Yes, you can only set it once, either when declared, at some time later in initialization or elsewhere. I couldn't seem to change it in a constructor, but I'm also not an advanced coder like some others here who'd probably know how to do it in a snap. Inside of a constructor, unless it's passed in, it would appear as a private variable, not as public. Using this.whereisThis works to change it, but I had some syntax difficulties with the full code, so didn't post it.
    – crmprogdev
    Commented Sep 6, 2015 at 17:29
1

The error you get is obvious. The final variable you used in your code is member variable and thus can be assigned value only either at declaration or in constructor.

You assigned your final variable a value while declaring it. So assigning a value in another initialization (anonymous) block is illegal and hence the error.

Hope it helps.

You must log in to answer this question.

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