When should a static intializer be used?

I come from a C# background, so I was a bit confused when I encountered a static intializer today:

public static final Integer MAX_VALUE; // in days
static{
     Common_Config__c config = Common_Config__c.getInstance();
     MAX_VALUE = (config.Max_Value__c == null ) ? 5 : Integer.valueOf( config.Max_Value__c);
}

I did find a reference to the static initializer here.

What are the use cases for the static initializer? Should these code blocks be used sparingly for initialization of final fields/properties only?

Answer

Taken from the documentation you linked above:

The instance initialization code in a class is executed every time an
object is instantiated from that class. These code blocks run before
the constructor.

If you do not want to write your own constructor for a class, you can
use an instance initialization code block to initialize instance
variables. However, most of the time you should either give the
variable a default value or use the body of a constructor to do
initialization and not use instance initialization code.

Similar to other static code, a static initialization code block is
only initialized once on the first use of the class.

A perfect use case for this would be a utility class. Let’s take a look at some code:

public class DiscountUtility{
    public static final Double DISCOUNT;
    static{
        Custom_Setting_Config__c settings = Custom_Setting_Config__c.getInstance();
        DISCOUNT = settings.Discount__c;
    }

    public static Double applyDiscount(Double value) {
        return value - DISCOUNT;
    }
}

You could then use this like:

public class StoreCheckoutController{
    public Double cartAmount{get;set;}

    public void finalizeCheckout(){
        if(condition){
            DiscountUtility.applyDiscount(cartAmount);
        }
    }
}

Notice how I am using a static method on the utility class and I never initialize the DiscountUtility class. Without initializing it, I would never be able to set the custom setting value (assuming the discount can change from environment to environment). It does have a limited use case. Normally, you would be able to just use a constructor. If you were creating an actual instance of a class, you could simply write the code like:

public class DiscountUtility{
    public static final Double DISCOUNT;
    public DiscountUtility(){
        Custom_Setting_Config__c settings = Custom_Setting_Config__c.getInstance();
        DISCOUNT = settings.Discount__c;
    }

    public Double applyDiscount(Double value) {
        return value - DISCOUNT;
    }
}

Then all you would need to do to populate that amount be would:

public class StoreCheckoutController{
    public Double cartAmount{get;set;}

    public void finalizeCheckout(){
        if(condition){
            DiscountUtility util = new DiscountUtility();
            util.applyDiscount(cartAmount);
        }
    }
}

The difference is the first situation requires no instance of the class to even be created and thus is much more efficient for a static utility class.


As @jkraybill pointed out, this type of scenario may not be the most efficient for the scenario I described above. From the documentation:

Static variables are only static within the scope of the request. They
are not static across the server, or across the entire organization.

as well as from the documentation on Custom Settings:

Custom settings are similar to custom objects and enable application
developers to create custom sets of data, as well as create and
associate custom data for an organization, profile, or specific user.
All custom settings data is exposed in the application cache, which
enables efficient access without the cost of repeated queries to the
database. This data can then be used by formula fields, validation
rules, Apex, and the SOAP API.

For instance, say your utility class looked like:

public class DiscountUtility{
    public static Double discount{
    get{
        if(discount == null){
            Custom_Setting_Config__c settings = Custom_Setting_Config__c.getInstance();
            discount = settings.Discount__c;
        }
        return discount;
    }
        set;
    }

    public static Double applyDiscount(Double value) {
        return value - DISCOUNT;
    }
    public static Double removeTwenty(Double value){
        return value = 20;
    }
}

Writing your class like this, you could call DiscountUtility.applyDiscount(value); and your class would properly set the discount, but you could also call DiscountUtility.removeTwenty(value) at a separate time and the Custom Setting would never have to even be called. This allows you to only initialize it when needed.

So, basically just keep in mind exactly what you need when you create these classes. They wouldn’t be a big performance hit with the scenario described above, but it all adds up over time. Need to keep all of this stuff in mind.

Attribution
Source : Link , Question Author : Brad Ullery , Answer Author : Vivek M. Chawla

Leave a Comment