[SalesForce] Need help understanding get/set methods, weird behavior

I came across this question somewhere which has been kept me engaged thinking why it is behaving this way.

Lets say I have an apex class:

public class TestController {
    public String  myString{get;set;}

    public String getStringmethod1()
    {
        System.debug('myString'+myString);
        return myString;
    }

    public String getStringmethod2()
    {
        System.debug('myString'+myString);
        if(myString == null)
            myString = 'Something';
        return myString;
    }

    public String getStringmethod3()
    {
        System.debug('myString'+myString);
        myString += 'Special';
        return mySTring;
    }
}

And a visualforce page:

<apex:page controller="TestController">
    {!myString}, {!Stringmethod1}, {!Stringmethod2}, {!myString}, {!Stringmethod3}, {!myString}
</apex:page>

I was expecting the output to be

, , Something, Something, SomethingSpecial, SomethingSpecial

But the output is:

, , Something, , SomethingSpecial,

So even after, inside the get methods, setting the myString property value, whenever I try to access the property directly again, I am getting null value. Its not reflecting the change done in getter method.

But again, when I am accessing the same myString property inside a getter method, I am seeing that its holding the changed value, not null anymore.

I am sure I am failing to understand the behavior of getter methods. Could anyone please explain this behavior? Whats happening here?

Best Answer

I have observed Apex properties - a convenient way to implement getters and setters - only being referenced once even though the Visualforce includes multiple references. It seems like there is some caching of values being done but I don't remember seeing any documentation that guarantees that behaviour. So if you want to check the same in your code please do the following changes and check the debug log : -

Apex class

public String  myString{
    get{
        System.debug('-----'+myString);
        return myString;
    }
    set;
}

In Your VF page made below changes :

<apex:page controller="TestController">
   <!-- {!myString}, {!Stringmethod1}, {!Stringmethod2}, {!myString}, {!Stringmethod3}, {!myString}-->
   {!myString},{!myString},{!myString}//make the change by only calling "myString" thrice 
</apex:page>

Now if you open the debug log and check it will only calls once in spite of calling the same thrice from the page.

The first time "myString" is referenced in Visualforce Page is done and the value assigned to the field. On subsequent references the field value is returned without the assignment being done. An advantage of this pattern over setting the properties in the constructor is that if the set of properties referenced varies depending on conditional page logic then only the initialization for the properties that are actually referenced is done so avoiding the waste of calculating the unreferenced properties. The approach works equally well for static fields.

Related Topic