36

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?

3 Answers 3

37

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.

24

In theory, you use static initializers for the scenario that Jesse described - as the de facto constructor logic in a static method utility class.

In practice, I almost never use them in Apex, because they incur a script statement cost with every request that executes any code in the class with the static initializer. Your utility classes have to be pretty narrow in scope, or unified in their prerequisite state, for blanket static initialization logic make sense.

It's a common misconception (from Java, .NET etc) that Apex static data outlives the request. It doesn't; static still (like everything else stateful) dies at the end of the request. So while in Java a static initializer will typically only run once in your entire VM lifetime, in Apex it will run up to once per request.

So you can use them for constructor-style logic, but you should prefer lazy initialization (in both static and instance initializers) if that logic is not needed every time you run any method in the class. I prefer lazy initialization almost 100% of the time in Apex.

3
  • 3
    This is an excellent point as well. Great thought there! Commented Feb 18, 2013 at 13:13
  • Agree, static intializers can be very hard to debug and predict at times, due to them really going off based on the class coupling and the way the platform loads classes. You don't really get the same sense of control as you do with lazy initialisation. Commented Sep 7, 2013 at 20:08
  • 4
    But, lazy initialization has it's own cost, too, because you have to check if(!init) { initialize(); } ...; if the utility is called 200 times in a trigger, and the static block was only 10 lines of code, then you've incurred an extra 190 if statements. Besides, in the near future, we'll no longer have script statement limits, so the argument is largely moot.
    – sfdcfox
    Commented Sep 7, 2013 at 21:43
-3
public class TestStaticInstanceConstructor {
    {
        System.debug('This is instance block.');
    }
    {
        System.debug('This is instance block-2.');
    }
    static
    {
        System.debug('This is static block.');
    }
    static
    {
        System.debug('This is static block-2.');
    }
    public TestStaticInstanceConstructor()
    {
        System.debug('This is constructor block.');
    }
    public void m1()
    {
        System.debug('This is method m1().');
    }
    public void m2()
    {
        TestStaticInstanceConstructor obj = new TestStaticInstanceConstructor();
        obj.m1();
        System.debug('This is method m2().');
    }
}

Calling Apex Class :

TestStaticInstanceConstructor obj = new TestStaticInstanceConstructor();

obj.m2();

enter image description here

You must log in to answer this question.

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