The Apex Master Class

When to Use the Static Keyword in Apex (Ep. 21)

4 min read

Subscribe on YouTube

Knowing What It Is Isn’t The Same As Knowing When To Use It

Last episode we worked out what static actually does. This episode is the more useful question: when should you reach for it, and when should you absolutely not?

Here’s the test I use, and it’s genuinely this simple:

Does this thing need to know anything about a specific instance? If no, make it static. If yes, don’t.

That’s it. Everything below is just working through what that means in practice.


When Static Is The Right Call

1. Utility methods that just transform inputs.

If a method takes some values, does something to them, and hands back a result without caring about any other state, it should be static.

Apex
public class StringUtils
{
    public static Boolean isValidEmail(String email)
    {
        return String.isNotBlank(email) && email.contains('@');
    }
}

//Nice and clean at the call site
if (StringUtils.isValidEmail(myEmail)) { ... }

Making that non-static would mean writing new StringUtils().isValidEmail(...) every time, which is pure ceremony for no benefit. Nobody wants that.

2. Constants.

Apex
public class Constants
{
    public static final String CLOSED_WON = 'Closed Won';
    public static final Integer MAX_RETRIES = 3;
}

The final keyword means it can’t be reassigned after it’s set. static final is the standard way to declare a constant, and the ALL_CAPS naming is a convention every developer will recognise instantly.

Do this instead of typing 'Closed Won' in fourteen places. When someone renames that stage, you’ll change one line rather than hunting through the whole org.

3. Flags that need to be shared across a transaction.

The trigger recursion guard from last episode is the classic:

Apex
public class TriggerControl
{
    public static Boolean hasAlreadyRun = false;
}

This one has to be static. If it were an instance variable, every new handler would get a fresh false and the guard would never guard anything.

4. Caching something expensive within a transaction.

Apex
public class SettingsService
{
    private static My_Setting__mdt cachedSetting;

    public static My_Setting__mdt getSetting()
    {
        if (cachedSetting == null)
        {
            cachedSetting = [SELECT Id, Value__c FROM My_Setting__mdt LIMIT 1];
        }
        return cachedSetting;
    }
}

Call that fifty times in a transaction, run one query. Very handy when you’re up against governor limits.


When Static Is The Wrong Call

1. Anything that represents a specific thing.

Our Computer class has a type and an amount of RAM. Those describe that computer. Make them static and every computer in your org instantly has the same RAM, which is a fun bug to debug.

Apex
public class Computer
{
    //RIGHT: each computer has its own
    private String computerType;

    //VERY WRONG: every computer shares one value
    private static String computerTypeStatic;
}

2. Anything you want to swap out in tests.

This is the big one, and it’s the reason experienced developers get twitchy about static.

Static methods are hard to mock. If your service class calls SomeOtherClass.doThing() directly, there’s no way to slide a fake in during a test. You’re stuck with the real one, whatever it does, including any callouts or queries it makes.

Instance methods can be swapped, because you control which instance gets handed in. This is a big part of what the separation of concerns series is about, and it’s why the Apex Common Library leans on instances so heavily.

3. Mutable shared state, for fun.

A static variable that half a dozen classes all write to is shared mutable state, and shared mutable state is where bugs go to breed. When something ends up with a value nobody expected, you now get to work out which of six classes did it. Use static for constants and flags, not as a convenient global scratchpad.


The Short Version

Use static for: utility methods, constants, transaction-wide flags, transaction-scoped caches.

Avoid static for: anything describing a specific object, anything you’ll want to mock in a test, and anything lots of classes will write to.

If you’re genuinely torn, default to non-static. Turning an instance method static later is a five second change. Untangling a static one that half your codebase depends on is considerably less fun.


What’s Next

That’s static covered from both directions. Next up is a run of four episodes on access modifiers, the keywords that decide who’s allowed to call what.

We start in the next episode with global, which is the one you should use the least and think about the hardest.

See you next time!


Get Coding With The Force Merch!!

We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.

Get Shirts Here!
Get Cups, Artwork, Coffee Cups, Bags, Masks and more here!


Check Out More Coding With The Force Stuff!

If you liked this post make sure to follow us on all our social media outlets to stay as up to date as possible with everything!

Youtube
Patreon
Github
Facebook
Twitter
Instagram


Salesforce Development Books I Recommend

Advanced Apex Programming
Salesforce Lightning Platform Enterprise Architecture
Mastering Salesforce DevOps

Good Non-SF Specific Development Books:

Clean Code
Clean Architecture